{
  "category": "auth",
  "vuln_class": "JWT algorithm confusion",
  "title": "RS256 → HS256 algorithm confusion via public key as secret",
  "user": "Login flow returns a JWT in the Authorization header. Decoded header: {\"alg\":\"RS256\",\"typ\":\"JWT\"}. The /.well-known/jwks.json endpoint is publicly accessible and returns the RSA public key. Logged-in actions are authenticated by sending this JWT back.",
  "assistant": "RECON: server signs JWTs with RS256 (asymmetric: private key signs, public key verifies). The public key is exposed at /.well-known/jwks.json — this is normal and expected. The risk is whether the server's JWT library accepts an algorithm-switched token.\n\nHYPOTHESIS: JWT algorithm confusion. If the JWT verification code naively passes the token's alg header to the verifier function, an attacker can forge a token signed with HS256 (symmetric) using the PUBLIC KEY as the HMAC secret. The verifier will use the public key (which it knows) to verify the HMAC, and the signature will validate.\n\nTEST: minimal probe:\n1. Fetch the public key from /.well-known/jwks.json.\n2. Take an existing valid JWT, modify the payload (e.g. set `sub` to an admin user's identifier, or extend `exp`).\n3. Change the alg header to HS256.\n4. Sign the new token with HMAC-SHA256 using the public key PEM bytes as the secret.\n5. Send the forged JWT to a protected endpoint.\n\nINDICATOR: if the server accepts the forged token and returns the admin user's data (or honors the elevated claims), algorithm confusion is confirmed.\n\nSecondary checks to queue:\n- alg=none acceptance (set header alg=none, remove signature)\n- weak HS256 secret (offline crack with hashcat against common secrets)\n- kid (key ID) injection — SQL injection or path traversal in the kid header"
}
