This is the first of the two parts to JSON Web Tokens and how to attack them. While the first part talks about what exactly are JSON Web Tokens, their use and their vulnerabilties. While the second part of this writeup would be focusing on attacks.
Link to the second part: https://mrinalprakash4577.medium.com/json-web-tokens-and-how-to-attack-them-part-2-of-2-21b2bd6b0335
JWT stands for JSON Web Token. JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed.
The client will need to authenticate with the server using the credentials only once. During this time the server validates the credentials and returns the client a JSON Web Token(JWT). For all future requests the client can authenticate itself to the server using this JSON Web Token(JWT) and so does not need to send the credentials like username and password. So any information that is required to make a decision or derive additional information to make a decision has to be embedded in token.
JWT Tokens consists of three components:
Header- Header is a JSON Object which identifies which algorithm is used to generate the signature. HS256 indicates that this token is signed using HMAC-SHA256. Typical cryptographic algorithms used are HMAC with SHA-256 (HS256) and RSA signature with SHA-256 (RS256). JWA (JSON Web Algorithms) RFC 7518 introduces many more for both authentication and encryption.
Payload- This is also a JSON Object which contains a set of claims. The JWT specification defines seven Registered Claim Names which are the standard fields commonly included in tokens. Custom claims are usually also included, depending on the purpose of the token. Claims are statements about an entity (typically, the user) and additional data. There are three types of claims: registered, public, and private claims.
- Registered claims: These are a set of predefined claims which are not mandatory but recommended, to provide a set of useful, interoperable claims. Some of them are: iss (issuer), exp (expiration time), sub (subject), aud (audience), and others.
- Public claims: These can be defined at will by those using JWTs. But to avoid collisions they should be defined in the IANA JSON Web Token Registry or be defined as a URI that contains a collision resistant namespace.
- Private claims: These are the custom claims created to share information between parties that agree on using them and are neither registered or public claims.
The following example has the standard Issued At Time claim (iat) and a custom claim (loggedInAs).
The payload is then Base64Url encoded to form the second part of the JSON Web Token. It is used to store the user’s information like id, username, role, token generation time and other customs claims.
Signature- Most important part as it Securely validates the token. The signature is calculated by encoding the header and payload using Base64url Encoding and concatenating the two together with a period(.) separator. The string is then run through the cryptographic algorithm specified in the header, in this case HMAC-SHA256. The Base64url Encoding is similar to base64, but uses different non-alphanumeric characters and omits padding. The signature will be created in the following way in this case:
base64urlEncoding(header) + '.' +
The signature is used to verify the message wasn’t changed along the way, and, in the case of tokens signed with a private key, it can also verify that the sender of the JWT is who it says it is.
The three parts are encoded separately using Base64url Encoding, and concatenated using periods to produce the JWT:
const token = base64urlEncoding(header) + '.' + base64urlEncoding(payload) + '.' + base64urlEncoding(signature)
The above data and the secret of “SECRET KEY” (for more information about SECRET KEY refer to the explanation section down below) creates the token:
This resulting token can be easily passed into HTML and HTTP.
In authentication, when the user successfully logs in using their credentials, a JSON Web Token will be returned and must be saved locally (typically in local or session storage, but cookies can also be used), instead of the traditional approach of creating a session in the server and returning a cookie. For unattended processes the client may also authenticate directly by generating and signing its own JWT with a pre-shared secret and pass it to a oAuth compliant service like so:
If the client passes a valid JWT assertion the server will generate an access_token valid for making calls to the application and pass it back to the client:
When the client wants to access a protected route or resource, the user agent should send the JWT, typically in the
Authorization header using the
Bearer schema. The content of the header might look like the following:
Authorization: Bearer eyJhbGci...<snip>...yu5CSpyHI
This is a stateless authentication mechanism as the user state is never saved in server memory. The server’s protected routes will check for a valid JWT in the Authorization header, and if it is present, the user will be allowed to access protected resources. As JWTs are self-contained, all the necessary information is there, reducing the need to query the database multiple times.
SECRET KEY- The Web Tokens can be generated using two types of encryption mechanisms: Symmetric encryption and Asymmetric encryption
1. Symmetric encryption- Symmetric-key algorithms are algorithms for cryptography that use the same cryptographic keys for both encryption of plaintext and decryption of ciphertext. The most common algorithm for this is HS256. The keys may be identical or there may be a simple transformation to go between the two keys. The keys, in practice, represent a shared secret between two or more parties that can be used to maintain a private information link. For example, if Alice has generated a JWT with “H4CK3R” as a secret key then any person who knows the key (i.e. H4CK3R) can modify the token using that key and the token would still be valid and this way a user can be impersonated.
2. Asymmetric encryption- It works on the combination of public and private key on the installed web servers. In order to decrypt a message in Asymmetric Encryption, a user needs the pair of public key and private key. A mechanism of Asymmetric Encryption technology is much compound to understand and therefore it has more value in data security on the Internet. For example, if Alice has used this encryption, then she is the only one who can create a new token using the private key but cannot modify it. The most common algorithm used in this encryption is RS256.
To understand more about public key cryptography, you can watch this Youtube video from Computerphile wich explains more about these in detail
The Vulnerabilities in JWTs
As explained above, in order to forge a token, one must have the correct set of keys (for example, secret keys for HS256 and the public and private keys for RS256) but if JWT’s configuration is not implemented correctly, then there are many ways to bypass the controls and modify the token to gain an unauthorized access.
JSON web tokens may contain session state. But if project requirements allow session invalidation before JWT expiration, services can no longer trust token assertions by the token alone. To validate the session stored in the token is not revoked, token assertions must be checked against a data store. This renders the tokens no longer stateless, undermining the primary advantage of JWTs.
With proper design, developers can address algorithm vulnerabilities by taking precautions:
1. Never let the JWT header alone drive verification
2. Know the algorithms.
3. Use an appropriate key size.
Nevertheless, we are here to talk about the attacks that can be done on JSON Web Tokens (JWT).
Why should we use JSON Web Tokens?
Let’s talk about the benefits of JSON Web Tokens (JWT) when compared to Simple Web Tokens (SWT) and Security Assertion Markup Language Tokens (SAML).
As JSON is less verbose than XML, when it is encoded its size is also smaller, making JWT more compact than SAML. This makes JWT a good choice to be passed in HTML and HTTP environments.
Security-wise, SWT can only be symmetrically signed by a shared secret using the HMAC algorithm. However, JWT and SAML tokens can use a public/private key pair in the form of a X.509 certificate for signing. Signing XML with XML Digital Signature without introducing obscure security holes is very difficult when compared to the simplicity of signing JSON.
JSON parsers are common in most programming languages because they map directly to objects. Conversely, XML doesn’t have a natural document-to-object mapping. This makes it easier to work with JWT than SAML assertions.
Regarding usage, JWT is used at Internet scale. This highlights the ease of client-side processing of the JSON Web token on multiple platforms, especially mobile.
HOW WE USE JSON WEB TOKENS IN AUTH0?
In Auth0, we issue JWTs as a result of the authentication process. When the user logs in using Auth0, a JWT is created, signed, and sent to the user. Auth0 supports signing JWT with both HMAC and RSA algorithms. This token will be then used to authenticate and authorize with APIs which will grant access to their protected routes and resources.
We also use JWTs to perform authentication and authorization in Auth0’s API v2, replacing the traditional usage of regular opaque API keys. Regarding authorization, JSON Web Tokens allow granular security, that is the ability to specify a particular set of permissions in the token, which improves debuggability.
For more information, check this post
Hope you all gained much information regarding JWT. This is the end of part one. The next part of this writeup would focus on the attacks that can be performed on JWTs.