Attack a JWT

A JWT is only as trustworthy as the server's check of its signature. This playbook takes a token off a captured request, reads its claims, changes one, re-signs it, and fires the classic verification-bypass payloads β€” alg:none, a weak-secret guess, header injection β€” to find out which the server accepts. Budget about ten minutes.

Before you begin. Set up a project and scope for a host you're authorized to test (Set up an engagement), and capture a flow that carries a JWT β€” an Authorization: Bearer eyJ… header is the usual source. The examples target api.example.com.

1. Send a token to the JWT tab

The JWT tab is in the default tab set (hide it from Preferences if you never touch tokens, and reveal it again from the tab-bar β‹― menu or Ctrl-P β†’ Go to JWT). Find the token: open the captured flow in History, select the token text after Bearer in the request detail, and Space β†’ Send to JWT. That seeds a new JWT sub-tab and decodes the token live into its header, payload, and signature on the Decode lens.

The decode shows what the token claims; it never checks the signature, so a token that decodes cleanly is not necessarily one the server trusts. That is the question the rest of this playbook answers.

gori JWT tab with a decoded HS256 token: the INPUT token under a ^T:β†’ENCODE lens chip, the decoded header JSON, and an ATTACKS list of generated payloads including alg=none case variants and signature stripping
The JWT tab decodes a token live (header, payload, signature) and lists ready-to-send attack payloads: alg:none, weak-secret, and header injection.

Checkpoint. The JWT tab shows the token's header and payload as JSON, with the signature below.

2. Tamper a claim

Switch to the Encode lens with Ctrl-T, or press l to load the decoded token straight into the Encode editors. Edit the PAYLOAD JSON β€” escalate a role, swap a sub, extend an exp. Pick the algorithm with Ctrl-A (it cycles HS256 / HS384 / HS512 / none), set a SECRET when you're signing with an HMAC algorithm, and the re-signed token appears live in OUTPUT. Copy it with y.

The same claim edit runs headless, taking the token from the argument or stdin β€” --set KEY=VALUE patches one claim (repeatable), or --payload replaces the claims wholesale:

gori run jwt eyJhbGci... --encode --set role=admin --secret s3cret       # escalate one claim
gori run jwt eyJhbGci... --encode --payload '{"sub":"1","admin":true}' --secret s3cret

--set's value is JSON when it parses, so admin=true is a boolean and role=admin a string. Over MCP, jwt_encode takes the same set / payload edits.

Checkpoint. OUTPUT holds a token carrying your edited claim, re-signed with the algorithm and secret you chose.

3. Run the attack presets

You rarely know the secret, so let gori generate the bypass attempts instead. On the Decode lens, below the decoded parts, is a selectable list of attack payloads built from the token:

Attack What it tests
alg:none Strips the signature and sets alg to none (plus None / NONE case variants) β€” a server that accepts unsigned tokens.
Weak secret Re-signs with a list of common weak HMAC secrets β€” a guessable signing key.
Header injection Manipulates the kid, jku, x5u, and jwk header parameters β€” a server that trusts attacker-supplied key material.

Generate the same set headless:

gori run jwt eyJhbGci... --attacks

Over MCP the jwt_attacks tool returns the identical list (and jwt_decode / jwt_encode cover steps 1 and 2). All three are read tools available even under --read-only, since they touch no network.

Checkpoint. The ATTACKS list is populated with ready-to-send token variants.

4. Replay and confirm

A forged token proves nothing until the server sees it. Pick a payload β€” your tampered token from step 2, or a preset from step 3 β€” and send it to Repeater, swap it into the Authorization header of the captured request, and re-send with Ctrl-R. Read the status against what the endpoint should return for a bad token:

Checkpoint. You can tell an accepted forgery (a success status) from a rejected one (401 / 403), and you know which presets, if any, the server let through.

Next Steps