app.py
#!/usr/bin/env python3 from Crypto.Util.Padding import pad, unpad from Crypto.Cipher import AES from Crypto.Random import get_random_bytes import binascii from flag import FLAG BLOCKSIZE = 16 def generate_body(key: bytes) -> dict: “”” Generate encrypted body to give to user “”” pt = ‘u=user’ iv = get_random_bytes(16) cipher = AES.new(key, AES.MODE_CBC, iv = iv) ct_hex = cipher.encrypt(pad(pt.encode(), block_size=BLOCKSIZE)).hex() return {“iv_hex” : iv.hex(), “ct_hex” : ct_hex} def check_body(ct_hex: str, iv_hex: str, key: bytes) -> str: try: cipher = AES.new(key, AES.MODE_CBC, iv = binascii.unhexlify(iv_hex)) pt_padded = cipher.decrypt(binascii.unhexlify(ct_hex)) pt = unpad(pt_padded, block_size=BLOCKSIZE).decode() except Exception: return “”” Welcome user! Unfortunately you are NOT an admin so no flags for you! “”” if pt == “u=admin”: return “”” ππ₯³ππ₯³ππ₯³ππ₯³ππ₯³ππ₯³ππ₯³ππ₯³ππ₯³ π₯³ Welcome Admin! π₯³ ππ₯³ππ₯³ππ₯³ππ₯³ππ₯³ππ₯³ππ₯³ππ₯³ππ₯³ FLAG: {flag} “””.format(flag = FLAG) name = pt[2:] return “”” Welcome {name}! Unfortunately you are NOT an admin so no flags for you! “””.format(name = name) def loop(key: bytes): while True: print(“YOUR INITIAL VECTOR: “, end=””) user_iv_hex = input() print(“YOU ENCRYPTED BODY: “, end=””) user_ct_hex = input() print(check_body(user_ct_hex, user_iv_hex, key)) print(“Continue? Y/N: “, end=””) c = input() if not c == ‘Y’: break def main(): key = get_random_bytes(BLOCKSIZE) gen_iv_ct = generate_body(key) iv_hex = gen_iv_ct[‘iv_hex’] ct_hex = gen_iv_ct[‘ct_hex’] print(“”” π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄ π΄ Welcome to our Bug Bounty! π΄ π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄π΄ “””) print(“Here are some encrypted texts for you!”, end=”\n\n”) print(“INTIAL VECTOR:”, iv_hex) print(“ENCRYPTED BODY:”, ct_hex) print(“”” Try modifying the encrypted text we gave you and see if you can login as the admin! “””) loop(key) if __name__ == “__main__”: main() |
Pada soal ini, kita diberikan initial value serta hasil enkripsi metode AES CBC, dengan plaintext βu=userβ. Tugas kita adalah mengirimkan initial value dan hasil enkripsi kita sendiri, yang ketika didekrip akan menghasilkan βu=adminβ, dan kita akan diberikan flag nya. Tentu kita tidak bisa asal membuat enkripsinya karena kita tidak diberikan key nya yang bernilai random.
Untuk menyelesaikannya, kita dapat menggunakan metode byte flipping. Singkatnya bit flipping attack adalah serangan pada AES CBC untuk memanipulasi plaintext dengan cara memainkan bit-bit ciphertext semulanya. Dengan informasi IV dan Ciphertext βu=userβ yang ada, kita dapat mengubah beberapa byte IV agar Ciphertext yang sama akan bernilai βu=adminβ ketika didecrypt. Selengkapnya mengenai serangan ini dapat dibaca di https://resources.infosecinstitute.com/topic/cbc-byte-flipping-attack-101-approach/
Perubahannya dimulai dari index 2 dimana βuβ dari u=user diubah menjadi βaβ dari u=admin. Lalu index 3 dimana βsβ dari u=user diubah menjadi d dari u=admin. Dan seterusnya. Lalu bagaimana untuk index ke 6 βnβ dari u=admin, sedangkan u=user hanya mentok di index 5? Karena plaintext awalnya diberlakukan padding, maka karakter padding itulah yang harus diubah menjadi βnβ.
Satu lagi, karena u=user dan u=admin memiliki panjang yang berbeda, maka karakter padding yang digunakan juga akan berbeda (padding untuk u=user adalah \n sedangkan untuk u=admin adalah \t). Karena itu, semua padding u=user juga harus diganti menjadi padding u=admin. Kalau tidak, akan muncul ValueError: PKCS#7 padding is incorrect.
Mappingan perubahannya kira-kira seperti ini
ivbaru=ivlama
userpad = pad(b”u=user”, 16)[-1]#userpaddingchar
adminpad = pad(b”u=admin”, 16)[-1]#adminpaddingchar
ivbaru[2]= iv[2] ^ ord(‘u’) ^ ord(‘a’)
ivbaru[3]= iv[3] ^ ord(‘s’) ^ ord(‘d’)
ivbaru[4]= iv[4] ^ ord(‘e’) ^ ord(‘m’)
ivbaru[5]= iv[5] ^ ord(‘r’) ^ ord(‘i’)
ivbaru[6]= iv[6] ^ userpad ^ ord(‘n’)
ivbaru[7]= iv[7] ^ userpad ^ adminpad
ivbaru[8]= iv[8] ^ userpad ^ adminpad
ivbaru[9]= iv[9] ^ userpad ^ adminpad
ivbaru[10]= iv[10] ^ userpad ^ adminpad
ivbaru[11]= iv[11] ^ userpad ^ adminpad
ivbaru[12]= iv[12] ^ userpad ^ adminpad
ivbaru[13]= iv[13] ^ userpad ^ adminpad
ivbaru[14]= iv[14] ^ userpad ^ adminpad
ivbaru[15]= iv[15] ^ userpad ^ adminpad
kirim(ivbaru, ciphertextlama)
Solve.py
#!/usr/bin/env python3 from Crypto.Util.Padding import pad, unpad from Crypto.Cipher import AES from Crypto.Random import get_random_bytes from Crypto.Util.number import * from pwn import * r = remote(‘128.199.210.141’, 4246) r.recvuntil(b’INTIAL VECTOR: ‘) iv_hex = r.recvline().strip().decode() r.recvuntil(b’ENCRYPTED BODY: ‘) ct_hex = r.recvline().strip().decode() print(iv_hex) print(ct_hex) iv = binascii.unhexlify(iv_hex) print(iv) iv= iv[:2] + long_to_bytes(iv[2] ^ ord(‘u’) ^ ord(‘a’)) + iv[2+1:] iv= iv[:3] + long_to_bytes(iv[3] ^ ord(‘s’) ^ ord(‘d’)) + iv[3+1:] iv= iv[:4] + long_to_bytes(iv[4] ^ ord(‘e’) ^ ord(‘m’)) + iv[4+1:] iv= iv[:5] + long_to_bytes(iv[5] ^ ord(‘r’) ^ ord(‘i’)) + iv[5+1:] userpad = pad(b”u=user”, 16)[-1]#userpaddingchar adminpad = pad(b”u=admin”, 16)[-1]#adminpaddingchar iv= iv[:6] + long_to_bytes(iv[6] ^ userpad ^ ord(‘n’)) + iv[6+1:] iv= iv[:7] + long_to_bytes(iv[7] ^ userpad ^ adminpad) + iv[7+1:] iv= iv[:8] + long_to_bytes(iv[8] ^ userpad ^ adminpad) + iv[8+1:] iv= iv[:9] + long_to_bytes(iv[9] ^ userpad ^ adminpad) + iv[9+1:] iv= iv[:10] + long_to_bytes(iv[10] ^ userpad ^ adminpad) + iv[10+1:] iv= iv[:11] + long_to_bytes(iv[11] ^ userpad ^ adminpad) + iv[11+1:] iv= iv[:12] + long_to_bytes(iv[12] ^ userpad ^ adminpad) + iv[12+1:] iv= iv[:13] + long_to_bytes(iv[13] ^ userpad ^ adminpad) + iv[13+1:] iv= iv[:14] + long_to_bytes(iv[14] ^ userpad ^ adminpad) + iv[14+1:] iv= iv[:15] + long_to_bytes(iv[15] ^ userpad ^ adminpad) + iv[15+1:] print(userpad) print(adminpad) iv = iv.hex() r.recvuntil(b’YOUR INITIAL VECTOR: ‘) r.sendline(iv.encode()) r.recvuntil(b’YOU ENCRYPTED BODY: ‘) r.sendline(ct_hex.encode()) r.interactive() |
Output
FLAG=OSC2022{w4iT_tH3_iV_c4N_B_u53d_t0_m4nIpvL4t3_tH3_pL41nT3xT_t0_4dm1n?!?!?!}