Anatomy of a JWT Token Part 2

Chintan Jain
8 min readOct 13, 2017

--

Executive Summary Part 2

In Part1 we discussed what is a JWT and what are the popular use cases where it can be used. In this part, let’s talk about what are the security issues with JWT and what are some of the remediation strategies.

As you know that JWTs once granted are self-contained bearer tokens. It means that the possessor of the token do not need to prove how they got it and once the possessor has it, they can give it to the relying party and the relying party will be able to validate it without calling the JWT issuer. Because of this JWT are very convenient and scalable to use however if not properly implemented, this can have huge security implications. So, let’s cover what are some of the security vulnerabilities with JWT and what can be done to remediate it?

JWT vulnerabilities & recommendations

1. Impossible to Revoke Vulnerability

The main selling point for JWT is that it is self-contained and can be independently verified by the relying party or a resource server without communicating to the authorization server. While, this is great from a scalability perspective as the relying party can directly validate the token without making another HTTPS call over a network, the security issue with this is that JWT once issued cannot be revoked. In other words, even in the resource owner changed their password after the JWT was issued, the JWT will continue to be valid until it is expired. Even if the identity provider was hacked and the resource owner wants to revoke the JWT token, there is no way to do it.

Due to this security vulnerability in JWT token, the authorization server should issue a JWT with a very limited expiry time. May be at max 20 to 30 minutes. This will ensure that the JWT is only valid for a very short window and for subsequent authentication and authorization requests the resource owner must come back to an authorization server and re-authenticate. At that time, authorization server can validate whether the user’s password was changed or any other changes happened in user’s account before issuing them a new JWT token. This will reduce the window of attack drastically against a vulnerable JWT.

The relying party or the consuming application trusting JWT tokens should always check for JWT expiry before granting access to the application.

2. Stolen JWT token vulnerability

As JWT is a bearer token, anyone with access to it can use it to access the user account at the resource server. So, it is very important to protect a JWT token during temporary or permanent storage.

As a relying party, if you were issued a JWT token and if this JWT token is used to access resources at a resource server, and you want to store it somewhere, always store it in a transient memory. If you are storing the JWT in a cache layer or a database layer, do not store it in plain text — always store it in an encrypted fashion using a symmetric algorithm such as AES-GCM with the cryptographic keying material stored in a secure vault, a cloud HSM or a cloud key store. This will ensure that someone is not able to access the JWT token in an unauthorized fashion in plain text and access the resources at the resource server using the stolen JWT token.

3. ‘: NONE’ Signature Algorithm Tampering vulnerability

The JWT spec allows a signature algorithm to be specified as NONE. There have been some security vulnerabilities discovered against earlier versions of JWT libraries where the attacker was able to manipulate the header of the JWT to change the signature algorithm to “NONE.” Then the attacker modified the payload and sent it to the consuming application. If the consuming application was using a vulnerable version of a JWT library or custom code that trusted the header of the received JWT to know how it was signed, in that case, they would trust this manipulated JWT (as there was not signature to verify and the signature algorithm was specified at :NONE) and allow access.

My recommendation is not to use vulnerable JWT libraries for JWT validation and always use the latest version(use jwt.io to find out if the library version that you are using to create or verify JWT is vulnerable or not). Also, do not write your custom code for signing and validating JWT. The chances are you will find a library in your language of choice so use that rather than reinventing the wheel and writing all signing and verification methods in your own custom code. if you are writing custom code do not trust the Header of the JWT when validating JWT. This will require you to hardcode the algorithm in your validating code when validating the JWT and either generate a headless JWT token (with no header) or just plainly ignore the algorithm coming into the header of the JWT token during validation of the token.

4. Modify Signature Algorithm Tampering vulnerability

There is another critical vulnerability against JWT libraries that could be exploited with Hackers. This works in this way.

Let’s say a JWT token is implemented so it is signed with a RS256 algorithm. In this case, only the authorization server can sign it because it knows its private key and the resource server can validate it with a publically known public key. Now what a smart attacker can do is find out that the token has implemented RS256 as the signing method. (S)he can generate a new JWT token with algorithm as HS256 and sign it with a public key. Now when the server receives this token and sees that the algorithm is HS256. It still uses its public key to verify it(this can be result of poorly written code). If there are no checks in place in the code for algorithm tampering, the validation will pass and the JWT token will be marked as successfully passed authentication. This will allow the attacker to access the resources on the server as the resource owner.

