| Field | Detail |
|---|---|
| Platform | PortSwigger Web Security Academy |
| Type | JWT Attacks |
| Difficulty | Apprentice |
| Objective | Modify the session JWT to impersonate the administrator, access /admin, and delete carlos |
JWT Authentication Bypass via Unverified Signature¶
I logged in as wiener:peter and decoded the session JWT from GET /my-account:
Header:
{"kid":"039db574-c1b9-4893-9e24-78346ecdc780","alg":"RS256"}
Payload:
{"iss":"portswigger","exp":1783040110,"sub":"wiener"}
alg: RS256 — asymmetric signing. In theory, only the server with the private key can produce valid signatures. The sub claim identifies the user. The question is whether the server actually verifies the signature before trusting that claim.
In Burp's inspector I modified the JWT payload directly, changing sub from wiener to administrator:
{"iss":"portswigger","exp":1783040110,"sub":"administrator"}
The payload was re-encoded; the signature stayed as-is from the original wiener token. Burp's JWT inspector handles this cleanly — it decodes the token, lets you edit the JSON directly, and re-encodes the payload without touching the signature. No external tools needed.
I pasted the modified session cookie into the browser's storage and navigated to /admin:
Access granted. The server called decode() instead of verify() — the signature being present doesn't mean it's being checked. We modified the payload and kept the wiener signature; a server that actually verifies signatures would reject this immediately because the signature no longer matches the new payload. The sub claim is just a string, and there's no enforcement at the token level. If the server trusts sub without verifying the signature that's supposed to protect it, any value works.
Deleted carlos.
Lab solved :P