Skip to content
All tools
TokensRuns locallyNo account

JWT secret brute force

Recover a weak HMAC signing secret from a JWT by testing a wordlist against the token’s own signature, in the browser.

Open in ctfpal

An HS256 token carries everything needed to test a candidate secret offline: the signed input is the header and payload you already hold, and the expected output is the signature. That makes secret recovery a pure local computation - no requests to the target, no rate limits, no detection.

Why it works so often

HMAC secrets are supposed to be long random keys. In practice they are secret, changeme, the framework’s documentation example, or the application’s name. A few thousand candidates covers a startling share of real deployments and nearly all CTF challenges.

signing_input = f"{header_b64}.{payload_b64}".encode()
for candidate in wordlist:
    mac = hmac.new(candidate.encode(), signing_input, hashlib.sha256).digest()
    if base64url(mac) == signature_b64:
        return candidate
The check ctfpal performs per candidate

Once you have the secret you are no longer forging - you are legitimately signing. Change any claim you like and re-sign; the token verifies because it genuinely is valid. That is a stronger position than an alg=none bypass, which only works against a broken verifier.

Common questions

Does brute forcing the secret alert the server?
No. Every candidate is tested against the signature you already have, entirely offline. The server sees nothing until you use the forged token.

Part of a module

6. Web attacks and session tokens

Read and forge JWTs and Flask sessions, find content nobody linked to, and probe for injection with detection payloads.

Practise on real challenges

Go deeper

Related tools