- When should you use JSON Web Tokens?
- What is JWT & how it can be exploited
- JWT's Subsystems
- Using a different bypassing approaches
- Attacks against Json Web Tokens
As an open standard, the JSON Web Token (JWT) defines a compact and self-contained method for securely transmitting information between parties as a JSON object (RFC 7519).
Because it has been digitally signed, this information can be trusted and verified. A secret (using the HMAC algorithm) or a public/private key pair (using RSA or ECDSA) can be used to sign JWTs.
In spite of the fact that JWTs are encryptable, we will only use signed tokens here.
Encrypted tokens, on the other hand, keep other parties from verifying the validity of claims contained within them. If a public/private key pair is used to sign a token, this signature also certifyes that only those who have access to the private key signed it.
When should you use JSON Web Tokens....?
Here are some scenarios where JSON Web Tokens are useful:
Authorization: This is the most common scenario for using JWT. Once the user is logged in, each subsequent request will include the JWT, allowing the user to access routes, services, and resources that are permitted with that token. Single Sign On is a feature that widely uses JWT nowadays, because of its small overhead and its ability to be easily used across different domains.
Information Exchange: JSON Web Tokens are a good way of securely transmitting information between parties. Because JWTs can be signed—for example, using public/private key pairs—you can be sure the senders are who they say they are. Additionally, as the signature is calculated using the header and the payload, you can also verify that the content hasn't been tampered with.
What is JWT - JSON web token & how it can be exploited.....?
JWT is a standard, meaning that all JWTs are tokens, but not all tokens are JWTs.
JWT is a open source service (API) that supports generating token based on client details and secret key.
Claims are used to transmit information between two parties.
JWTs are signed using a cryptographic algorithm to ensure that the claims cannot be altered after the token is issued.
JWTs are relatively small in size, a JWT can be sent through a URL, through a POST parameter, or inside an HTTP header, and it is transmitted quickly.
It stores information in an easy-to-access manner, both for developers and computers.
It can be used as a data format by any programming language and is quickly becoming the preferred syntax for APIs, surpassing XML.
A token is a string of data that represents something else, such as an identity.
In the case of authentication, a non-JWT-based token is a string of characters that allow the receiver to validate the sender’s identity.
A JWT is a string made up of three parts, separated by dots (.), and serialized using base64. In the most common serialization format, compact serialization, the JWT looks something like this: xxxxx.yyyyy.zzzzz
Example: The API consumer authenticates to the API provider with a username and password. The provider generates a JWT and sends it back to the consumer. The consumer adds the provided JWT to the Authorization header in all API requests.
- The header
- The payload.
- The signature.
The header contains metadata about the token, such as the algorithm used for the signature and the type of the token (which is simply JWT). For this example, the header before encoding is:
The most common algorithms used are HMAC and RSA algorithms.
The payload section contains the information that is actually used for access control. This section, too, is base64url encoded before being used in the token.
The signature is the part that is used to validate that the token has not been tampered with. It is calculated by concatenating the header with the payload, then signing with the algorithm specified in the header.
The complete token
You get the complete token by concatenating each section (header, payload, and signature) with a “.” in between each section.
Using Different Bypassing Approaches
When implemented correctly, JSON web tokens provide a secure way to identify the user since the data contained in the payload section cannot be tampered But if implemented incorrectly, there are ways that an attacker can bypass the security mechanism and forge arbitrary tokens.
1.Failing to verify the signature
Many JWT libraries provide one method to decode the token and another to verify it:
decode(): Only decodes the token from base64url encoding without verifying the signature.
verify(): Decodes the token and verifies the signature.
Sometimes developers might mix up these methods. In that case, the signature is never verified and the application will accept any token (in a valid format). Developers might also disable signature verification for testing and then forget to re-enable it. Such mistakes could lead to arbitrary account access or privilege escalation.
For example, let’s say we have the following valid token that is never actually verified:
An attacker could send the following token with an arbitrary signature to obtain escalated privileges:
2. Allowing the None algorithm
The JWT standard accepts many different types of algorithms to generate a signature:
The None algorithm specifies that the token is not signed. If this algorithm is permitted, we can bypass signature checking by changing an existing algorithm to None and stripping the signature.
Encoded and signed, the token will look like this (signature in bold):
None is permitted as the algorithm value, an attacker can simply use it to replace the valid algorithm and then get rid of the signature:
Though now unsigned, the modified token will be accepted by the application:
Note : That is why it is important to not accept tokens with
nOnE, or any other case variations in the
3. Changing the algorithm from RS256 to HS256
The algorithm HS256 uses a secret key to sign and verify each message.
The algorithm RS256 uses a private key to sign messages, and a public key to verify them.
If we change the algorithm from RS256 to HS256, the signature is now verified using the HS256 algorithm using the public key as secret key. Since the public key is not secret at all, we can correctly sign such messages.
Consider the following example code, which could be present at the server:
If the JWT uses asymmetric RS256, this correctly verifies the signature on the token. If the JWT uses symmetric HS256, however, the signature is compared to a HMAC of the token, where the public_key is used as key. We can thus exploit this vulnerability by signing our own token using HS256 with the public key of the RS256 algorithm.
Attacks against JSON Web Tokens
1. Kid Parameter Manipulation
The JWT header can contain the Key Id parameter kid. It is often used to retrieve the key from a database or filesystem. The application verifies the signature using the key obtained through the kid parameter. If the parameter is injectable, it can open the way to signature bypass or even attacks such as RCE, SQLi, and LFI.
kid parameter is vulnerable to command injection, the following modification might lead to remote code execution:
2. kid parameter injection + directory traversal = signature bypass
If an application uses the kid parameter to retrieve the key from the filesystem, it might be vulnerable to directory traversal.
Then an attacker can force the application to use a file whose value the attacker can predict as a key for verification. This can be done using any static file within the application. Knowing the key file value, the attacker can craft a malicious token and sign it using the known key. For example, an attacker might try to insert /dev/null as the key source to force the application to use an empty key
If directory traversal to
/dev/null succeeds, the attacker will be able to sign a malicious token using an empty string.
Note: The same technique can be used with known static files, for example, CSS files.
3. Attacks using the jku header
In the JWT header, developers can also use the jku parameter to specify the JSON Web Key Set URL.
This parameter indicates where the application can find the JSON Web Key (JWK) used to verify the signature – basically the public key in JSON format.
For Example, let’s take the following JWT that uses the jku parameter to specify the public key
key.json file might look something like, The application verifies the signature using the JSON Web Key retrieved based on the
jku header value:
Authentication processes in modern web applications are becoming increasingly dependent on JSON Web Tokens. Instead of developing their own implementations of JWT.
Developers should follow best practices and use trusted JWT libraries. You should also use a high-quality vulnerability scanning solution to find weaknesses before they can be exploited by cybercriminals in order to minimize the risk of attackers chaining JWT attacks with other vulnerabilities.
JWT, like many other technologies, is fundamentally secure, but some implementations fail to meet this standard. The JWT may contain sensitive information, or it may be possible to change the signing algorithm, or the key used in the signature is insufficiently strong.