JSON Web Token (JWT) and Security

General

JWT is an open standard for transmitting information as a JSON object. The most common scenario is authorization.

Unfortunately, the token keeps cropping up in connection with the security vulnerability. For example, it is mentioned in the OWASP top ten under the item “Broken Access Control”. In the following, I would like to briefly explain the JWT and point out a few risks when using it.

The token consists of three parts: the header, payload, and signature. Each part has been encoded with Base64Url, and all parts are joined together, separated by dots.

The type of the token and the signing algorithm is typically defined in the header.

{
  "alg": "HS256",
  "typ": "JWT"
}

The payload contains the information that should be transmitted. In cases of authorization, the user and permissions. It is also possible to define token metadata, like an expiration time. Such information must be checked by the developer. The token itself has no expiration.

{
  "exp": 1516242622,
  "name": "Max Mustermann",
  "admin": true
}

The signature take the encoded header, the encodes payload and a secret and encode it with the algorithm defined in header.

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

In the authorization scenario, the token is requested from the client and created by the authorization server. The client uses the token to authorize a resource server. Therefore, the token is sent in the authorization header using the bearer schema.

Security Issues

JWT has a lot of attack surfaces, like the None Hashing Algorithm, ECDSA “Psychic Signatures”, Weak HMAC Keys, HMAC vs Public Key Confusion, Attacker Provided Public Key and the plaintext transmitting of the payload. All in all, JWT is vulnerable to replaying or tampering. Especially if the secret is not strong, the token does not expire, or no signature is used at all.

In the following, I will take a closer look at the none hashing algorithm issue as an example:

JWT allows you to set the algorithm in the header to none. So the signature part that tries to detect tampering is missing. It is just the first two parts and the point of waiting for a signature, which does not come.

eyJhbGciOiAibm9uZSIsICJ0eXAiOiAiSldUIn0K.eyJ1c2VybmFtZSI6ImFkbWluaW5pc3RyYXRvciIsImlzX2FkbWluIjp0cnVlLCJpYXQiOjE1MTYyMzkwMjIsImV4cCI6MTUxNjI0MjYyMn0.

All security precautions are already suspended, and the attacker can create his own tokens or modify intercepted ones at his leisure.

Some frameworks forbid this configuration, but in the JWT standard, it is possible. Although many applications and libraries that use JWT have disabled the option or at least tried to do so, there are still security vulnerabilities due to the configuration option. For example, because only case-sensitive “none”  was checked, settings like “None” or “NoNe” could still be used as an attack surface. So if you want to forbid this setting, it is important to do it case-insensitively.

Since this is a big problem that also occurs again and again, there is a website that counts the days since the last none algorithm problem: https://www.howmanydayssinceajwtalgnonevuln.com/.

The none algorithm is not the only attack surface on the algorithm usage. Most of the before named issues are related to the algorithm part.

How to use most secure

At best, the token should only be used once to confirm authentication and authorization. It should not be used for session management and has a short lifespan. Thus, the time span for attacks can be minimized. Also, the algorithm none option should be prevented, and a proper signature algorithm should be used. Additional information and configuration recommendations can be found under: https://jwt.io/ and OWASP cheatsheet.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.