Category: Web Exploitation
Difficulty: Medium
Points: 90
Description
The site sets an auth_name cookie that controls access. Modifying it naively breaks the format. The goal is to flip bits in the ciphertext to produce a cookie that the server accepts as an admin.
Overview
- The
auth_namecookie is double-base64-encoded AES-CBC ciphertext. - AES-CBC is vulnerable to bit-flip attacks: flipping a bit at position
pin the ciphertext causes a predictable, controllable flip at the same position in the decrypted plaintext. - Systematically trying every position and bit value eventually produces a plaintext the server treats as authenticated.
Background: CBC Bit-Flip Attack
- In CBC mode, decrypting ciphertext block produces .
- Flipping bit at position in block causes bit at position in to flip.
- This means you can make targeted changes to the plaintext without knowing the key, provided you know what the original plaintext bytes were.
- The drawback is that block itself decrypts to garbage, but only one block is corrupted.
Solution
Step 1: Extract the Cookie
- The server sets
auth_nameon the initial page load. - The raw value is double-base64-encoded:
base64(base64(ciphertext)).
Step 2: Implement the Bit-Flip Helper
def bit_flip(pos: int, bit: int, data: str) -> str:
raw = base64.b64decode(base64.b64decode(data).decode())
data = bytearray(raw)
data[pos] = data[pos] ^ bit
raw = bytes(data)
return base64.b64encode(base64.b64encode(raw)).decode()
- The function decodes the cookie, XORs one byte at the given position with the given value, and re-encodes it.
Step 3: Brute-Force Position and Bit Value
- The loop iterates over the first 10 byte positions and all 128 single-bit XOR masks.
- Each mutated cookie is sent back in the
auth_namefield. - When the response contains
picoCTF{, the correct flip has been found.
for pi in range(10):
for bi in range(128):
auth_cookie = bit_flip(pi, bi, cookie)
r = requests.get(url, cookies={"auth_name": auth_cookie})
if "picoCTF{" in r.text:
break
Why This Works
- The admin flag is stored in the plaintext somewhere in the first block of the cookie.
- The correct bit flip changes a non-admin byte (e.g.
is_admin=0) to an admin byte (is_admin=1). - Because the flip is in the previous ciphertext block, only that block is corrupted on decryption, and the server still reads the admin value correctly from the next block.
Flag
picoCTF{cO0ki3s_yum_a9a19fa6}