My recommendation is same as # 4 above. First recommendation is to make sure you are not using a vulnerable version of the library and the second one is not to trust the Header of the received JWT when validating it. This will require you to hardcode the algorithm in your validating code when validating the JWT and either generate a headless JWT token(with no header) or just plainly ignore the algorithm coming into the header of the JWT token during validation of the token.

5. Man in the middle vulnerability

As discussed above, a leaked JWT can be used by any possessor. Hence, it is of utmost importance that JWT token is not vulnerable to Man in the middle attacks. As an issuer or as a relying party, always make sure that the communication to request the JWT or to use the JWT always happen on a TLS 1.2 connection. TLS 1.2 is strongly recommended due to the prevalent security vulnerabilities against TLS 1.1/TLS 1.0 and SSL 3.0/2.0.

Some other JWT security recommendations

1. Using at least 256 bit PRNG key to sign JWT when using HMAC-SHA256

It is very important that if you are using HMAC-SHA256 as a signature algorithm to sign JWT, you use at least a 256-bit key that is generated using a proven crypto secure random number generator library. The rule is that if you are using an algorithm that provides a 256-bit output, your key size should be at least 256 bit. If you are using an algorithm that provides a 512 bit output, the key size should be at least 512 bit. This is as per the RFC 7518 spec Section 3.2 that specifically states following:

A key of the same size as the hash output (for instance, 256 bits for”HS256") or larger MUST be used with this algorithm. (This requirement is based on Section 5.3.4 (Security Effect of the HMAC Key) of NIST SP 800–117 [NIST.800–107], which states that the effective security strength is the minimum of the security strength of the key and two times the size of the internal hash value.)

2. Using unique secret keys to sign JWT when using HMAC-SHA256 for different relying parties

The Authorization Server should generate a unique secret key per client if using HS256 as the signing algorithm. This is because if two different clients are sharing the same secret with the Authorization Server, a malicious or a hacked client can use this knowledge to create validly signed JWT that will be useable at an unsuspecting client. As an example, lets say that a hacker hacked into client 2 and now they know the secret key that the Authorization Server has given that will be used to sign the JWT issued by the server. A hacker can now intercept the login requests at Client 1, create validly signed JWTs using a proxy tool and allow the user to access a different user’s account as indicated in the JWT on Client 1.

3. Tracking the number of sessions created with the same JWT

As we have already covered above, a JWT is reusable until it expires. This can have the disadvantage of the resource owner able to use the JWT to create multiple concurrent sessions with an unexpired JWT. If the resource server wants to disallow this for security reasons there is a way to do this. It is recommended that when the Authorization Server issues a JWT, the JWT always contains a jti claim(jwt id). This claim is included in the rfc 7519 spec however is not being used consistently. Now the resource server that is validating the JWT should look at the jwt id and cache the number of sessions active with this jwt id. The count of the number of active sessions per jwt id can be used as per the business rule whether to allow that jwt id or not for further sessions.

4. Replay attacks against JWT

In addition to the above security vulnerabilities with JWT, a jwt is also subject to replay attacks if a static jwt is issued and none of the parameters of jwt are dynamic. Examples of some of the dynamic claims in jwt include nbf(not before), iat(issued at), jti(jwt id), exp(expiration time). This static jwt can be reused over and over at the resource server even if the resource owner privileges are revoked at the resource server. In order to protect against the replay attacks vulnerability against JWT, it is recommended to issue the JWT with at least two of the above dynamic claims. What the dynamic claims will do is change the signature of the jwt and hence the jwt cannot be replayed.

Conclusion of Part 2

As you see from above, JWT if implemented incorrectly can have huge security implications for the security of your system and your authentication and authorization schemes can be easily hacked or manipulated to a hacker’s advantage.

However, all is not lost and you can have a very secure implementation of JWT by using the techniques described in this paper.

--

--