JWTs Under the Microscope: How Attackers Exploit Authentication and Authorization Weaknesses
In modern web applications, JSON Web Tokens (JWT) have become a popular choice for authentication and authorization due to their simplicity and flexibility. However, while JWTs offer significant advantages, their improper implementation and validation can expose applications to serious security risks. A single vulnerability in how tokens are handled can lead to unauthorized access, data breaches, or even full system compromise.
JWT tokens provide a mechanism to implement stateless authentication, meaning that information regarding the authorization of a user is strictly stored on the client’s side. This eliminates the need for the server to store and retrieve session data for each request, offering a more scalable and efficient solution compared to using opaque session identifiers. JWTs allow two applications to exchange user information using JSON objects. To maintain the integrity of these JSON objects, the tokens would be signed using either a symmetric or asymmetric public/private key set. Thus, JWTs allow a self-contained authentication mechanism where the JSON object issued by the server could contain details regarding the user, the resource for which authorization was granted, and a duration for which the token is valid. By allowing stateless, token-based authentication, JWTs streamline user management across distributed systems, enabling seamless Single Sign-On (SSO) and enhancing scalability.
There are three components to a JWT token separated by <.> - header, payload and signature.
- The header is a Base64 encoded JSON object which contains details regarding the type of token, the algorithm used and the public key if any used to sign the token.
- The payload is also a Base64 encoded JSON object where each field called claim, contains details regarding the user, the resource granted access too and the validity of the token. The claims can be predefined or custom as per the server implementation.
- The signature is the hash obtained when the header and payload are signed using the algorithm and key. Hence changing any part of the payload would result in a different key generated.
JWT STRUCTURE: <HEADER>.<PAYLOAD>.<SIGNATURE>
From an attacker’s perspective, the first step would be to do a reconnaissance of the JWT and look at susceptible components. Before looking into each structure, the first validation to perform is to check if the JWT signature is verified. If a server accepts a JWT token after the signature has been tampered with, an addition or modification of any claim is possible. This vulnerability is called Improper JWT Signature Validation.
A JWT header once decoded contains the following information:
{
"alg": "RS256",
"typ": "JWT",
"kid": "key-id-12345",
"jku": "https://example.com/keys.json",
"x5u": "https://example.com/cert.pem",
"x5t": "abc123xyz456",
}
Among these the ALG field indicates the logic used to sign the JWT. Almost all JWTs are signed using a symmetric key algorithm such as HMAC or an asymmetric key algorithm such as RSA or ECDSA. What is sometimes overlooked by developers is that the JWT can also be unsigned i.e. by providing “alg”: “None”, indicating that there is no algorithm used and hence no hash generated. Without the hash, claims can be added/tampered in the JWT and there would be no way for the server to verify its integrity. Because the JWT has no verification, an attacker can modify the JWT however they like. The vulnerability can also be expanded to scenarios where servers accept HMAC signed tokens signed by the public key of an RSA signed JWT. The vulnerability where multiple algorithms are unintentionally allowed is called JWT Algorithm Confusion.
Even if a strong hashing algorithm is chosen, their ultimate strength in data confidentiality lies in choosing a random unguessable secret key. Many servers use commonly used secrets such as password, secret, admin to sign the JWTs leading to a JWT Weak Secret Vulnerability. Symmetric key algorithms i.e. algorithms using the same key for encryption and decryption, such as HS256 can be brute forced to find the secret key when it is of small/medium size. JWTs using symmetric key algorithms or having a small hash generated therefore have greater potential for exploitation. Hence it is recommended to use a secret of large size (as large as the hash) or an asymmetric key algorithm for applications
The KID field is used to identify the key used to sign the JWT if there are multiple keys present. If the field value is a string, it may be vulnerable to an SQL Injection Attack if the field value is directly used in a DB query without input validation. If the field value is a URL, it may be vulnerable to an SSRF Attack if whitelisting of the domain is not ensured along with other URL validations. If the field value is a file path, Path Traversal attack may be possible if file validations such as removal of (../) characters, navigation beyond web root folders is not forbidden.
The JKU field is a URL pointing to the collection of keys that can be used to verify the JWT encryption and hash by the server. A JKU Misuse Vulnerability can be exploited if the JKU field is replaced with a different URL pointing to a key set controlled by an attacker and the server verifies the new JWT token. Rigorous URL validation including domain whitelisting and path filtering must be ensured on any URL parameter to prevent such vulnerabilities.
The X5U field is a URL that points to a certificate used to verify the validity of JWT signature. So similar to JKU field exploitation, an attacker can sign the JWTs using their own private key and replace the X5U field with a URL pointing to their certificate.
The X5T field holds the hash of the certificate that was used to sign the JWT. It helps the server identify the specific certificate among the certificate collection. If a weak hashing algorithm such as SHA-1 is used, an attacker could exploit the collision property of algorithms (multiple certificates produce the same signature) to obtain a unique certificate. If an attacker is able to generate such a certificate and point to it via the X5U claim, they would be able to bypass certificate validation checks by the server.
Moving to the payload section:
{
"iss": "server.com",
"sub": "12344",
"aud": "payment.server.com",
"exp": 1731558400,
"nbf": 1731554800,
"iat": 1731551200,
"name": "John Doe",
"email": "john.doe@example.com",
"roles": ["user"],
"permissions": ["read"],
"scope": "openid profile"
}
The payload section of the JWT contains both predefined claims and well as public/customizable claims. The public claims would pertain to the user for which the JWT was generated so the first test would be to check if manipulation of any of these fields would return a different response by the server. If the manipulation of name or email renders information of another user, a Broken Object Level Authorization (BOLA) vulnerability would be exploited.
Another possible area of exploitation are the roles, permission and scope claims. If the user role was present in the JWT, change its value to [“admin”, "user"]. Similarly add write/delete value to the permission claim. If the server accepts the newly created JWT, a privilege escalation vulnerability - Broken Functional Level Authorization (BFLA) would be exploited.
The predefined claims in the payload are present to serve specific purposes so we can narrow our tests to certain scenarios. The IAT field indicates when the token was issued and EXP field indicates its expiry time, hence the most common test is to test if the token is valid beyond the expiry time mentioned, which if successful would result in a JWT Expired Token vulnerability. If the fields IAT and EXP are not present in the JWT, it would indicate that the JWT has no expiry which is a critical vulnerability. As a standard, tokens are issued for a duration of 60 minutes before expiry.
The NBF field indicates from what time the token should be valid. So another test would be to check if the token is valid before this resulting in a JWT NBF Claim not Validated vulnerability. There is another attack possible to manipulate the NBF time. Assume the server takes client date information as input to generate the NBF claim in the JWT. If the JWT is issued to be used 2 days from generation, changing the date on the client machine to 2 days into the future would result in the generation of a JWT that could be used today.
The audience claim is used to specify for which service the token was issued for. In a micro-service architecture application, authorization is usually done by a single service. If the audience claim is not mentioned, the JWT generated could be used to access other services in the application leading to a Cross Service Relay Attack. The aud claim is present to narrow down the scope of the JWT to specific services. Vulnerabilities such as ALBEAST arise when an attacker is able to configure a token for their own AWS tenant which could then be used on victim applications. Such attacks could be prevented with proper security configurations and validation of aud and signer claims.
In conclusion, while JWTs are secure, flexible and efficient, improper implementation and validation can introduce significant vulnerabilities, making them susceptible to a wide range of attacks such as impersonation, privilege escalation and full account takeover. To mitigate these risks, developers must follow best practices, including using strong cryptographic algorithms, thoroughly validating token fields, and ensuring proper input sanitization. By doing so, they can minimize the attack surface and protect their applications from malicious exploitation.