CryptoHack Flipping Cookie

题目脚本

from Crypto.Cipher import AES
import os
from Crypto.Util.Padding import pad, unpad
from datetime import datetime, timedelta

KEY = ?
FLAG = ?

@chal.route('/flipping_cookie/check_admin/<cookie>/<iv>/')
def check_admin(cookie, iv):
    cookie = bytes.fromhex(cookie)
    iv = bytes.fromhex(iv)

    try:
        cipher = AES.new(KEY, AES.MODE_CBC, iv)
        decrypted = cipher.decrypt(cookie)
        unpadded = unpad(decrypted, 16)
    except ValueError as e:
        return {"error": str(e)}

    if b"admin=True" in unpadded.split(b";"):
        return {"flag": FLAG}
    else:
        return {"error": "Only admin can read the flag"}

@chal.route('/flipping_cookie/get_cookie/')
def get_cookie():
    expires_at = (datetime.today() + timedelta(days=1)).strftime("%s")
    cookie = f"admin=False;expiry={expires_at}".encode()

    iv = os.urandom(16)
    padded = pad(cookie, 16)
    cipher = AES.new(KEY, AES.MODE_CBC, iv)
    encrypted = cipher.encrypt(padded)
    ciphertext = iv.hex() + encrypted.hex()

    return {"cookie": ciphertext}

观察代码可知,get_cookie 函数不含参数,返回值为 admin=False;expiry={expires_at} 经过 CBC 加密后把 iv 并在一起后的十六进制文本串;check_admin 函数含有参数 cookieiv,返回值根据其解密后文本串中按 ; 进行 .split() 操作后是否为 admin=True 串,如果满足条件,则返回 FLAG。

我们首先可以利用 get_cookie 划分后得到 iv 的原值与 cookie 经过 CBC 加密后的值,根据 CBC 加密的规则:

  • c1 ^ iv ^ KEY = d(c1)
  • c2 ^ c1 ^ KEY = d(c2)
  • c3 ^ c2 ^ KEY = d(c3)
    ...

其中 d() 表示加密函数,由于 KEY 未知,我们只能通过字节翻转攻击来构造出 admin=True 子串,不难想到我们可以伪造 iv,因为 c1 只与 iv 相关,而其余与前一块文本相关。

根据 c1 ^ iv ^ KEY = d(c1),Fake_c1 ^ Fake_iv ^ KEY = d(c1) 可知,构造 Fake_iv = iv ^ admin=True;00000 ^ admin=False;expi 即可。

脚本如下

import requests
from tqdm import *
from Crypto.Util.number import *
from pwn import *

requests.adapters.DEFAULT_RETRIES = 100000
s = requests.Session()
s.timeout = (1000.0, 1000.0)

real_c1 = b'admin=False;expi'
fake_c1 = b'admin=True;00000'

get_cookie = requests.get(f'http://aes.cryptohack.org/flipping_cookie/get_cookie')
result = get_cookie.text[11:][:-3]
iv = result[0:32]
ciphertext = result[32:]
iv = xor(bytes.fromhex(iv), xor(real_c1, fake_c1)).hex()
check_admin = requests.get(f'http://aes.cryptohack.org/flipping_cookie/check_admin/{ciphertext}/{iv}')
result = check_admin.text
print(result)
posted @ 2025-02-26 08:56  YipChip  阅读(18)  评论(0)    收藏  举报