The code is vulnerable to hash length extension attack. The hash for a message with a new block appended can be computed from the hash of the old message, and xor
with the result of encrypting the old hash with the key as the new block. Denote
Hence the task is simply to reconstruct the correct state of the hash algorithm, then do a simple xor
with the new block and we should obtain a valid hash. The padding is a bit tricky to get it correct, so I recommend testing the challenge code out locally first.
Python Implementation:
xxxxxxxxxx
from pwn import *
import json
import os
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
def bxor(a, b):
return bytes(x ^ y for x, y in zip(a, b))
io = remote('socket.cryptohack.org', 13388)
io.recvline()
# Randomly 15 bytes for less painful padding issues
r = os.urandom(15)
to_send = {'option': 'sign', 'message': r.hex()}
io.sendline(json.dumps(to_send).encode())
sig = json.loads(io.recvline().decode())['signature']
sig = bytes.fromhex(sig)
payload = b'admin=True'
# Message is the padded random 15 bytes earlier plus the payload
m = pad(r, 16) + payload
sig = bxor(AES.new(pad(payload, 16), AES.MODE_ECB).encrypt(sig), sig)
to_send = {'option': 'get_flag', 'message': m.hex(), 'signature': sig.hex()}
io.sendline(json.dumps(to_send).encode())
io.interactive()