Log in Join

JWT Attacks

A verifier that trusts the algorithm a token claims for itself, rather than enforcing one server-side.

What it is

JSON Web Tokens carry their own signing algorithm in the header, and a verifier that trusts that header rather than enforcing one algorithm itself hands an attacker several ways to forge a token.

How it works

$decoded = JWT::decode($token, $key, ['HS256', 'RS256', 'none']);

Two classic footguns: accepting alg: none (no signature required at all), and accepting both an asymmetric algorithm (RS256, verified with a public key) and a symmetric one (HS256, verified with that same value as a shared secret). Since an RS256 public key is public by definition, an attacker who has it can sign an HS256 token with it and have the verifier accept the forgery as if it were legitimately RS256-signed.

Real-world impact

Complete authentication bypass: a forged token with arbitrary claims, such as any user id or role, is accepted as fully valid.

How to prevent it

$decoded = JWT::decode($token, $key, ['RS256']); // exactly one, chosen server-side

Pin the verifier to exactly one expected algorithm, chosen by the server, never read from the incoming token's own header, and never let a single verifier accept both a symmetric and an asymmetric algorithm for the same key material.

Labs in this topic

Easy

TicketFlow alg-none forgery

An internal help-desk system. The token verifier accepts whatever algorithm the token's header claims, including none.

1 solve

Medium

SkyView RS256/HS256 key confusion

A drone-fleet dispatch console. The RS256 verifier also accepts HS256, using the same public key as the HMAC secret.

1 solve