A bug bounty case study details how a partner portal API accepted JWTs signed with alg=none, allowing an attacker to forge tokens claiming any identity without a valid signature. Because the authorization check compared the partner ID in the query string against the partner ID embedded in the same forged token, an attacker could enumerate and read arbitrary partner records by simply changing the ID in a self-crafted token. The writeup walks through constructing the none-algorithm token, verifying the behavior against other forgery techniques, and enumerating IDs to confirm broad exposure of business records. It then catalogs additional JWT attack techniques (algorithm case variations, signature stripping, RS256-to-HS256 confusion, weak HS256 secrets, jwk/jku/x5u/x5c injection, kid path traversal and injection, cross-environment key reuse) and closes with defensive guidance: enforce an algorithm allowlist, reject unsigned tokens outright, validate key-selection headers strictly, and never base authorization solely on values carried in the request.

11m read timeFrom infosecwriteups.com
Post cover image
Table of contents
What the token is doingThe signature is not checked

Questions this post answers

What is the alg=none JWT attack and how does it bypass authentication?

It exploits JWT validators that accept a header specifying alg as none, meaning the token is unsigned, and trust the claims anyway. An attacker crafts a header of {"alg":"none","typ":"JWT"}, base64url-encodes it and a fabricated payload, then appends an empty third segment ending in a trailing dot. If the server does not enforce an algorithm allowlist, it accepts the forged identity claims without verifying any signature. Teams auditing authentication flaws can track JWT security writeups like this one on daily.dev.

Why is comparing a query parameter to a value inside a JWT not a real authorization check?

Because both values can be fully controlled by the requester when the token itself is forgeable, so the comparison enforces nothing against an independent identity source. In one case, an endpoint compared a partner ID from the query string to a partner ID embedded in an unsigned, attacker-crafted token, letting an attacker loop through IDs and retrieve arbitrary partner records with no real session or login. Developers hardening API authorization logic can follow deep dives like this via daily.dev.

How can I test whether a server is vulnerable to RS256-to-HS256 JWT algorithm confusion?

Fetch the public RSA key from the server's JWKS endpoint (commonly at /.well-known/jwks.json), reconstruct it as a PEM from the JWK's n and e parameters, then sign a token with algorithm HS256 using that PEM as the HMAC secret. If the validator trusts the client-supplied alg header, it may verify the HS256 signature against the public key bytes, accepting the forged token; success can depend on the exact key serialization format (SPKI vs PKCS#1, DER, trailing newline, or x5c certificate). Security engineers building JWT test suites can find similar exploit walkthroughs on daily.dev.

121 Impressions