Breaking JWT Authentication: Algorithm Confusion Attacks in the Wild
Overview
During a recent penetration test of a multi-tenant SaaS platform, we discovered a critical JWT algorithm confusion vulnerability that allowed complete authentication bypass. This post details the discovery, exploitation, and remediation of this finding.
The Discovery
The application used RS256 (asymmetric) JWT tokens for authentication. During our initial reconnaissance, we noticed the server's public key was exposed via a /.well-known/jwks.json endpoint — standard practice for OIDC implementations.
However, when we modified a token's alg header from RS256 to HS256 and signed it using the public key as the HMAC secret, the server accepted it as valid.
Why This Works
The vulnerability exists because the JWT verification library was configured to accept multiple algorithms. When it encountered an HS256 token, it used the same key material (the RSA public key) as the HMAC symmetric secret — a key that is, by definition, public.
# Forging a token using the public key as HMAC secretpublic_key = open('public_key.pem').read() forged_token = jwt.encode( {"sub": "admin", "role": "superadmin", "tenant": "*"}, public_key, algorithm="HS256" ) ```
Impact
- Authenticate as any user across any tenant
- Escalate to superadmin privileges
- Access and modify data for all 2,400+ tenant organizations
Remediation
- **Pin the algorithm** — Never allow the token to dictate which algorithm is used for verification
- **Use separate key stores** — Asymmetric and symmetric keys should never be interchangeable
- **Validate the `alg` header** — Reject tokens with unexpected algorithm values
Key Takeaway
This class of vulnerability remains surprisingly common. If your application uses JWTs, audit your verification logic — ensure the algorithm is enforced server-side, not derived from the token itself.
Want us to test your defenses?
Our research feeds directly into our offensive security engagements. Let's find your vulnerabilities before attackers do.
Request a Pentest