Home Notes | Web | JWT
Post
Cancel

Notes | Web | JWT

Introduction

JSON Web Tokens (JWTs) have become a standard for transmitting cryptographically signed JSON data between systems. Primarily used for authentication, session handling, and access control, JWTs offer a decentralized approach, storing necessary information client-side. This guide will delve into the format, components, security, potential attacks, and countermeasures associated with JWTs.

JWT Format

A JWT comprises three parts (base64 encoded): a header, a payload, and a signature, separated by dots. The header contains metadata, while the payload holds user claims. The signature, derived from hashing the header and payload, ensures data integrity and authenticity.

Example JWT:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsImV4cCI6MTUxNjI0OTAyMn0.bVZZls9tsMF0muy1gw5LH5depDZmRCp7iykkdhVewD4

Decoding the payload reveals claims:

1
2
3
4
5
{
  "name": "John Doe",
  "iat": 1516239022,
  "exp": 1516249022
}

JWT Signature

The server generates the signature by hashing the header and payload, enhancing security. A compromised signature jeopardizes data integrity and authenticity. Proper signature verification is crucial for a robust JWT mechanism.

JWT vs JWS vs JWE

JWT, as a specification, is extended by JSON Web Signature (JWS) and JSON Web Encryption (JWE). JWTs are often synonymous with JWS tokens, where JWEs encrypt token contents.

JWT Attacks

JWT attacks involve manipulating tokens to bypass authentication and access controls. Successful attacks can lead to privilege escalation and impersonation.

Impact

JWT attacks can have severe consequences, granting attackers unauthorized access and control over user accounts.

Vulnerabilities

Flawed JWT handling in applications introduces vulnerabilities. Common issues include improper signature verification, accepting unsigned tokens, and weak key management.

Exploiting Flaws

Exploiting flawed signature verification allows attackers to modify token values, potentially leading to unauthorized access and privilege escalation.
Example:

1
2
3
4
{
    "username": "guest",
    "isAdmin": false
}

If the “username” is used to identify sessions, modifying it would allow us to impersonate a user. Similarly, the “isAdmin” parameter could be used for access control. Setting “isAdmin” to true could allow us to perform privilege escalation.

Accepting Tokens with No Signature

Servers trusting tokens without signatures (unsecured JWTs) can be exploited by attackers, bypassing security measures. If the server does not verify the signature, we can set the “alg” parameter in the header to “none”.

1
2
3
4
{
    "alg": "none",
    "typ": "JWT"
}

Note that we still need to add a dot at the end of the payload even if there is no signature.

Brute-forcing Secret Keys

Weakly managed secret keys, especially in algorithms like HS256, pose a threat. Developers may overlook changing default or placeholder secrets, enabling attackers to brute-force keys.

You can brute-force it using Hashcat.

1
hashcat -a 0 -m 16500 <jwt> <wordlist>

One you know the secret, you can use it to sign your own tokens.

I recommend using jwt.io (really good to understand jwt format) or the JWT Editor extension of Burp Suite which is a very powerful tool.

Header Parameter Injections

User-controllable parameters like jwk, jku, and kid can be exploited to inject self-signed JWTs or manipulate key references, compromising security.

  • jwk (JSON Web Key) - Provides an embedded JSON object representing the key.
  • jku (JSON Web Key Set URL) - Provides a URL from which servers can fetch a set of keys containing the correct key.
  • kid (Key ID) - Provides an ID that servers can use to identify the correct key in cases where there are multiple keys to choose from. Depending on the format of the key, this may have a matching kid parameter.

JWK

A JWK (JSON Web Key) is a standardized format for representing keys as a JSON object.

Example:

1
2
3
4
5
6
7
8
9
10
11
{
    "kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",
    "typ": "JWT",
    "alg": "RS256",
    "jwk": {
        "kty": "RSA",
        "e": "AQAB",
        "kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",
        "n": "yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9m"
    }
}

Server Behavior: Misconfigured servers may use any key embedded in the jwk parameter.
Exploitation: Exploit by signing a modified JWT using your RSA private key and embedding the matching public key in the jwk header.

You can use JWT Editor extension on burp suite to facilitate this process.

JKU

Instead of embedding public keys with the jwk header parameter, some servers allow the use of the jku (JWK Set URL) header parameter.

A JWK Set is a JSON object containing an array of JWKs representing different keys. You can see an example of this below.

If the app is misconfigured, JWK Sets may be publicly exposed via standard endpoints like /.well-known/jwks.json

If you can modify it, you can add your own public key and sign your token with your own private key. If you specify this key with the jkw parameter, the server will use it to decypher your token.

Kid

Servers may use the kid (Key ID) parameter in the JWT header to identify which key to use during signature verification.
The kid parameter may point to a specific entry in a database, a file name, or any arbitrary string.

Directory Traversal

If the kid parameter is vulnerable to directory traversal, an attacker could force the server to use an arbitrary file as the verification key.

Example:

1
2
3
4
5
6
{
    "kid": "../../path/to/file",
    "typ": "JWT",
    "alg": "HS256",
    "k": "asGsADas3421-dfh9DGN-AFDFDbasfd8-anfjkvc"
}

If the server supports symmetrically signed JWTs, an attacker might point to a predictable file, signing the JWT with a secret matching the file’s contents. “/dev/null” is perfect for this as it is empty so easily predictable.

Other Interesting Parameters

Parameters like cty and x5c may introduce additional attack vectors, including content type manipulation (leading to potential XXE or deserialisation problem) and injection of self-signed certificates.

JWT Algorithm Confusion

Even with robust secrets, attackers might forge valid JWTs by signing tokens using unexpected algorithms (algorithm confusion attack).

Prevention Measures

Use up-to-date JWT libraries and ensure developers understand their security implications.
Perform robust signature verification, accounting for unexpected algorithms.
Enforce a strict whitelist for permitted hosts in the jku header.
Ensure no path traversal or SQL injection vulnerabilities via the kid header.

Best Practices for JWT Handling

Always set an expiration date for issued tokens.
Avoid sending tokens in URL parameters when possible.
Include the aud (audience) claim to specify the intended recipient, preventing use on different websites. Enable token revocation on server logout.

Note: Adhering to these best practices helps prevent vulnerabilities associated with JWTs.

This post is licensed under CC BY 4.0 by the author.