JWT attack
They are separated by dots . like this: header.payload.signature
Introduction#
JSON Web Tokens (JWT) are widely used for stateless authentication. But misconfigurations and weak implementations can make them vulnerable to critical attacks.
JSON Web Tokens (JWTs) are a standardized way to send **cryptographically signed JSON data** between systems.They can hold any data, but most often they're used to send user information ("claims") for:
- Authentication
- Session management
- Access control
Key idea: Unlike classic session tokens (which store user data on the server), all the user data is in the JWT itself (client-side). This makes them popular for large, distributed systems.
Common mistakes:
- Using `none` algorithm without verification
- Weak signing keys
- Disclosure of secrets
- Algorithm confusion attacks (HS256 ↔ RS256)
- Lack of signature validationJWT format#
A JWT is made of 3 parts:
1️⃣ Header
2️⃣ Payload
3️⃣ Signature
They are separated by dots . like this:
header.payload.signature
Example token:#
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0IiwibmFtZSI6ImFuYXMiLCJyb2xlIjoiYWRtaW4iLCJpYXQiOjE2MDAwMDAwMDB9.dummySignature
Explanation:
- Header: Contains metadata about the token (e.g. algorithm used, type).
- Payload: Contains the user data ("claims") like user ID, name, role.
- Signature: Ensures the token has not been tampered with and proves it was issued by the server.
Example decoded Header
{
"alg": "HS256",
"typ": "JWT"
}Example decoded Payload
{
"sub": "1234",
"name": "anas",
"role": "admin",
"iat": 1600000000
}Anyone with access to the token can read and even edit this data. It's just Base64-encoded JSON!
That's why the signature is critical: it ensures the data wasn't changed since the server issued it.
JWT Signature#
How is the signature made? The server hashes the header + payload. It signs this hash with a secret key. The result is the signature.
Security principle: Change 1 letter in the payload → signature becomes invalid. Without the server's secret, you can't forge a valid signature.
Exemple :
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)Tip Want to try it? Use jwt.io to decode, edit, and re-sign tokens in the live debugger.
JWT vs JWS vs JWE#
The JWT specification itself is very limited:
It only defines a format for representing data ("claims") as JSON that can be exchanged between two parties.
Important:
JWT alone does not specify how to protect that data.
It’s just a container format.
JWS - JSON Web Signature#
- A JWT with a signature.
- The data is not encrypted → anyone can read it.
- Integrity protection: ensures data hasn't been modified.
- Most commonly used for authentication.
Example claim:
{
"name": "anas",
"role": "admin"
}JWE - JSON Web Encryption#
A JWT with encryption. Data is encrypted → can't be read without decryption key. Provides confidentiality + integrity. Used for sensitive data.
Relationship between JWT, JWS, and JWE#
| Type | Protection | Use Case |
|---|---|---|
| JWS | Signature (Integrity) | Prove data wasn't changed |
| JWE | Encryption + Signature | Keep data secret & untampered |
Note: When people say "JWT", they usually mean JWS. Some vulnerabilities may apply to JWE as well.
What are JWT attacks?#
JWT attacks involve sending modified tokens to the server to achieve malicious goals.
Typical goals:
Bypass authentication Impersonate another user Escalate privileges
Example Attack: Decode the JWT:
{
"name": "anas",
"role": "user"
}Change role to "admin":
{
"name": "anas",
"role": "admin"
}Forge a valid signature if possible.
Impact of JWT attacks#
Usually severe:
Account takeover. Admin access. Total system compromise.
How do vulnerabilities arise? Not verifying the signature properly. Accepting "none" algorithm. Using weak / guessable secrets. Algorithm confusion (e.g. HS256 vs RS256).
Even if signature verification is strong: It depends on keeping the secret key safe.
If the secret is leaked or brute-forced → attacker can sign any token.
JWT Attack Labs - Summary#
Below is a clear, concise summary of the labs I completed about JWT attacks on PortSwigger Web Security Academy.
🟢 1. Exploiting flawed JWT signature verification#
Idea:
Servers don't store JWT contents, they trust what's inside the token. If they fail to verify the signature properly, an attacker can modify the payload freely.
Example Attack:
- Change
{ "isAdmin": false }→{ "isAdmin": true } - Forge any claim.
Lab:
JWT authentication bypass via unverified signature
🟢 2. Accepting tokens with no signature ("none" algorithm)#
Idea:
JWT header has an alg parameter. Some servers fail to enforce safe algorithms and accept alg: none, meaning no signature is checked at all.
Example Attack:
- Modify header to
"alg": "none" - Remove signature
- Edit payload claims freely
Lab:
JWT authentication bypass via flawed signature verification
🟢 3. Brute-forcing secret keys#
Idea:
HS256 (HMAC + SHA-256) uses a secret key for signing. If this key is weak or default, it can be guessed or brute-forced.
Example Attack:
- Get a valid JWT
- Use tools like
hashcatto brute-force the secret - Sign new tokens with arbitrary claims
Tools:
- hashcat:
hashcat -a 0 -m 16500 <jwt> <wordlist> - jwt_tool
Lab:
JWT authentication bypass via weak signing key
🟢 4. JWT header parameter injection - JWK parameter#
Idea:
Some servers use the jwk header to embed the public key inside the JWT itself. If not properly validated, an attacker can embed their own key.
Example Attack:
- Sign JWT with your own private key
- Include matching public key in the
jwkheader - Server accepts and verifies your malicious token
Lab:
JWT authentication bypass via jwk header injection
🟢 5. JWT header parameter injection - JKU parameter#
Idea:
jku header lets a JWT point to a URL where a JWK Set (keys) is hosted. If the server blindly fetches and trusts any JKU, an attacker can host their own malicious keys.
Example Attack:
- Create your own JWK Set on your server
- Set
jkuheader to your URL - Server fetches your public key and accepts your signature
Lab:
JWT authentication bypass via jku header injection
JWT header parameter injection -#
Idea:
The JWT header usually includes fields like alg and typ, but it can also contain a jwk field.
jwk is a public key embedded directly in JSON format inside the header.
What's the problem?
Well-configured servers only accept keys they trust (whitelisted keys).
But some vulnerable servers will use any public key found in the jwk header without verifying where it came from.
What does the attacker do?
- Creates a JWT with a forged payload (e.g.
"role": "admin"). - Signs it with their own private key.
- Embeds the matching public key in the
jwkheader.
How does the server get fooled?
- The server reads the
jwkheader and finds the attacker's public key. - It uses that key to verify the signature → the signature is valid (because the attacker signed it with the matching private key).
- The server accepts the JWT as valid → attacker gains access.
In short:
The attacker tells the server:
"Here's my signature, and here's the public key to check it."
And the server naively trusts it without verifying who controls the key.
Example header with jwk:
{
"alg": "RS256",
"typ": "JWT",
"jwk": {
"kty": "RSA",
"n": ".....",
"e": "AQAB"
}
}Lab: JWT header parameter injection - jku parameter#
Idea:
- The JWT header can include a
jkuparameter. jkuis a URL that tells the server where to fetch a JWK Set (a collection of public keys).- The server then uses one of these keys to verify the JWT's signature.
What's the problem?
- Servers should only accept trusted, whitelisted URLs in
jku. - Vulnerable servers just fetch any URL given in the
jkuheader without validation. - This means the attacker can control where the server fetches the key.
What does the attacker do?
- Creates a JWT with forged payload (e.g.
"role": "admin"). - Signs it with their own private key.
- Hosts their public key on their own server in a JWK Set.
- Sets
jkuin the header to their malicious URL.
How does the server get fooled?
- The server reads the
jkuheader → follows the attacker's URL. - Fetches the attacker's public key from there.
- Verifies the signature → it's valid (because the attacker signed it).
- Server accepts the forged JWT → attacker gains access.
In short:
The attacker tells the server:
"Here's my signature, and here's the URL to fetch my public key from."
The server blindly trusts it without checking who controls the URL.
Example header with jku:
{
"alg": "RS256",
"typ": "JWT",
"jku": "https://attacker.com/mykeys.json"
}Result:
Attacker signs their own forged JWT. Provides a URL under their control with their public key. The server accepts the JWT as valid. Attacker escalates privileges (e.g. becomes admin).
This attack is highly dangerous on servers that don't verify the source of the jku URL or lack a strict whitelist of trusted domains.
Lab: Injecting self-signed JWTs via the kid parameter#
Idea:
- The JWT header includes a
kid(Key ID) parameter. kidhelps the server identify which key to use when verifying the signature.- Servers often store multiple keys in a JWK Set, selecting the correct one by matching the
kid.
What's the problem?
- The
kidis just an arbitrary string with no enforced format. - Vulnerable servers might use the
kiddirectly in a file path or database lookup without sanitization. - This allows directory traversal or other injection attacks.
What does the attacker do?
- Sets a malicious
kidvalue like:
"kid": "../../path/to/file"The server tries to load this file as the secret key. If the attacker knows the file’s contents, they can sign their own JWT with it.
Why is this dangerous? For symmetric algorithms like HS256, the same secret is used to sign and verify. If the attacker can choose a file with predictable contents (like /dev/null), they can craft a valid signature.
Example attack with /dev/null (on Linux):
/dev/null is always empty → contents = "". The attacker signs the JWT with an empty secret. The server reads /dev/null, uses "" as the secret, and accepts the signature as valid.
Example malicious header:
{
"kid": "../../dev/null",
"typ": "JWT",
"alg": "HS256"
}In short:
The attacker uses kid to force the server to load a specific file as the key. They sign the JWT using that known content. The server verifies it and accepts the forged token. Attacker can escalate privileges (e.g. become admin).
Why is this attack so dangerous?
It exploits poor input validation on kid. Servers should never trust user-supplied kid values blindly. They must enforce whitelists and sanitize paths to avoid traversal attacks.
Lab: JWT authentication bypass via algorithm confusion#
Idea:
Algorithm confusion attacks happen when the server is tricked into verifying a JWT using a different algorithm than intended. If the server doesn't enforce which algorithm must be used, attackers can forge valid tokens without knowing the secret key.
Symmetric vs Asymmetric Algorithms:
- HS256 (symmetric): same secret is used to sign and verify. Must be kept private.
- RS256 (asymmetric): uses a private key to sign and a public key to verify. Public key can be shared openly.
Where does the vulnerability come from?
Some applications rely on the alg header in the token to choose the verification method.
Example pseudo-code:
function verify(token, secretOrPublicKey){
algorithm = token.getAlgHeader();
if(algorithm == "RS256"){
// Use the provided key as an RSA public key
} else if (algorithm == "HS256"){
// Use the provided key as an HMAC secret key
}
}If developers assume only RS256 is used, they might always pass the public key into the verify() function without checking the alg.
How does the attack work?
- The attacker obtains the server's public key (often exposed at endpoints like /.well-known/jwks.json).
- Modifies the JWT header to set
"alg": "HS256". - Signs the token using HS256 with the server’s public key as the HMAC secret.
- The server uses the public key as the secret, verifying and accepting the attacker's token.
Example malicious header:
{
"alg": "HS256",
"typ": "JWT"
}Example payload:
{
"user": "attacker",
"role": "admin"
}Attack Steps:#
Obtain the server’s public key. Convert it to the correct format if necessary. Modify JWT header to use "alg": "HS256". Sign the JWT with HS256 using the public key as the secret. Send the forged JWT to the server.
Why is this dangerous?#
The attacker can escalate privileges (e.g., become admin). They do not need the server’s private signing key or secret. Exploits poor validation of the alg parameter.
Defense recommendations:#
Do not trust the alg value from the token. Enforce a single expected algorithm (e.g., RS256) on the server. Use robust, well-maintained libraries that prevent this class of bug.
List of standard endpoints for public JSON Web Keys: /.well-known/jwks.json /jwks.json /auth/jwks /api/jwks /keys /security/jwks /public-keys
Performing an algorithm confusion attack#
An algorithm confusion attack generally involves the following high-level steps:
Obtain the server's public key Convert the public key to a suitable format Create a malicious JWT with a modified payload and the alg header set to HS256. Sign the token with HS256, using the public key as the secret.
Step 1 - Obtain the server's public key Servers sometimes expose their public keys as JSON Web Key (JWK) objects via a standard endpoint mapped to /jwks.json or /.well-known/jwks.json, for example. These may be stored in an array of JWKs called keys. This is known as a JWK Set.
{
"keys": [
{
"kty": "RSA",
"e": "AQAB",
"kid": "75d0ef47-af89-47a9-9061-7c02a610d5ab",
"n": "o-yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9mk6GPM9gNN4Y_qTVX67WhsN3JvaFYw-fhvsWQ"
},
{
"kty": "RSA",
"e": "AQAB",
"kid": "d8fDFo-fS9-faS14a9-ASf99sa-7c1Ad5abA",
"n": "fc3f-yy1wpYmffgXBxhAUJzHql79gNNQ_cb33HocCuJolwDqmk6GPM4Y_qTVX67WhsN3JvaFYw-dfg6DH-asAScw"
}
]
}Step 2 - Convert the public key to a suitable forma You can convert a JWK to a PEM using the JWT Editor extension in Burp as follows:
With the extension loaded, in Burp's main tab bar, go to the JWT Editor Keys tab. Click New RSA Key. In the dialog, paste the JWK that you obtained earlier. Select the PEM radio button and copy the resulting PEM key. Go to the Decoder tab and Base64-encode the PEM. Go back 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 parameter with a Base64-encoded PEM key that you just copied. Save the key.
Step 3 - Modify your JWT Once you have the public key in a suitable format, you can modify the JWT however you like. Just make sure that the alg header is set to HS256.
Step 4 - Sign the JWT using the public key Sign the token using the HS256 algorithm with the RSA public key as the secret.
Lab : Deriving public keys from existing tokens#
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 <token1> <token2>token 1 : we can get the token 1 when we logged with the 1 for exemple anas:password123 and inpecter == we have the jwt token1 token 2 : we can get the token 2 when we logged with the 2 for exemple anas:password123 and inpecter == we have the jwt token2
see this exemple :
sudo docker run --rm -it portswigger/sig2n eyJraWQiOiI2YTFjN2U0MC00ODU0LTQxYTMtYTU3OC0wNDVjYzBjYmYzZTIiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTc1MTU1OTk2Mywic3ViIjoid2llbmVyIn0.Zg0CXJf4PSw0-Cc4GsqYp4bJyvnilDpRhTBWCYhat86vTEtaaFVam_Km1c4bhcUzRcf2KZOEpsrDhB6u5eImWvH55WepyJh1g8aIND8bo8_W-1vqLSnNerm1Zw4h1hUZXWWK1QxqMGFlwkaJhR50CBLi8MrXjlMVtvoxtZDaicctPnI17gc-JGpsbPrZ1HrfYo4mlFlqotQmh0Pub-Yc-wZIXogetdm51PtQKfktNgjPdiG7ixqYymgeZITPl9OGuF24E782QC2i42B5dGBgZwzVN1fQonMfZcsqrnEb2l4MwugXN0n_m3SN28HBorXT35OuiWrAyUwKlvc-okylOg eyJraWQiOiI2YTFjN2U0MC00ODU0LTQxYTMtYTU3OC0wNDVjYzBjYmYzZTIiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTc1MTU2MDAxMSwic3ViIjoid2llbmVyIn0.WWUFuadm1IDAKWz0c5KZGnQYDGEhb0vaTPPb6Vnul7FVIpM394b-Cm7eh5eh-Y_Qx5efxISB_AW37d3fqmckzue3_28P5PI-Vnw2kU2dTvrOVT7domRhzqA1JgkrM0VeuBD7ejeustrKCKdsKNBWFbr2J9u7tQkQol2zO7U-hwv-ku4joFhQXWSe79czsHhpXCMrO1sR5tgEbyBIAKP5OC7ltQXJYYPITJzFW43pRH3uCz_ncQDxra_sJupqJr1ZwF0BUpmqEHgmuy78TRjD4difjCPsqEdrstGUtYhrLmhOMYj103DcA4yJoQwAQZHoP6qk_pkLu6c9BlSjwA5TfA
[sudo] password for anas:
Running command: python3 jwt_forgery.py <token1> <token2>AFTER
Running command: python3 jwt_forgery.py <token1> <token2>
Found n with multiplier 1:
Base64 encoded x509 key: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRkZrMmtrM3lneElZazE3YmZQNXp2ZApVQUtRZG9GRE5FdWFOelkweWFrNEN3TC9VQnFybkc3MUY2ZkIzNERqRUpNN0xDQ3ZuYThaUDBseHVMZnNxLy9DCmhvalRTc0doTU01cE9EV2VxQkFmVUhVbytMczJkL1pGY2VHQ2cwNkx0NjhaeURORHBuUk5tNkZtQ2Y0dUFCc28KVFpqeTl0cjkzbEdnZi9tREdqS2xZK2IzTnJHNDFhT2xnRXhRY1FKcjF2YVN3SFRXYzRJYzJoRDR5SEw1dElZVgpzWTBkazRMVStjdmQ5V1paWmFzNlltc1pMK1QxS3U1ck0yZzd0enUzOEh1ZUNINXpzM2M3am1XV0F0VGtSMkF4ClRJQjYrdVhvY0tvZUp6YUdsUFUvdXNrTFNOTlk0azVlcm5ObjBJYTd0TUxVQk1RRHIwYk5kNjhBRDErdWduREsKOWdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==
Tampered JWT: eyJraWQiOiI2YTFjN2U0MC00ODU0LTQxYTMtYTU3OC0wNDVjYzBjYmYzZTIiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiAicG9ydHN3aWdnZXIiLCAiZXhwIjogMTc1MTY0MjkyNCwgInN1YiI6ICJ3aWVuZXIifQ.yu7YNqr5US1NsDMRYkwby0DSqN8jnL2oRdfzb79KZT8
Base64 encoded pkcs1 key: LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFGRmsya2szeWd4SVlrMTdiZlA1enZkVUFLUWRvRkRORXVhTnpZMHlhazRDd0wvVUJxcm5HNzEKRjZmQjM0RGpFSk03TENDdm5hOFpQMGx4dUxmc3EvL0Nob2pUU3NHaE1NNXBPRFdlcUJBZlVIVW8rTHMyZC9aRgpjZUdDZzA2THQ2OFp5RE5EcG5STm02Rm1DZjR1QUJzb1Raank5dHI5M2xHZ2YvbURHaktsWStiM05yRzQxYU9sCmdFeFFjUUpyMXZhU3dIVFdjNEljMmhENHlITDV0SVlWc1kwZGs0TFUrY3ZkOVdaWlphczZZbXNaTCtUMUt1NXIKTTJnN3R6dTM4SHVlQ0g1enMzYzdqbVdXQXRUa1IyQXhUSUI2K3VYb2NLb2VKemFHbFBVL3Vza0xTTk5ZNGs1ZQpybk5uMElhN3RNTFVCTVFEcjBiTmQ2OEFEMSt1Z25ESzlnSURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K
Tampered JWT: eyJraWQiOiI2YTFjN2U0MC00ODU0LTQxYTMtYTU3OC0wNDVjYzBjYmYzZTIiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiAicG9ydHN3aWdnZXIiLCAiZXhwIjogMTc1MTY0MjkyNCwgInN1YiI6ICJ3aWVuZXIifQ.bMEVhDUCco4hYvsxhF3ROpNr9Ll9FwzkQZnEbk4xRno
Found n with multiplier 2:
Base64 encoded x509 key: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRWl5YlNTYjVRWWtNU2E5dHZuODUzdQpxQUZJTzBDaG1pWE5HNXNhWk5TY0JZRi9xQTFWempkNmk5UGc3OEJ4aUVtZGxoQlh6dGVNbjZTNDNGdjJWZi9oClEwUnBwV0RRbUdjMG5CclBWQWdQcURxVWZGMmJPL3NpdVBEQlFhZEYyOWVNNUJtaDB6b216ZEN6QlA4WEFBMlUKSnN4NWUyMSs3eWpRUC96QmpSbFNzZk43bTFqY2F0SFN3Q1lvT0lFMTYzdEpZRHByT2NFT2JRaDhaRGw4MmtNSwoyTWFPeWNGcWZPWHUrck1zc3RXZE1UV01sL0o2bFhjMW1iUWQyNTNiK0QzUEJEODUyYnVkeHpMTEFXcHlJN0FZCnBrQTlmWEwwT0ZVUEU1dERTbnFmM1dTRnBHbXNjU2N2VnptejZFTmQybUZxQW1JQjE2Tm11OWVBQjYvWFFUaGwKZXdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==
Tampered JWT: eyJraWQiOiI2YTFjN2U0MC00ODU0LTQxYTMtYTU3OC0wNDVjYzBjYmYzZTIiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiAicG9ydHN3aWdnZXIiLCAiZXhwIjogMTc1MTY0MjkyNCwgInN1YiI6ICJ3aWVuZXIifQ.Ivhv-QLjFsOMyfzqbt4oY9gJTTjZQmaDwYT66VxfEtI
Base64 encoded pkcs1 key: LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFFaXliU1NiNVFZa01TYTl0dm44NTN1cUFGSU8wQ2htaVhORzVzYVpOU2NCWUYvcUExVnpqZDYKaTlQZzc4QnhpRW1kbGhCWHp0ZU1uNlM0M0Z2MlZmL2hRMFJwcFdEUW1HYzBuQnJQVkFnUHFEcVVmRjJiTy9zaQp1UERCUWFkRjI5ZU01Qm1oMHpvbXpkQ3pCUDhYQUEyVUpzeDVlMjErN3lqUVAvekJqUmxTc2ZON20xamNhdEhTCndDWW9PSUUxNjN0SllEcHJPY0VPYlFoOFpEbDgya01LMk1hT3ljRnFmT1h1K3JNc3N0V2RNVFdNbC9KNmxYYzEKbWJRZDI1M2IrRDNQQkQ4NTJidWR4ekxMQVdweUk3QVlwa0E5ZlhMME9GVVBFNXREU25xZjNXU0ZwR21zY1NjdgpWem16NkVOZDJtRnFBbUlCMTZObXU5ZUFCNi9YUVRobGV3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K
Tampered JWT: eyJraWQiOiI2YTFjN2U0MC00ODU0LTQxYTMtYTU3OC0wNDVjYzBjYmYzZTIiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiAicG9ydHN3aWdnZXIiLCAiZXhwIjogMTc1MTY0MjkyNCwgInN1YiI6ICJ3aWVuZXIifQ.kV70rzb9lRGaDwhtwVe0tDQubzSnS80gVD7WbNfO3Q0
...etc
So il faut tester all Tampered JWT If the request with the tampered JWT returns 200 OK, it means the server accepted it. So you can take the Base64-encoded x509 key that matched, and use it to create a new symmetric key in your JWT editor. Then you can forge a new JWT with any payload you want (for example, set "role": "admin"). Finally, sign it using HS256 with the symmetric key you just created (based on the server’s public key). This new forged token can now be used to bypass access controls and gain admin privileges.
sig2n used the two JWTs you provided. It calculated the value of n (the RSA modulus) for the server’s public key. It generated the server’s public key for you in standard formats (x509 and PKCS1). Then it forged a new JWT signed using HS256 with the public key used as the secret. This tampered JWT can be sent to the vulnerable server to bypass verification if the server is vulnerable to algorithm confusion.
AFTER
Take the tampered JWT that was generated. Load it into Burp Repeater. Replace the Cookie or Authorization header with this JWT. Send the request to the server. Check if the server accepts it. If it does → you have control!