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 ctfpalAn 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 candidateOnce 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.