Authentication and authorization are critical components of any application. Various standards and frameworks have been developed to facilitate the development of such components and make applications more secure. Among them, JSON Web Tokens (JWTs) have become popular choice over the years.

JSON Web Tokens are an open, industry-standard RFC 7519 method for securely sending data between two parties. They contain information (claims) encoded in the JSON format. These claims help to exchange specific details between the parties involved. The contained information can be verified and trusted using digital signatures.

OpenID Connect and OAuth2 are two authentication frameworks that have become popular in recent years. Both of them use JWT to transfer user data between the parties involved.

In this article, we discuss commons flaws in JWT-based authentication and present our extension to automatically check for these issues in Burp: JWT-scanner.

An example JWT Authentication

When a user attempts to log in to a Web application, the Web server verifies the user’s credentials and returns a JWT containing all relevant data: the user’s identity and authorization details.

In subsequent requests the client includes the JWT. The server verifies the token’s signature to ensure it hasn’t been tampered with. Within the implementation of this verification, design issues can make Web sites vulnerable to attack.

JWT 101

A JWT consists of three parts: The Header, Payload and Signature also known as JSON Web Signature (JWS).

The header segment of a JWT contains information about the signing algorithm and token type. The alg parameter specifies the cryptographic algorithm used to create the signature. JWTs are most commonly signed using one of the following algorithms: HS256 (HMAC using SHA256), and RS256 (RSA using SHA256).

The payload segment of a JWT contains registered claims or identifying information, usually for a user.

The signature segment depends on the algorithm defined in the header segment. It consists of the Base-64 URL-encoded header and payload segments, signed using a secret and hashed.

For symmetric signing algorithms using HMAC (e.g. HS265), the private key is shared between all participating servers. The same private key is used to generate the signature and to validate the signatures of incoming JWTs.

For asymmetric signing algorithms using RSA (e.g. RS256), the JWT signatures are generated using a private key and the server can validate them using the public key.

JWT attacks

JWT attacks aim to bypass authentication and access controls by forging a JWT to impersonate another user. To accomplish this, they typically exploit implementation flaws in the signature verification mechanism.

Unverified invalid signature

The first pitfall is when the server does not implement signature verification at all. All arbitrary signatures are accepted and the server trusts all forged JWTs.

JWT without signatures

In this case, the alg parameter is set to none, indicating a so-called “unsecured JWT”. Most servers will reject tokens without signatures, but if the filtering relies on string comparisons, it is sometimes possible to get around it using classic obfuscation techniques, such as mixed case and unexpected encodings.

Empty passwords

Some symmetric signing algorithms, such as HS256 use an arbitrary, standalone string as the secret key. Most libraries that implement this will use an empty string as the default secret. Of course, if the developers forget to change this default value when implementing the web application, the server will also accept forged JWT signed with an empty string.

CVE-2022-21449

In 2022, it was discovered that Java versions 15, 16, 17 and 18 contained a critical bug also known as CVE-2022-21449. This vulnerability allows attackers to forge ECDSA signatures with specific values that would be accepted by the server.

This can also be exploited with JWT signatures. An attacker can specify the ECDSA algorithm: alg: "ES256" and append a predefined signature to the JWT. The Web server will successfully verify the signature. If you are interested in how this vulnerability works in more detail, you can read the following blog post by Neil Madden.

Self Signed JWTs via JWK injection

The JSON Web Signatures standard RFC 7515 defines that there is an optional jwk header parameter that servers can use to embed their own RSA public key in the JWK (RFC 7517 ) format.
Some misconfigured servers will use the this public key embedded in the JWT to verify the signature instead of using their own set of whitelisted public keys. This allows an attacker to self-sign a forged JWT and include the matching public key used to sign the JWT in the jwk header.

JWT-scanner

All of the above attacks require manual modifications to the JWT and in some cases cryptographic key generation. We are seeing more and more web applications using JWTs for authentication and authorization. Some implementations, especially when used in conjunction with OpenID Connect or OAuth2, may contain several different JWTs, such as an ID token, an access token and a refresh token. This makes testing these tokens repetitive and error-prone.

This is where our Burp extension comes in play to automate the detection of JWT attacks. The idea was to use as much of Burp’s functionality as possible. The existing context menu of the Proxy, Repeater, Target, Logger and Intruder can be used to initiate the tests on a selected request:

There are two ways to select the desired JWT from a request:

  1. The simpler and standard case is to just let the extension autodetect the JWT based on its structure.
  2. However, if you have a somewhat special case and you have different JWTs contained in a request, the extension allows you to simply select the JWT that you want to test and run the extension on it.

Before the extension starts testing, it will first check if the selected JWT is still valid. This is because the extension needs a valid request to compare the test requests against. This is all the interaction required. If the extension detects an issue from one of the test cases, it will create an issue in the Burp All Issues tab:

Download and Sources

The latest latest version and the source code can be found on the Compass Security GitHub repository. The extension has been submitted to PortSwigger and will soon™ be available on the BApp Store.

Interested in learning more?

Do you want to know more about these attack techniques and tools? Then, our advanced Web app security training might be something for you! In this training, you will learn hands-on about security vulnerabilities in modern Web technologies. This is a perfect course for Web developers or security professionals that want to know more about Web applications vulnerabilities, how they are exploited or how to avoid them.

More info about this training in general can be found here: https://www.compass-security.com/en/trainings/web-application-security-advanced.

There is a public training on the 10th and 11th of June 2024 where everyone interested can participate. More info can be found here: https://www.compass-security.com/en/trainings/web-application-security-advanced/waa-zurich-june-2024.

Note: This training will be held in German only (slides/course material are in English).