JWTweak v2.1 – A Guided, Offline Toolkit for Modern JWT Attacks
Introduction
JSON Web Tokens sit at the heart of modern authentication – and because the token travels in the user’s hands, a single weak check on the server side can hand an attacker an admin account. JWTweak was built to test for exactly these flaws. It started as a small utility to switch a token’s algorithm and re-issue it in seconds, helping security enthusiasts hunt for issues like the JWT Algorithm Confusion Attack. Version 2.1 is a complete rewrite into a guided, menu-driven toolkit: you paste a token, it decodes and risk-analyses it, recommends the attacks that fit, and walks you through each one – entirely offline, with no flags to memorise. In this post we’ll tour the tool and then break into a deliberately vulnerable app with two live proof-of-concept attacks.Requirements
Python 3.8+ (tested on Kali and macOS)
pip3 install pyjwt cryptography rich
PyJWT and cryptography are required; rich is optional and simply powers the enhanced terminal interface – the tool falls back to clean plain text without it.
pip3 install pyjwt cryptography rich
PyJWT and cryptography are required; rich is optional and simply powers the enhanced terminal interface – the tool falls back to clean plain text without it.
Features
- Detects the algorithm of the input JWT and pretty-prints the header and payload
- Built-in risk analysis (flags ‘none’ / empty algorithm, weak HMAC, jku / jwk / x5u / kid headers, and missing or expired expiry)
- Generates ‘alg:none’ tokens in four casings (none / None / NONE / nOnE)
- Algorithm Confusion Attack – signs an HS256 token using the target’s RSA/EC public key as the HMAC secret
- Re-signs tokens with HS256/384/512, RS256/384/512, PS256/384/512, ES256/384/512 or EdDSA
- Key-resolution header injection: jwk (CVE-2018-0114), jku, x5u and x5c – with an optional built-in local server to host a malicious JWKS/cert offline
- kid injection – path traversal, SQL injection and command-injection payloads
- Interactive claim tampering that chains straight into any signing attack
- Offline HMAC secret cracking with a wordlist, then a one-click forge using the recovered secret
- ‘Run recommended suite’ automation that generates every applicable token and saves them for replay in Burp or a fuzzer
Download Link - JWTweak.py (or clone the full project from GitHub)
Meet the Target
The project ships a small, deliberately vulnerable web app in the poc/ folder – “Aegis Cloud” – so you can watch the attacks land against a realistic login → dashboard → admin console flow, safely and on your own machine. It makes two classic mistakes on purpose: it trusts ‘alg:none’, and it verifies with a single public key while also accepting HS* – mis-using that public key as an HMAC secret. Spin it up:
cd poc pip install -r requirements.txt python3 vulnerable_server.py # http://127.0.0.1:5000
Open http://127.0.0.1:5000 and sign in – the demo credentials are prefilled. You land on a dashboard that shows your session token and your role: user.
Click Open Admin Console with this normal token and you are correctly turned away with a 403 Access denied. That refusal is our baseline – each attack below flips it into a full admin session.
POC 1 – The ‘alg:none’ Trick
The oldest trick in the book still works on plenty of implementations: set the algorithm to ‘none’, drop the signature, and dare the server to verify nothing. Launch JWTweak, and when it asks for a token, paste the session token you copied from the dashboard. Then follow the menu – a (claim tampering) → c (make admin) → s (finish) → y (apply) → n (emit an alg:none copy):
python3 ../JWTweak.py
Copy the forged token, paste it into the dashboard’s Session token box, and open the Admin Console. The server happily accepts an unsigned, self-issued admin token – and we’re in.
POC 2 – Algorithm Confusion (RS256 → HS256)
This is the classic that JWTweak was born for. The server expects RS256 tokens verified with its RSA public key – but its code also accepts HS256, and when it does, it feeds that same public key in as the HMAC secret. The public key is, by definition, public, so an attacker can forge a signature the server will trust. First grab the key exactly as an attacker would (many apps expose it at a /jwks or .pem endpoint):
curl -s http://127.0.0.1:5000/public_key.pem -o public_key.pem
Run JWTweak again, paste your user session token, then work the menu – a → c → s → y → skip to escalate to admin, then 3 (Algorithm confusion) and provide public_key.pem when prompted:
Paste this HS256 token into the dashboard and open the Admin Console. Accepted again – only this time the signature is cryptographically valid, forged from nothing but public information.
Why These Attacks Work
Both PoCs share one root cause: the server let the token decide how it would be verified. The algorithm, the kid, the jku/jwk – all of it is attacker-controlled, yet vulnerable code feeds it straight into the verification path. ‘alg:none’ disables verification, and algorithm confusion swaps the algorithm so the server checks the wrong thing with the wrong key. In every case, the attacker is quietly choosing the rules the server will check its own security against.
How to Fix It
- Pin the algorithm. Pass an explicit allow-list to your verify call; never read the algorithm from the token’s own header.
- Never cross key types. Keep symmetric secrets and asymmetric keys separate – a public key must never be usable as an HMAC secret.
- Reject ‘none’. Do not accept unsecured JWTs.
- Ignore untrusted key headers. Don’t honour jwk, jku or x5u from incoming tokens; resolve keys from a trusted server-side store and match kid exactly.
- Use strong secrets and enforce claims. Make HMAC secrets long and random, and always validate expiry (and nbf / aud / iss where relevant).
[Disclaimer - For Education and Ethical Security Testing Purpose - Case study, attacks' scenarios and audit guidelines on vulnerabilities]









Comments
Post a Comment