What on Earth is JWT?
JWT is an abbreviation for JSON Web Token, which refers to a very common way of conveying small amounts of data between the browser and the server, or between information systems, in digitally signed form.
JWT tokens usually look like this: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
If you look closely, you will notice that the token has three parts separated by dots.
- First part: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
- Second part: eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
- Third part: SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
All parts of the token are base64 encoded. Base64 is a widely used method to convert any type of data into a format consisting of 64 different characters, and back again.
Part 1: JOSE-Header
The first part of the token is JOSE (Javascript Object Signing and Encryption) header, which contains information about for example the encryption or signing algorithm of the token.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 is decoded as (base64):
{"alg":"HS256","typ":"JWT"}
alg: Encryption/signing algorithm. HS256 stands for "HMAC with SHA-256", which is a symmetric signing algorithm, meaning that the digital signature is created and signed with the same encryption key.
type: Not used for much, value is typically JWT.
Part 2: Data
The second part contains token information (also referred to as token data or payload). eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ is base64-decoded:
{"sub":"1234567890","name":"John Doe","iat":1516239022}
The information of the data partition is also called "claims". Typically, the token includes some kind of user identifier, possibly a list of user rights, and usually also information about when the token was created and when it expires.
The following claims are included in the example token:
- sub: Subject, in this case the user's identifier.
- name: User name
- iat: "Issued at", which is an epoch timestamp indicating when the token was issued.
Common claims often seen include:
- iss: "Issuer", who has issued the token.
- aud: "Audience", for whom the token is intended to be processed.
- exp: "Expiration time", an epoch timestamp indicating when the token will no longer be valid.
- nbf: "Not before", when the token becomes valid.
- jti: "JWT ID", unique identifier for this specific token. Can be used, for example, to prevent reuse of the same token, or to revoke (disable) a granted token.
Part 3: Signature
The third part of the JWT token is the digital signature. SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c is base64 decoded to I�J�IHNJ(]�O���lj~�:N�%_�u,×. So it's gibberish.
Since the algorithm is HS256, meaning HMAC + SHA256, the digital signature is, to put it simply, formed as follows:
- A: Take Part 1, i.e., the JOSE Header, and encode it in base64.
- B: Take part 2, token information, and base64 encode it.
- C: Connect with point A and B. The resulting message to be signed is something like this: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
- Take encryption key K and combine it with the message to be signed C.
- Execute a combination (K + C) of a hash algorithm (in this case SHA256), and obtain the final digital signature.
Signature verification
When JWT implementation checks if the token signature is valid, it must:
- Know which algorithm the token is signed with.
- Use the algorithm and calculate the signature from the JWT.
- Compare the calculated signature to the signature included with the token and ensure that they match.
- Check whether the token has expired or is not yet valid.
- Etc.
JWT Vulnerabilities
JWT is a versatile protocol that has historically been misunderstood in both implementations (such as JWT software libraries used by applications) and usage (applications where a secure JWT handler is not defined).
How should a JWT verification, for example, infer what algorithm is used, if the developer has not explicitly stated it in the application code? A perfectly valid and natural answer is "from the JOSE header". That's why it's there. But what if the attacker modifies the token information to their liking (e.g. "userId": "admin"), and then sets the algorithm of the token to "none," meaning no signature is needed? If the application accepts such a token, the consequences are catastrophic.
What if a too weak secret has been used in the JWT signature, and the attacker manages to guess it, and then creates their own tokens?
We will explore these and other security issues related to JWTs in this course!
Ready to become an ethical hacker?
Start today.
As a member of Hakatemia you get unlimited access to Hakatemia modules, exercises and tools, and you get access to the Hakatemia Discord channel where you can ask for help from both instructors and other Hakatemia members.