code

Cracking JWT Vulnerabilities

Written by Yuval Batan on

Cracking JWT Vulnerabilities

Written by Yuval Batan on


Introduction

JSON Web Tokens (JWTs) are a crucial and wide part of modern web authentication and authorization systems. However, if this technology is not implemented correctly, malicious actors can exploit it and cause unauthorized access and actions. Understanding and mitigating these risks is crucial, which we will discuss in more detail in this article.

What is a JWT?

The JWT stands for “JSON Web Tokens,” which mainly stores user identity information and permissions. It is popular among developers for being lightweight and easy to use. JWTs are sealed using a cryptographic signature, guaranteeing the data’s integrity and authenticity.
JWTs are stateless, meaning the server verifies their signature and extracts needed data, eliminating the need for server-side session storage and reducing the attack surface, as there is no server-side session data to steal. This improves scalability and versatility compared to cookies, which require constant server verification.

The JWT Structure

The JWT, encoded by Base64 encoding, consists of three integral parts – header, payload, and signature. These parts are separated by periods and contain the following information:

  1. Header – the first part contains metadata about the token, such as cryptographic algorithm (represented as ‘alg’), token type (‘typ’), etc.
  2. Payload – the second part contains the actual data and contains the information related to the specific system requirements. For example, username, role, permissions, and more.
  3. Signature – the third part is used to verify the token integrity and authenticity, ensuring the data has not been tampered with by signing the header and payload with a secret key (the type of the secret depends on the cryptography algorithm mentioned at the header segment).
Visual Representation of the JWT’s Structure

Attack Vectors and Misconfigurations

To better understand the topic of JWT vulnerabilities, we will explore and demonstrate the exploitation and mitigation of common misconfigurations and attack vectors within PortSwigger’s vulnerable labs. This will help us to understand how malicious actors can exploit JWT vulnerabilities and how to protect systems from these attacks.

To illustrate this, we will analyze misconfigurations where attackers can decode and modify the JWTs content. While various tools can be used to achieve the same impact, we will utilize the “jwt.io” website for decoding and the PortSwigger BurpSuite extension named “JWT Editor” for modifications and tampering.

Weak Secret

As mentioned, a JWT secret is a cryptographic key whose main purpose is to ensure that the JWT content cannot be tampered with.
There are two types of encryption: Symmetric and Asymmetric. Symmetric encryption uses the same key to encrypt and decrypt data, while asymmetric encryption uses two different keys – a public key and a private key.

One of the most common and simple misconfigurations in symmetric encryption is using a weak secret. This vulnerability can be exploited through brute-forcing to uncover the correct key, enabling the creation of valid JWTs that can be used to impersonate legitimate users or access unauthorized resources.
The following scenario will examine this attack vector:

  • The tested application validates the users’ permissions by the JWT. It also allows only the administrator user to enter the admin panel.
  • After a successful login with a low-privileged user, the system returns the user’s JWT value in a response.
  • The decoded parameters and values that the following JWT stores are as follows:
Decoded JWT Values After a Successful Login
  • It can be concluded that the JWT uses symmetric encryption by the alg parameter value (HS256).
  • Moreover, the sub parameter value in the body is responsible for confirming the user’s identity. For example, modifying this parameter value to an administrator value can lead to a privilege escalation attack.
  • This modification can be possible only by signing the token correctly with a valid secret because the system verifies the signature of the JWT.
  • To find the correct secret (assuming it is weak and guessable), it is possible to guess it using a dedicated wordlist containing possible secret values using publicly accessible tools, such as jwt_tool, an automated tool based on Python for testing the strength of a JWT.
  • To perform the brute force, it is required to execute the following command on Linux OS:

python jwt_tool.py -C -d {WordList} {JWT}

Weak Secret Discovered by Brute Force Attack
  • To leverage the attack, creating a new JWT with administrator permissions on the system is possible using the fetched secret and a dedicated tool. To reach this result, it is necessary to change the sub parameter value to administrator, create a new symmetric key with the secret1 secret, and sign the new JWT:
Creating New Administrators JWT
  • Using this new, valid JWT, it is possible to access the admin panel successfully:
Accessing the Admin Panel is Possible

JWK Header Injection

The JSON Web Key (JWK) parameter is an optional header parameter in a JWT that can be used to specify the cryptographic key used to verify the token. If the JWK parameter is present, the server will use it to verify the token instead of fetching the key from a trusted location.
If the system does not validate the JWT properly, it is possible to modify the JWT using this method, which will cause unauthorized actions on the system.

In this scenario, a valid user can authenticate the system and receive a valid JWT.

  • The following decoded values are the fetched JWT’s content:
The Decoded User’s JWT Content
  • It can be concluded that the JWT uses asymmetric encryption (RS256). Therefore, brute force is not an option for the secret. Also, the server identifies the user by the sub parameter value.
  • To successfully modify the JWT’s sub parameter value, it is required to create a new RSA key using publicly accessible tools and change the sub parameter value to an administrator.
