You don’t need the private key to break the system — just a crack in the logic. Real hackers don’t guess… they understand.
~ Aditya Bhatt
After days of intense lab break-ins, PoC crafting, and diving headfirst into JWT madness — we’ve arrived. This is the final chapter in my “Cracking JWTs: A Bug Bounty Hunter’s Guide” series.
In this ultimate write-up, we deal with JWT algorithm confusion — no kid, no jwk, no jku, and no exposed key. Just pure logic abuse, math trickery, and Burp wizardry to pop admin without the private key. This is where 🔐 security meets misconfiguration, and we turn it into a full-blown exploit.
Whether you’re a beginner bug hunter or a seasoned red teamer, this one’s gonna hit hard. Let’s go full throttle. 🧠⚡
JSON Web Tokens (JWTs) are the backbone of modern web auth — fast, stateless, and compact. But if you don’t enforce how the server verifies JWTs… attackers like us can twist that logic. Today’s lab from PortSwigger shows how we bypass authentication via JWT algorithm confusion — no key leaks required. Just clever use of public keys, alg header, and 💣 HMAC abuse.
Let’s pop the hood and rewrite the rules. 🔐🧠
JWTs can be signed with:
RS256: Asymmetric (Public/Private RSA)HS256: Symmetric (Shared Secret HMAC)
Algorithm confusion happens when:
A server configured for RS256 wrongly accepts HS256 and uses the RSA public key as the HMAC secret.
What happens then?
✅ You can forge any JWT
✅ Bypass auth
✅ Get admin access
✅ No private key required
Just some twisted header values and a server that trusts too much.💀
- Type: JWT Authentication Bypass
- Weakness: Algorithm Confusion (RS256 → HS256)
- Impact: Admin Access, Account Deletion
- CVSS Analogy: Improper Authorization via Algorithm Trust
- Real-World Severity: 🔴 P1 — Critical
Let’s recreate the lab and walk through the exact exploit chain.
Visit: https://portswigger.net/web-security/jwt/algorithm-confusion/lab-jwt-authentication-bypass-via-algorithm-confusion-with-no-exposed-key Login with: wiener:peter
Modify the /my-account request to /admin. You see:
“Admin interface only available if logged in as an administrator.”
- Logout, then log in again.
- Capture both sessions’ JWTs from the
sessioncookie. - Save them for public key derivation.
Use Docker’s sig2n tool to brute-force the public key:
docker run --rm -it portswigger/sig2n <JWT1> <JWT2>This outputs:
- Possible
nvalues (modulus) - Base64-encoded X.509 public key
- Tampered JWTs signed using that key
- Paste each tampered JWT into the
sessioncookie. - Send a request to
/my-account.
✅ If you get a 200 OK → This is the correct key.
🚫 If you get a 302 Redirect to /login → Try the next.
- Copy the Base64 X.509 key from the valid tampered JWT.
- In JWT Editor > Keys tab → New Symmetric Key.
- Set the
kvalue to the Base64 public key.
- In Burp Repeater > JSON Web Token tab:
- Change
subclaim toadministrator - Set
algtoHS256 - Click Sign → Choose the newly created key
- Ensure “Don’t modify header” is checked
And Voila! 🪄 You now have admin access!
Send a request to: /admin/delete?username=carlos
Right-click → Show in browser → Paste the response URL. Lab solved ✔️
- Never trust the
algfield from untrusted JWTs. - Fix the algorithm server-side — don’t allow fallback to
HS256. - Public keys are public. Don’t treat them as secrets.
- A secure algo like RSA is only as secure as its implementation.
This lab brings the whole JWT journey full circle. You don’t need the private key to break an app — just one bad decision by the developer.
With this, our JWT series ends with a bang 💥 But your bounty journey? It’s just getting started.
Until the next exploit.
Happy Hacking!
~ Aditya Bhatt 🧠