Labs Covered
This write-up focuses on the following EXPERT-level labs from the PortSwigger Web Security Academy related to JWT (JSON Web Token) vulnerabilities:
7 JWT authentication bypass via algorithm confusion
This lab demonstrates how attackers can bypass authentication by exploiting algorithm confusion vulnerabilities in JWT implementations.
8 JWT authentication bypass via algorithm confusion with no exposed key
This lab shows how attackers can exploit algorithm confusion even when no public signing key is exposed.
LAB 7 - JWT authentication bypass via algorithm confusion
Lab Description
Overview: JWT Algorithm Confusion (Key Confusion Attack)
What is it?
JWT algorithm confusion is a critical vulnerability where a server accepts a token signed with a different algorithm than intended. An attacker can exploit this by switching the alg field in the JWT header to trick the server into verifying a forged token.
Why It’s Dangerous
JWT supports both:
- Symmetric algorithms (e.g., HS256): Same key is used for signing and verification.
- Asymmetric algorithms (e.g., RS256): Private key is used to sign, public key is used to verify.
If a server expects RS256 but an attacker sends a JWT with alg: HS256, some poorly configured libraries may accept it and use the public key as the HMAC secret, effectively allowing attackers to forge valid tokens.
How the Exploit Works
Step 1: Obtain the Public Key Public keys are often exposed via:
/.well-known/jwks.json
or may be extracted from existing tokens. These keys are typically in JWK format.
Example JWK:
{
"kty": "RSA",
"e": "AQAB",
"n": "o-yy1wpYmf...",
"kid": "75d0ef47..."
}
Step 2: Convert Public Key to a Secret Convert the JWK to PEM format, then Base64-encode it. This becomes the secret used in HMAC signing.
Tools like Burp Suite JWT Editor can perform this conversion easily.
Step 3: Craft a Malicious JWT Create a JWT with:
algset toHS256- A payload of your choice (e.g.,
{"role": "admin"}) - Sign the token using the Base64-encoded public key as the HMAC secret
Step 4: Send the Token to the Server If the server incorrectly uses the public key as an HMAC secret, it will accept the token as valid, giving the attacker unauthorized access.
Example Attack Flow
-
Change JWT header:
{ "alg": "HS256", "typ": "JWT" } -
Use a payload like:
{ "user": "admin" } - Sign the JWT using HMAC-SHA256 with the public key as the secret
- Submit the token to the server
If the server is vulnerable, it accepts the token and treats the attacker as an authenticated or privileged user.
Solution
As we can see that admin panel is accessible to administrator only.
In the browser, go to the standard endpoint /jwks.json and observe that the server exposes a JWK Set containing a single public key.
Now we want public to sign our jwt token ,Now the public key is not in correct form to sign, So we create New Rsa key and paste the same public key as above in jwks.json and first paste above public key start from KTY and it was obsufcate, Now press jwk and it remove obsufaction
Then we will Public key as pem as shown below( PEM (Privacy Enhanced Mail) format is often used for verifying the signature of the JWT).
Encode PEM key from decoder
Then we will generate New Symmetric key and click on generate and paste Encoded above pem public key in k and then used tis signature Of jwt
Second One is secret key which we will used for signing
Change alg to HS256 FROM RS256 and change sub to administrator
Now try to access admin and we will get the admin
Now deleted carlos user to solve the lab
After deleting carlos and follow redirection lab is solved
In cases where the public key isn’t readily available, you may still be able to test for algorithm confusion by deriving the key
from a pair of existing JWTs. This process is relatively simple using tools such as jwt_forgery.py. You can find this, along with several other useful scripts, on the rsa_sign2n GitHub repository.
We have also created a simplified version of this tool, which you can run as a single command:
docker run –rm -it portswigger/sig2n
Note You need the Docker CLI to run either version of the tool. The first time you run this command, it will automatically pull the image from Docker Hub, which may take a few minutes.
LAB 8 - JWT authentication bypass via algorithm confusion with no exposed key
Lab Description
Solution
Login as wiener
In the cookie we have jwt key
Copy your JWT session cookie and save it somewhere for later.
Log out and log in again.
Copy the new JWT session cookie and save this as well. You now have two valid JWTs generated by the server
Brute-force the server’s public key
In a terminal, run the following command, passing in the two JWTs as arguments.
docker run --rm -it portswigger/sig2n <token1> <token2>
Note that the first time you run this, it may take several minutes while the image is pulled from Docker Hub.
Notice that the output contains one or more calculated values of n. Each of these is mathematically possible, but only one of them matches the value used by the server. In each case, the output also provides the following:
A Base64-encoded public key in both X.509 and PKCS1 format.
A tampered JWT signed with each of these keys.
Copy the tampered JWT from the first X.509 entry (you may only have one).
Go back to your request in Burp Repeater and change the path back to /my-account.
Replace the session cookie with this new JWT and then send the request.
If you receive a 200 response and successfully access your account page, then this is the correct X.509 key.
If you receive a 302 response that redirects you to /login and strips your session cookie, then this was the wrong X.509 key. In this case, repeat this step using the tampered JWT for each X.509 key that was output by the script.
redirect to 302
Generate a malicious signing key
From your terminal window, copy the Base64-encoded X.509 key that you identified as being correct in the previous section. Note that you need to select the key, not the tampered JWT that you used in the previous section.
In Burp, go to the JWT Editor Keys tab and click New Symmetric Key.
In the dialog, click Generate to generate a new key in JWK format.
Replace the generated value for the k property with a Base64-encoded key that you just copied. Note that this should be the actual key, not the tampered JWT that you used in the previous section.
Save the key.
1. Go to the Burp Repeater tab
- Locate the request to
/adminin Burp Repeater. - Change the request path from its original endpoint (e.g.
/my-account) to:
/admin
2. Open the JWT in the extension tab
- Switch to the “JSON Web Token” tab (if using the JWT Editor extension).
- You should see the JWT split into Header, Payload, and Signature.
3. Modify the JWT
- Header: Make sure this looks like:
{
"alg": "HS256",
"typ": "JWT"
}
- Payload: Change the
sub(subject) field toadministrator. For example:
{
"sub": "administrator",
"iat": <keep_original_value>,
...
}
(Keep other fields unchanged unless instructed.)
4. Sign the token
- At the bottom of the JWT tab, click Sign.
- Choose HS256 and select the symmetric key you found earlier (likely the server’s public key, used as the HMAC key).
- Make sure “Don’t modify header” is selected so the alg remains HS256.
- Click OK — the JWT is now signed properly.
5. Send the modified request
- The Authorization header (or Cookie) should now contain the updated JWT.
- Click Send.
- You should now get access to the admin panel.
6. Delete Carlos
- In the response, search for:
/admin/delete?username=carlos
- Copy this URL, and send a new GET request to that endpoint in Burp Repeater.
Lab should now be solved, and you will see a success message.