easy AES

Deskripsi

Attack on AES OFB

Author: prajnapras19

nc ctf-gemastik.ub.ac.id 10002

Kita diberikan sebuah service dan source code dari service tersebut.

chall.py

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Util.number import bytes_to_long, long_to_bytes
import os

key = os.urandom(AES.key_size[0])
iv = os.urandom(AES.block_size)
secret = bytes_to_long(os.urandom(128))

def encrypt(pt):
    bytes_pt = long_to_bytes(pt)
    cipher = AES.new(key, AES.MODE_OFB, iv)
    padded_pt = pad(bytes_pt, AES.block_size)
    return bytes_to_long(cipher.encrypt(padded_pt))

def menu():
    print('===== Menu =====')
    print('1. Encrypt')
    print('2. Get encrypted secret')
    print('3. Get flag')
    print('4. Exit')
    choice = int(input('> '))
    return choice

def get_flag():
    res = int(input('secret: '))
    if secret == res:
        os.system('cat flag.txt')
        print()

while True:
    try:
        choice = menu()
        if choice == 1:
            pt = int(input('plaintext = '))
            ciphertext = encrypt(pt)
            print(f'{ciphertext = }')
        if choice == 2:
            ciphertext = encrypt(secret)
            print(f'{ciphertext = }')
        if choice == 3:
            get_flag()
            break
        if choice == 4:
            break
    except:
        print('something error happened.')
        break

print('bye.')

Berikut tampilannya apabila dijalankan.

Pada soal ini, terdapat sebuah implementasi AES dengan mode OFB yang kelihatannya normal-normal saja. Lalu di mana vuln-nya? Setelah membaca berbagai sumber untuk memahami mode operasi OFB, saya jadi memahami bahwa OFB ini intinya adalah iv yang di-enkripsi berkali-kali (sesuai jumlah block), lalu hasil enkripsi tersebut di-xor-kan dengan plaintext pada block masing-masing. Jika dipikir-pikir, OFB ini bekerja seperti OTP (One Time Password) di mana OTP-nya adalah nilai dari IV.

Bicara soal OTP, satu hal yang harus diperhatikan adalah password yang digunakan pada OTP hanya boleh digunakan sekali. Masalahnya, pada soal ini, kita malah diperbolehkan meng-enkripsi plaintext apapun berkali-kali, tentunya dengan iv yang sama :). Di sinilah letak vuln-nya.

Nah untuk meng-exploitnya, mari kita merujuk kembali pada cara kerja OFB. Kita bisa saja meng-input pesan โ€œbikinanโ€ yang nilainya kita ketahui untuk di-enkripsi pada service. Dengan memiliki sepasang plaintext dan ciphertext yang diketahui, kita bisa menemukan nilai โ€œiv yang dienkripsiโ€ dengan beberapa operasi xor.

Supaya lebih jelas, berikut ini adalah contoh. Katakanlah ada pesan sepanjang 3 block yang dienkripsi dengan OFB. Di sini, plaintext ditulis sebagai pt, iv berarti โ€œiv hasil enkripsiโ€, kpt adalah known plaintext (nilai โ€œbikinanโ€ kita), dan kct adalah known ciphertext.

Maka dari itu, untuk mendapatkan nilai secret, ini adalah hal-hal yang perlu kita lakukan:

  • membuat nilai kpt

  • membagi kpt ke dalam blockโ€

  • meng-enkripsi kpt โ†’ mendapatkan nilai kct

  • membagi kct ke dalam blockโ€

  • meng-xor masing-masing block (kpt_i ^ kct_i) โ†’ mendapatkan iv

  • mengambil nilai ct (dari service)

  • membagi ct ke dalam blockโ€

  • meng-xor masing-masing block (ct ^ iv) โ†’ mendapatkan pt

  • ubah pt dari format per block, menjadi satu kesatuan utuh.

  • submit

Dan berikut ini adalah kode solver yang mengimplementasikan hal-hal di atas.

solve.py

Dari sini, hasil secret-nya tinggal kita submit ke server. Flag pun didapatkan.

Referensi https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation https://ctftime.org/writeup/22856#ofbuscated

Flag: gemastik{c43ef527f089bcf2a87373b2e2b6de0ef7005c3038c1f9910cd3c5013f42f054}

Last updated