| Field | Detail |
|---|---|
| Platform | PortSwigger Web Security Academy |
| Type | JWT Attacks |
| Difficulty | Expert |
| Objective | Derive the server's RSA public key from two signed tokens, then use it as an HMAC secret to forge a valid HS256 token as administrator and delete carlos |
JWT Authentication Bypass via Algorithm Confusion with No Exposed Key¶
I logged in as wiener:peter and decoded the session JWT:
Header: alg: RS256. No /jwks.json endpoint exposing the public key — the key has to be derived.
In RSA, the signature S = M^d mod n ties the message, private exponent, and public modulus together mathematically. Given two signed messages and their signatures from the same private key, there are relationships that allow recovering n — the public modulus, which is the only component needed for the algorithm confusion attack. Not having a JWKS endpoint doesn't make the key unrecoverable: any application that signs multiple JWTs with the same key is potentially vulnerable to this recovery technique.
The tool portswigger/sig2n automates this. Given two JWTs signed with the same RSA private key, it derives candidate n values, reconstructs candidate public keys, and outputs tampered JWTs already signed with HS256 using the derived key — so you can test immediately whether the derivation was correct.
I logged in a second time to get a fresh token with a different payload (log out and back in ensures exp or iat differ — two tokens with identical payloads produce the same signature and give the algorithm nothing new to work with), then ran the tool with both:
docker run --rm -it portswigger/sig2n \
'eyJraWQiOiI1YzM3NTc1Yi1hNjIwLTRmMDMtOTM4Ni02Zjg2MzMyZTRiNDAiLCJhbGciOiJSUzI1NiJ9...' \
'eyJraWQiOiI1YzM3NTc1Yi1hNjIwLTRmMDMtOTM4Ni02Zjg2MzMyZTRiNDAiLCJhbGciOiJSUzI1NiJ9...'
I pasted the tampered JWT from the output as the session cookie to verify the derived key:
200 OK with wiener's account loaded — the derived key matched. From here the attack is identical to the previous lab: import the base64-encoded X.509 public key as a symmetric key in Burp's JWT Editor, change sub to administrator, sign with HS256. The difference between this lab and the previous one is only in how you get the key.
Signed the forged token and pasted it into the browser:
Admin panel loaded. Deleted carlos:
Lab solved and section finished