[OSCCTF Final 2022] – Admin?

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?!?!?!}

Leave a Reply

Your email address will not be published. Required fields are marked *