この大会は2019/5/18 10:00(JST)~2019/5/20 10:00(JST)に開催されました。
今回もチームで参戦。結果は1111点で405チーム中46位でした。
自分で解けた問題をWriteupとして書いておきます。
welcome (Misc)
Telegramに入ったら、メッセージにフラグが書いてあった。
RCTF{Welcome_To_RCTF2019}
baby_crypto (Crypto)
サーバ処理は以下のようになっている。
key: ランダム16バイト iv : ランダム16バイト salt: key username: a-zで5文字以上10文字以下で指定 password: a-zで5文字以上10文字以下で指定 cookie: admin:0;username:[username];password:[password] hv : salt + cookie のsha1 hv_hex : salt + cookie のsha1(hex) cookie_padded: cookieのpadding iv + cookie_padded暗号 + hvのhexを表示 cookie入力 復号後、以下の処理 ・salt + cookieのsha1が一致しているかをチェック ・;区切りで各値を取り、adminの値が1の場合、フラグを表示
cookieのデータの末尾に";admin:1"が入っているデータでハッシュがわかるものをHash Length Extension Attackからハッシュと、対応するデータを求める。その際saltはkeyなので、長さは16バイトと分かっている。さらにそのデータに対する暗号文をCBC Oracle Padding Attackで生成する。
import socket import hashpumpy import binascii def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) def str_xor(s1, s2): return ''.join(chr(ord(a) ^ ord(b)) for a, b in zip(s1, s2)) def pad(s): l = 16 - len(s) % 16 return s + chr(l) * l s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('45.76.208.70', 20000)) data = recvuntil(s, ':\n').rstrip() print data username = 'admin' print username s.sendall(username + '\n') data = recvuntil(s, ':\n').rstrip() print data password = 'admin' print password s.sendall(password + '\n') data = recvuntil(s, '\n').rstrip() print data data = recvuntil(s, '\n').rstrip() print data mac = data[-40:] base_str = 'admin:0;username:' + username + ';password:' + password h, d = hashpumpy.hashpump(mac, base_str, ';admin:1', 16) pad_d = pad(d) plain_blocks = [pad_d[i:i+16] for i in range(0, len(pad_d), 16)] c = ['\x00'*16] * 5 for i in range(4, 0, -1): key = '' for j in range(16): for code in range(256): try_iv = 'X' * (15 - len(key)) + chr(code) + str_xor(key, chr(j+1)*j) cookie = try_iv + c[i] + 'h' * 20 cookie = binascii.hexlify(cookie) data = recvuntil(s, ':\n').rstrip() print data print cookie s.sendall(cookie + '\n') data = recvuntil(s, '\n').rstrip() print data if data not in 'Invalid padding': key = chr(code ^ (j+1)) + key break c[i-1] = str_xor(plain_blocks[i-1], key) cookie = binascii.hexlify(''.join(c)) + h data = recvuntil(s, ':\n').rstrip() print data print cookie s.sendall(cookie + '\n') data = recvuntil(s, '\n').rstrip() print data
実行結果は以下の通り。
Input username: admin Input password: admin Your cookie: 5633290bdd244501f1f689a3bae19fb112b83db0334df13c985d0bba608e6c72862632b10bbd4f2139c57e4b9830079d3f26d77ae8b9e8659e109fc5ed08d42ac06c663a4e1ad2282392ea588611eb610150cc2d Input your cookie: 58585858585858585858585858585800000000000000000000000000000000006868686868686868686868686868686868686868 Invalid padding : Input your cookie: e965ebc63e74c43fd695d41737eaaf6a8d5f4d8e991c614853cfd3a37ebe04cb6868686868686868686868686868686868686868 Invalid padding Input your cookie: ea65ebc63e74c43fd695d41737eaaf6a8d5f4d8e991c614853cfd3a37ebe04cb6868686868686868686868686868686868686868 Invalid hash Input your cookie: 9b1196bf405ee414b3f6a175499bd21f8d5f4d8e991c614853cfd3a37ebe04cb6cba5321c2052667775d12198cb964e4932b6e3035a82c1e7b587659aceacff000000000000000000000000000000000803eb104472c0600959f2aaccc645871fabbdbf8 Your flag: RCTF{f2c519ea-567b-41d1-9db8-033f058b4e3e}
RCTF{f2c519ea-567b-41d1-9db8-033f058b4e3e}