''' Solution to https://cryptohack.org/courses/symmetric/flipping_cookie/ ''' import requests from datetime import datetime, timedelta URL = 'https://aes.cryptohack.org/flipping_cookie' # NOTE: assumes A and B are equal length def xor_bytes(A: bytes, B: bytes) -> bytes: return b''.join([(a ^ b).to_bytes() for (a, b) in zip(A, B)]) def xor_str(A: str, B: str) -> str: return ''.join([chr(ord(a) ^ ord(b)) for (a, b) in zip(A, B)]) def gen_expiry() -> str: return (datetime.today() + timedelta(days=1)).strftime("%s") def get_cookie() -> tuple[bytes, bytes]: resp = requests.get(f'{URL}/get_cookie/') cookie = resp.json()['cookie'] iv = bytes.fromhex(cookie[:32]) ciphertext = bytes.fromhex(cookie[32:]) return iv, ciphertext def main() -> None: # cookie flipping preprocessing step admin_len = len('admin=') expiry_len = len(';expiry=') + len(gen_expiry()) admin_mask = '\x00' * admin_len expiry_mask = '\x00' * expiry_len # we aim to replace "admin=False;" with "admin=True;;" # NOTE: double semicolon ("True;;") is intentional # NOTE: and the server won't ever realise it happened! deletion = admin_mask + 'False' + expiry_mask insertion = admin_mask + 'True;' + expiry_mask # determine the value that replaces deletion with insertion cookie_flip = xor_str(deletion, insertion) # get our new cookie and apply the cookie flip! iv, ciphertext = get_cookie() flipped_iv = xor_bytes(cookie_flip.encode(), iv) print('Flipped Cookie:') print('IV:', flipped_iv.hex()) print('Body:', ciphertext.hex()) if __name__ == '__main__': main()