Hello! Welcome back to our course on penetration testing and bug bounty hunting.
In our previous lesson, we thoroughly examined the anatomy of a JSON Web Token. You learned how to deconstruct a JWT into its three core components: the header, payload, and signature. We established that the signature's primary role is to guarantee the token's integrity, not its confidentiality.
Today, we're taking the next logical step: breaking that integrity. This lesson focuses on the learning outcome: Exploit JWT vulnerabilities such as weak secrets, algorithm confusion (alg=none), and signature stripping. We will explore three common but critical implementation flaws that can allow an attacker to bypass authentication, escalate privileges, and take over user accounts. These are fundamental skills for any web application pentester.
1. The Root of the Problem: Trusting User Input
All the vulnerabilities we'll discuss today stem from a single, classic security mistake: the server implicitly trusts metadata sent from the client. Specifically, the server trusts the alg (algorithm) parameter in the JWT header. As you'll see, an attacker who can control the algorithm used for verification can often bypass the signature check entirely.
2. Attack #1: Signature Stripping via the none Algorithm
The JWT specification includes an option for an unsecured JWT where the alg parameter is set to none. This means the token has no signature. While intended for situations where the token's integrity is verified by other means, if a server's JWT library is misconfigured to accept tokens with alg: "none", it creates a critical vulnerability.
An attacker can simply take a valid JWT, decode it, change the payload claims (e.g., set "admin": true), modify the header to {"alg": "none"}, and resubmit it without a signature. The server, trusting the header, would "verify" the token by doing nothing, granting access based on the forged claims.
Bypass JWT Signature via Flawed Authentication | Access Admin Panel |
To see this attack in practice, let's watch a walkthrough from the YouTube channel Medusa. This video provides a clear, step-by-step demonstration using Burp Suite.
Watch from 01:39 to 05:02. Pay close attention to these two critical steps: Modifying the alg parameter in the header to none and changing the sub claim to administrator. Removing the signature part of the token. Notice how the attack fails until the signature is completely removed, leaving only header.payload. (with the trailing dot).
As demonstrated, the practical steps are:
- Intercept a request containing a JWT.
- Send the request to a tool like Burp Repeater.
- Decode the JWT's header and payload.
- Change the
algvalue in the header tonone(case-insensitivity might also work, e.g.,None,nOnE). - Modify the payload claims as desired (e.g., change user ID, role, etc.).
- Re-encode the header and payload.
- Construct the new token by joining the modified header and payload with a dot, and then adding a final dot but omitting the signature entirely.
- Send the modified request with the forged token.
This is often one of the first things to test for when you encounter a JWT.
3. Attack #2: Cracking Weak Symmetric Secrets
When a token uses a symmetric algorithm like HS256, both the server and the token creator use the same single secret key. If this key is weak, guessable, or a default value, an attacker can brute-force it.
Once an attacker discovers the secret key, they have complete control. They can create and sign tokens with any payload they wish, making them indistinguishable from tokens generated by the server.
This Tiny JWT Mistake = Massive Bug Bounty
Let's watch this clip from NahamSec, which explains the concept of cracking weak HS256 secrets.
Watch from 01:41 to 02:16. Focus on the idea that developers sometimes use weak or default secrets, which can be found using common wordlists.
How to Brute-Force a Secret
You can use tools like hashcat to perform an offline brute-force attack. Since this doesn't require sending requests to the server, it is fast and stealthy.
JWT attacks | Web Security Academy
The Web Security Academy by PortSwigger provides a concise guide on using hashcat for this purpose. This is a practical skill you'll use often.
Read the section titled 'Brute-forcing secret keys'. Pay close attention to the hashcat command provided. This shows you how to use a wordlist to find the secret from a captured JWT.
The process is straightforward:
- Obtain a valid JWT signed with
HS256from the application. - Save the full JWT string to a file.
- Use a tool like
hashcatwith a wordlist of common secrets (like the one fromjwt.secrets.listmentioned in the article, or evenrockyou.txt).- The command is:
hashcat -a 0 -m 16500 <your-jwt-file> <your-wordlist-file>
- The command is:
- If
hashcatfinds a match, it will output the secret key. - With the secret key, you can now use a tool (or a script) to forge a new token with a modified payload and sign it with the cracked key. Websites like
jwt.ioare also great for this; you can paste the decoded parts and the secret, and it will generate the new signature.
Test your understanding!
You are testing an application and capture the following JWT, which is signed with HS256:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIiLCJyb2xlIjoidXNlciIsImlhdCI6MTYxNjIzOTAyMn0.tExS2H5b8yRTQzVNoC2myFk1bnpvumV4yzzc2Ci0Asw
You suspect the developer used a weak secret. Your goal is to gain admin access. Outline the steps you would take, including the specific hashcat mode you would use.
Show answer
- Save the Token: Save the entire JWT string to a file, for example,
token.txt. - Get a Wordlist: Obtain a wordlist of common passwords/secrets, such as
rockyou.txtor a specialized JWT secret list. - Run Hashcat: Use
hashcatto brute-force the secret. The mode for JWTs is16500. The command would be:
hashcat -a 0 -m 16500 token.txt /path/to/wordlist.txt - Crack the Secret: Let's assume
hashcatsuccessfully cracks the secret and reveals it to bepassword123. - Forge a New Token:
- Go to
jwt.io. - Keep the header as
{"alg": "HS256", "typ": "JWT"}. - Change the payload to
{"username": "user", "role": "admin", "iat": 1616239022}. - In the "Verify Signature" section, enter the cracked secret
password123. - Copy the new, fully-formed JWT.
- Go to
- Use the Forged Token: Replace the original JWT in your browser or Burp Suite with the newly forged admin token and make a request to an admin-only resource.
4. Attack #3: Algorithm Confusion (RS256 to HS256)
This attack is more subtle and powerful. It exploits a flaw in how some libraries handle tokens signed with asymmetric algorithms (like RS256) versus symmetric ones (HS256).
Here's the breakdown:
- Normal RS256 Verification: The server signs the JWT with its private key. To verify it, the server uses the corresponding public key. The public key is often made available to clients (e.g., at a
/.well-known/jwks.jsonendpoint). - The Attack: An attacker takes a token signed with
RS256, changes thealgin the header toHS256, and then signs the token using the server's public key as the secret. - The Flaw: When the misconfigured server receives this token, it sees
alg: "HS256". It now expects a symmetrically signed token. The library's verification function looks for the secret key to use. Instead of its private key, it fetches what it thinks is the right key for this token—which is the public key. It then uses this public key to validate theHS256signature. - Since the attacker also used the public key to sign the token, the signature verification succeeds.
This Tiny JWT Mistake = Massive Bug Bounty
This is a tricky concept to grasp initially. NahamSec does an excellent job of explaining it with a clear visual aid.
Watch from 02:16 to 03:26. Focus on the core confusion: the server is tricked into using the public key as the secret for an HS256 signature verification.
The key steps for this attack are:
- Obtain a JWT from the target that is signed with
RS256. - Find the server's public key. This is often exposed at a well-known endpoint like
/jwks.json,/certs, or may be hardcoded in client-side JavaScript files. - Modify the JWT's header, changing the
algfromRS256toHS256. - Modify the payload claims as desired.
- Sign the new token using the
HS256algorithm, providing the server's public key as the secret. - Submit this forged token to the application.
Conclusion
You've now learned three powerful techniques for exploiting JWTs by attacking the signature verification process. These are not theoretical attacks; they are found regularly in bug bounty programs and penetration tests, often with high impact.
Key Takeaways:
- Signature Stripping (
alg=none): A simple but effective attack where you tell the server there is no signature to check. Remember to remove the signature part of the token. - Weak Secrets: For symmetric algorithms (
HS256), a weak secret is a fatal flaw. Use tools likehashcatto crack them offline. - Algorithm Confusion: A more advanced attack where you trick the server into using its public key as the secret for a symmetric signature check.
- The fundamental rule for developers is: never trust the
algheader from a client-side token. The server should always enforce a specific, expected algorithm.
Next Lesson Preview:
We have focused on attacking the authentication token itself. In the next lesson, we will shift our focus to a different class of vulnerability that exploits ambiguities in how servers process HTTP requests. You will learn to identify and exploit HTTP Request Smuggling vulnerabilities, a powerful technique used to bypass security controls, poison web caches, and access internal systems.