For the complete documentation index, see llms.txt. This page is also available as Markdown.

Challenge example

Source code example

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

FLAG = ?
KEY = ?

def admin():
    print("welcome admin")
    print(f"Flag = {FLAG}")


def guest():
    print("welcome guest")


def auth():
    user = dict()
    username = input("username : ")
    password = input("password : ")
    user["is_admin"] = int(username == "admin" and password == FLAG)
    
    plaintext = json.dumps(user).encode()
    padded = pad(plaintext, 16)
    iv = os.urandom(16)
    cipher = AES.new(KEY, AES.MODE_CBC, iv)
    try:
        encrypted = iv + cipher.encrypt(padded)
    except ValueError as e:
        return {"error": str(e)}

    print(f"Here is your token : {encrypted.hex()}")

    return user


def authToken():
    token = input("Token : ")
    token = bytes.fromhex(token)
    iv = token[:16]
    token = token[16:]

    cipher = AES.new(KEY, AES.MODE_CBC, iv)
    try:
        plaintext = cipher.decrypt(token)
        unpadded = unpad(plaintext, 16)
        user = json.loads(unpadded)
    except ValueError as e:
        return {"error": str(e)}

    return user


print("Welcome !")
print("Please login first.")

choice = input("How would you login ?\n1) Token\n2) Credentials\n\nChoice :")

if choice == "1":
    user = authToken()
elif choice == "2":
    user = auth()
else:
    print("error... goodbye")
    exit(0)

if "error" in user:
    print(f"ERROR : {user['error']}")
    exit(0)

elif user["is_admin"] == 1:
    admin()
else:
    guest()

The challenge objective is to authenticate as admin using an arbitrary token forged using bit flipping attack.

Exploitation

First, a legit token is needed.

The token contains two blocks, the IV and the ciphertext block.

As explain here, plaintext is xored with the precedent cipherblock ( the IV for the first block ) before encryption. As we can control the ciphertext, we can control the plaintext.

The original plaintext is :

The json data + padding

The targeted data is :

The IV can be replace with the value 9cdc43fb9d2fed9a0b5ccc837d4b5bad obtaned using the following operation :

And then using the new token, the admin access is granted :

Exploitation Script

Exercice

If you want to try this exploit by yourself, you can pull this docker image :

Deploy the image using the followed command :

The service is available on port 1337

Last updated