From ec465bcefd945f126729787bc9f41ba39712bc29 Mon Sep 17 00:00:00 2001 From: Steliyan Syarov Date: Tue, 19 Nov 2019 15:47:53 +0000 Subject: [PATCH] Added a asis2019 writeup --- writeups/icecrax/asis2019.md | 204 +++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 writeups/icecrax/asis2019.md diff --git a/writeups/icecrax/asis2019.md b/writeups/icecrax/asis2019.md new file mode 100644 index 0000000..1e69fca --- /dev/null +++ b/writeups/icecrax/asis2019.md @@ -0,0 +1,204 @@ +# ASIS 2019 +## web: protected-area (unsolved) +A web page is given which printed the content of a file from a directory to the html of the page. + +First I looked up the source file of the webpage. It was importing the following JS script: +``` javascript + var file_check = function(file){ + $.ajax({ + url: '/check_perm/readable/', + data: {'file': file} + }).done(function(data){ + if (data == "True") { + file_read(file) + }else{ + console.log('fail') + } + }) + } + + var file_read = function(file){ + $.ajax({ + url: '/read_file/', + data: {'file': file} + }).done(function(data){ + update_page(data) + }) + return + } + + var update_page = function(text){ + $("#t").append(text) + } + + $(document).ready(function() { + console.log("ready!"); + file_check('public.txt'); + }); +``` +The first command `file_check` executed like this `http://66.172.33.148:8008/check_perm/readable/?file=public.txt` gives either `True` or `0`, depending if the file exists. If the file is not found it prints in the console `fail`. If it exists its being passed to the command `file_read`. + +The second command `file_read` executed like this `http://66.172.33.148:8008/read_file/?file=public.txt` opens the file. It then passes itas an argument to `update_page`. If the file is not found `security` or `500` is being printed. + +The trird command `update_page` takes the passed text and appends to the DOM. + +I tried path triversal by encoding the ../ in UTF-8, by replacing ../ with ..././ or ..;/, but it seems the dots and slash are still being replace, bacause `http://66.172.33.148:8008/read_file/?file=../../../public.txt` is being interpreted the same as `http://66.172.33.148:8008/read_file/?file=public.txt` + +There was also `private.txt` file in the same directory as `public.txt` with the content `lol haha`. + +I tried to mess up with the console: +`update_page("")` executes the script and the pop up shows, hints towards an XSS attack. + +I tried looking for a way to list the directory via javascript +``` javascript +const testFolder = './public.txt'; +const fs = require('fs'); + +fs.readdir(testFolder, (err, files) => { + files.forEach(file => { + console.log(file); + }); +}); +``` + +## web: cursed-app (unsolved) + +An `cursed_app.elf` file is given. +The description of the challenge stated `If we want to say 100, should we start at 1 and count until 100?` and `sha256(flag) = dd791346264fc02ddcd2466b9e8b2b2bba8057d61fbbc824d25c7957c127250d` was given. + +First I tried to brute force the hash using variuos websites. No luck there. +Hexdumping the file reveals some readable strings: `hexdump -C cursed_app.elf`. +After that I found a more useful command `strings`, which filters only the readable strings. +Intressting segment was +``` +[]A\A]A^A_ +please locate license file, run ./app license_key +Congratz! You got the correct flag!! +Bummer! You got the wrong flag!! +;*3$" +``` +So I tried executing file. If it's being run without arguments the first message is printed: `please locate license file, run ./app license_key`, if a file is specified it prited `Bummer! You got the wrong flag!!`. + +So clearly the program was reading the flag file and computing and comparing the string. + +I tried `strace` and `ltrace` to understand better what functions and libraries are being called. + +Using `objdump -d cursed_app.elf` showed me that there was no main function. + +I then installed `Hopper`, which is a reverse engineering tool that lets me disassemble, decompile and debug the applications. With it I tried to undestand the execution pattern and to find out how and when `Congratz!` is being printed. I figured out that after opening the flag/key file 59 characters are being read and most likely compared (although no cmp function was found). Those 59 chars could be brute forced and encrypted with `sha256` and then compared with the given solution in the description. A brute force of 59 chars seems impossible. + +## web: Golden_Delicios (unsolved) + + A `.sage` file is given, containing the following python scrypt. And at the bottom of it, there were the results of the print function commented. + + ``` python + #!/usr/local/bin/sage + +from sage.all import * +from secret import * + +print '(A_1, B_1) =', (A_1, B_1) +print '(A_2, B_2) =', (A_2, B_2) + +E_1 = EllipticCurve(Zmod(n_1), [A_1, B_1]) +E_2 = EllipticCurve(Zmod(n_2), [A_2, B_2]) + +d_1 = int(flag[:len(flag)/2].encode('hex'), 16) +d_2 = int(flag[len(flag)/2:].encode('hex'), 16) + +assert d_1 < n_1 and d_2 < n_2 and n_1 * n_2 % 2 == 1 + +print 'P_1 =', P_1 +print 'P_2 =', P_2 + +Q_1 = d_1 * P_1 +Q_2 = d_2 * P_2 + +print 'Q_1 =', Q_1 +print 'Q_2 =', Q_2 + ``` + +The EllipticCurve function was interesting. After googling it I found out that there exists a very popular algorithm in cryptography for encrypting public keys. +The formula for an elliptic curve is as follows: `y^2=x^3+ax+b` and the parameters corresponded to those used in the script, so I guessed I was on the right track. +After that I spent time reading wikipedia articles and watching youtube youtibe videos explaining it. But after some time trying to understand it, I gave up... I decided to concetrate more on the other challenges. + +## web: Bit_game (unsolved) +The following script was given, together with a text file containing the resulting H and enc variables: +```python +import random +from Crypto.Util.number import * +#from flag import flag + +def gen_rand(nbit, l): + R = [] + while True: + r = random.randint(0, nbit-1) + if r not in R: + R.append(r) + if len(R) == l: + break + R.sort() + rbit = '1' + for i in range(l-1): + rbit += (R[i+1] - R[i] - 1) * '0' + '1' + rbit += (nbit - R[-1] - 1) * '0' + return int(rbit, 2) + +def genkey(p, l): + n = len(bin(p)[2:]) + f, skey = gen_rand(n, l), gen_rand(n, l) + pkey = f * inverse(skey, p) % p + return (p, pkey), skey + +def encrypt(msg, pkey): + p, g = pkey + msg, enc, n = bytes_to_long(msg), [], len(bin(p)[2:]) + print(n) + for b in bin(msg)[2:]: + s, t = gen_rand(n, l), gen_rand(n, l) + c = (s * g + t) % p + if b == '0': + enc.append((c, t)) + else: + enc.append((p-c, t)) + return enc + +p = 862718293348820473429344482784628181556388621521298319395315527974911 +l = 5 + +pkey, skey = genkey(p, l) +enc = encrypt(flag, pkey) +H = pkey[1] ** 2 % p +print('H =', H) +print('enc =', enc) +``` +I think I was on the right track on this one. Sadly this challenge was released on the last day and I didn't get the opportunity to spent more time on it. The CTF was over and the challenge was left unsolved... +Nevertheless that is what I managed to put together: + +``` python +#enc = [...] +flag = '' +l = 5 +p = 862718293348820473429344482784628181556388621521298319395315527974911 +r = 738852413361336333302472130287418462898049591392380573449381971565615 +for i in range(len(enc)): + c = enc[i][0] + print("c: ",c) + t = enc[i][1] + print("t: ",t) + deca = ((-c-t) * r) % p + print("deca: ",deca) + b = bin(deca)[2:].count('1') + print("b: ", b) + if b == l: + flag += '0' + continue + deca = ((c-t) * r) % p + print("deca: ",deca) + a = bin(deca)[2:].count('1') + print("a: ",a) + if a == l: + flag += '1' + continue +print(hex(int(flag,2))[2:-1].decode('hex')) +``` \ No newline at end of file -- 2.43.0