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)
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)
, wheretime
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.
- Derived from the variable
Analyzing the source code and creating a script to do the challenge for us:
Overview
The application uses a variable named APP_SECRET
to generate a secret key with the following process:
-
Generate Secret Key:
APP_SECRET = hashlib.sha256(str(time_started).encode()).hexdigest()
Here,
time_started
is the time when the application started. -
Check for Session Cookie:
The application looks for a
session
cookie. If it exists, it attempts to decode it. -
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.
- A payload containing
-
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.](../assets/images/byuctf-web-random/source_code.webp)
Script:
Overview
I developed a Python script to exploit a vulnerability in the application's JWT handling. The steps are as follows:
- Generate Random JWT Token:
Create a JWT token with the payload
{"userid": 0}
and a random secret, encoded with HS256. - Send Initial Request:
Send the token to the
/api/files
endpoint and receive an error response containing the application's runtime in seconds. - 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()
- Generate Valid JWT Token:
Create a new JWT token with the payload
{"userid": 0}
, encoded with HS256 using the correctAPP_SECRET
. - Send Valid Request:
Send the new token to the
/api/files
endpoint successfully. - 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](../assets/images/byuctf-web-random/do_challenge_script.webp)
Some requests with the new payload:
Found dir in /etc/passwd
:
![BYUCTF2024 - Random challenge script.py source code](../assets/images/byuctf-web-random/etc_passwd_hint.webp)
Used that dir to get the flag from flag.txt
file:
![BYUCTF2024 - Random challenge script.py source code](../assets/images/byuctf-web-random/flag.webp)
The script I worte worked!
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.