Home > Writeups > Raptor Weekly 2 - ECHELON JWT 1 - 1.2 ; NOISE FLOOR

Raptor Weekly 2 - ECHELON JWT 1 - 1.2 ; NOISE FLOOR

Intercepting a JWT delivered in a non-standard HTTP response header, decoding the payload to recover the flag hidden in a custom claim, and recognizing the truncated signing key that will matter again two challenges later.

1.2 ; NOISE FLOOR

Challenge Description

You are in. The system says your clearance is CONFIDENTIAL. It also says higher tier requires an elevated token.

URL: https://echelon.two-shoes.org/access


Overview

The /access page renders a 403-style warning and the CONFIDENTIAL tier file downloads. The server also sets an X-Session-Token response header containing a JWT. The flag is embedded as a custom claim inside the JWT payload. Decoding it requires no key and no attack, just base64. The token is also signed with a truncated key, making it unforgeable as-is. Understanding what that implies feeds directly into 2.2 ; DEAD DROP and 2.3 ; SIGNED.


Step 1: Inspect the Response Headers

Read the response headers for /access with any tool that exposes them:

curl -v -b cookies.txt https://echelon.two-shoes.org/access 2>&1 | grep -i "x-session\|x-auth"
X-Session-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhb...
X-Auth-Status:   CONFIDENTIAL ; ELEVATED TOKEN REQUIRED FOR SECRET

Record the full X-Session-Token value.


Step 2: Decode the JWT Payload

A JWT is three base64url-encoded sections separated by dots: header, payload, signature. Decode the payload, the middle section, without verifying anything:

import base64, json

token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhb..."
parts = token.split(".")

def b64d(s):
    s += "=" * (-len(s) % 4)
    return base64.urlsafe_b64decode(s)

payload = json.loads(b64d(parts[1]))
print(json.dumps(payload, indent=2))

The decoded payload:

{
  "sub": "analyst",
  "role": "CONFIDENTIAL",
  "node": "ECHELON.NODE.07",
  "iat": 1773423600,
  "exp": 9999999999,
  "x-echelon-flag": "ECHELON{n0ise_is_never_just_n0ise}"
}

Alternatively: paste the token into jwt.io (https://jwt.io). The flag is in the x-echelon-flag custom claim.


Step 3: Note What Else Is Here

The algorithm is HS256. The role is CONFIDENTIAL. The signature is present but does not verify against the full JWT secret, it was signed with a truncated key. This token cannot be used for tier escalation without reconstructing the correct secret. That reconstruction happens across the two CONFIDENTIAL tier artifacts:

  • JWT_PT1 comes from 2.1 ; INTERCEPT
  • JWT_PT2 comes from 2.2 ; DEAD DROP
  • The full secret feeds 2.3 ; SIGNED

Hold the token. Move to 2.1.


Key Takeaways

JWT payloads are base64url-encoded, not encrypted. Any party who can observe the token can read every claim without knowing the signing secret. Custom claims like x-echelon-flag are visible to anyone who looks. Sensitive data placed in a JWT payload is only as protected as the transport layer carrying the token. If a token must contain sensitive fields, the entire token should be encrypted (JWE), not just signed (JWS).


Flag

ECHELON{n0ise_is_never_just_n0ise}

< Back to All Writeups