BYUCTF2024 - Random (web) writeup

Published on by logoseq

Walkthrough


Summary:

In this challenge, our task is to generate a JSON Web Token (JWT) with specific requirements. The payload of the JWT should include the parameter "userid" set to 0. The JWT must be encoded using the HS256 algorithm. The secret key for this encoding is derived from the variable APP_SECRET, which itself is generated using the SHA-256 hash function. The input to this hash function is the time at which the application started.

  • From source code:
    APP_SECRET = hashlib.sha256(str(time_started).encode()).hexdigest()
    payload = jwt.decode( session, APP_SECRET, algorithms=['HS256'] )
    if payload['userid'] != 0:
  • session = request.cookies.get('session', None)
JWT Challenge
Objective

Generate a JSON Web Token (JWT) with the following specifications:

  • Payload: {"userid": 0}
  • Algorithm: HS256
  • Secret Key:
    • Derived from the variable APP_SECRET.
    • APP_SECRET is generated using the SHA-256 hash function.
    • The input to SHA-256 is the application's start time.
    • Use the function hashlib.sha256(time), where time is the timestamp when the application started.
    • Create the JWT token and use it as cookie "session".
    • Then go to /api/files to see which file is present in that directory.

Analyzing the source code and creating a script to do the challenge for us:

Session Validation Process
Overview

The application uses a variable named APP_SECRET to generate a secret key with the following process:

  1. Generate Secret Key:
    APP_SECRET = hashlib.sha256(str(time_started).encode()).hexdigest()

    Here, time_started is the time when the application started.

  2. Check for Session Cookie:

    The application looks for a session cookie. If it exists, it attempts to decode it.

  3. Decode JWT Token:

    The session cookie should be a JWT token with:

    • A payload containing {"userid": 0}.
    • Encoded using HS256 algorithm with APP_SECRET as the secret key.
  4. Validation:

    If the token does not pass these checks, the application returns an error including the time since the app started. This indicates a business logic flaw that permits token creation.

BYUCTF2024 - Random challenge source code. From here we understand the JWT payload creation to be able to use it as cookie session and get files from system.

Script:

JWT Exploit Process
Overview

I developed a Python script to exploit a vulnerability in the application's JWT handling. The steps are as follows:

  1. Generate Random JWT Token:

    Create a JWT token with the payload {"userid": 0} and a random secret, encoded with HS256.

  2. Send Initial Request:

    Send the token to the /api/files endpoint and receive an error response containing the application's runtime in seconds.

  3. Create Correct Secret:

    Use the runtime information to reconstruct the correct APP_SECRET:

      import hashlib
      time_started = current_time - seconds_since_start
      APP_SECRET = hashlib.sha256(str(time_started).encode()).hexdigest()
                        
  4. Generate Valid JWT Token:

    Create a new JWT token with the payload {"userid": 0}, encoded with HS256 using the correct APP_SECRET.

  5. Send Valid Request:

    Send the new token to the /api/files endpoint successfully.

  6. Access Restricted File:

    Send a request to /api/file?filename=/dirFromEtcPasswd/flag.txt to access the restricted file.

BYUCTF2024 - Random challenge script.py source code

Some requests with the new payload:

Found dir in /etc/passwd:

BYUCTF2024 - Random challenge script.py source code

Used that dir to get the flag from flag.txt file:

BYUCTF2024 - Random challenge script.py source code

The script I worte worked! BYUCTF2024 - Random challenge script.py running and getting the flag

P.S: I could add a new regex to get the random dir hash from /etc/passwd and let the script do anything, but I'm a lazy guy and I just copied the directory found with curl.