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

Challenge example

Arbitrary token

Code source example

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

FLAG = ?
KEY = ?

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


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


def auth():
    user = dict()
    user["username"] = input("username : ")
    user["password"] = input("password : ")
    user["uid"] = int(user["username"] == "admin" and user["password"] == FLAG)
    
    plaintext = json.dumps(user).encode()
    padded = pad(plaintext, 16)
    cipher = AES.new(KEY, AES.MODE_ECB)
    try:
        encrypted = 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)

    cipher = AES.new(KEY, AES.MODE_ECB)
    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["uid"] == 1:
    admin()
else:
    guest()

The challenge objectif is to log as admin user.

Exploitation

When the user authenticates using their credentials, the application will send a token that can be reuse to directly access the app.

The token contain :

  • username : provided by the user

  • password : provided by the user

  • uid : set by the application depending if the provided credentials are admin or not.

Can the user forge an arbitrary block ?

The user can effectively forge arbitrary blocks.

In order to obtain admin access the user need to replace the block containing 'uid': 0

Here we will manipulate the input to have this at the end of the penultimate block :

We now need to forge the block 1

We need a last block :

Now to obtain the admin access we need to replace the last block of the first token (containing 0} + padding) by the second block of the second token ( containing 1) and concat the last block of the last token ( containing } + padding )

At this moment the json value will be :

And when we use it :

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