Creating a New RSA Key and Modifying the User Parameter
  • Next, it is required to add the self-signed JWK parameter to the Header of the JWT as follows:
Modifying the JWT’s Header
  • This JWT can replace the original retrieved from the server to gain unauthorized access to the admin panel:
Successfully Accessing the Admin Panel

JKU Header Injection

JSON Web Key Set URL (JKU) is an optional parameter in the JWT header. This parameter is being used to store the location of multiple JSON Web Keys (JWKs). The main issue with this functionality occurs when the server does not validate the JWK location correctly, which could result in several attack vectors with a significant impact. One of these attack vectors is the JKU header injection. It tricks the server into trusting a malicious key URL by injecting it into the JWT header, enabling attackers to forge valid tokens and bypass authentication and authorization mechanisms.

The following scenario will demonstrate how malicious actors can use this vulnerability for a privilege escalation:

  • Viewing the low-privileged user’s JWT structure as follows:
The Decoded User’s JWT Content
  • The JWT is signed with asymmetric encryption and contains the sub parameter in its payload segment responsible for the user’s privileges.
  • The next steps are as follows:
    • Create a new RSA key.
    • Copy the generated content of this key.
    • Paste it into the attacker’s controlled server.
    • Save it into the “Body” section, so when a client sends a request to the server, they will get a response containing the self-signed keys.
  • To proceed and leverage the attack, change the kid parameter value to the value of the new kid parameter, which is inside the key we self-signed before.
  • Add the jku parameter to the header of the JWT containing the URL of the exploit server.
  • Then, changing the sub parameter value to the administrator is possible.
The Modified JWT Content Results in Unauthorized Access

The original JWT can be replaced by the generated JWT to gain unauthorized access to the admin panel.

Path Traversal Injection within the kid Parameter

In the JWT header part, the kid parameter specifies the key identifier used to verify the token. This parameter is typically used to prevent replay attacks, as an attacker would need to know the key identifier to generate a valid token.

However, if the server does not validate the kid parameter correctly, attackers can inject a malicious path into this parameter, bypassing the key validation and causing unauthorized modification of the JWT.

This specific method of bypassing validation occurs when the JWT is signed with symmetric encryption.

The following scenario will demonstrate how malicious actors can exploit this vulnerability for a privilege escalation:

  • Authenticating the system using the default credentials of the low-privileged user will retrieve the following JWT:
The Decoded User’s JWT Content
  • Viewing the decoded JWT, it can be concluded that it uses symmetric encryption (HS256) and the sub parameter contains the user permissions.
  • Creating a new symmetric key with an empty value is required to use the unvalidated kid parameter and modify the JWT without a valid secret.
  • The next step is to modify the kid parameter value into /dev/null, a well-known path in Linux OS containing a null value. This means that the JWT secret will be validated against an empty value.
  • Now, it’s possible to change the sub parameter value to administrator and sign the JWT using the key created in the previous step.
The Modified JWT Content

The original JWT can be replaced by the generated JWT to gain unauthorized access to the admin panel.

Mitigation

If you have encountered any of the above scenarios, please follow the below instructions provided by Clear Gate for immediate mitigation and to prevent further JWT misconfigurations:

  • Enforce cryptographically strong, lengthy, and randomly generated secrets for JWT signing, deterring brute-force attacks and safeguarding data integrity.
  • Validate incoming JWK headers against a trusted key set and reject any tokens bearing untrusted or malformed keys to thwart unauthorized actions.
  • Validate the origin of jku URLs against a trusted allowlist of domains, ensuring key retrieval exclusively from authorized sources.
  • Validate the kid parameter in JWTs against a trusted set of key identifiers. This ensures only legitimate parties can modify the JWT.

In a more general manner, it’s possible to mitigate most JWT misconfigurations by embracing robust asymmetric algorithms like EdDSA or RS256, strictly validating all JWT header and payload components against defined schema and format constraints to prevent parameter manipulation vulnerabilities.

Conclusion

Despite their rising popularity and undeniable advantages in simplifying authorization flows, JWTs are not immune to vulnerabilities. Overlooking seemingly trivial misconfigurations, like weak secrets and improper validation, can open doors for attackers to exploit. Using the methods and tools shown in this article, for example, allows attackers to craft a malicious JWT, tricking systems into unauthorized access to sensitive data, or even taking control of critical functions – all through a minor oversight in the JWT implementation.

Organizations should prioritize cyber security risk assessments and penetration tests to mitigate risks in JWT deployments, which have become increasingly popular among companies developing SaaS products. Clear Gate, a trusted cybersecurity provider, offers in-depth manual penetration tests to help organizations strengthen their web application security and protect valuable data from potential threats.

References