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