JWT and Asymmetric Encryption
It is possible to sign JWT with asymmetric encryption, meaning with public key encryption. In this case, instead of using one encryption key, we have two keys: a public key and a private key.
The public key can be freely distributed to the world, as its name suggests. The public key can be used to verify a JWT (JSON Web Token) signed with a private key.
Let's take an example. Let's say we have an HTTP interface api.example.com which is accessed with a JWT token issued by the authentication service auth.example.com.
Authentication and use of the HTTP interface could work like this:
- The user sends their username and password to the authentication service (auth.example.com). Username: "Maija", Password: "kissa123".
- The identification service has a private key that no one else has. The identification service uses its private key to sign a JWT containing the claim with the username "Maija".
- Maija sends the next message to the HTTP interface (api.example.com), with JWT included (typically in the Authorization header).
- The HTTP interface has a public key for the identification service, which it typically retrieves from the identification service's /.well-known/jwks.json path. The HTTP interface validates the JWT token with the public key, and if it is signed with the correct private key, the verification is successful, and it is known that Maija is indeed Maija. At least if the identification service is trustworthy.
Vulnerability
Vulnerability that may occur in this kind of situation is very similar in nature to the none-algorithm attack in the previous module.
It is said that there is code like this validating the token in the HTTP interface:
token = request.getHeader("Authorization")
public_key = get_public_key_identification_service()
token_correct = jwtLibrary.validateToken(
token=token,
public_key = public_key
)
What algorithm does the validoiToken call validate? It is not specifically defined in the code, so the JWT implementation uses the algorithm that is in the token. And if the token has the correct algorithm, such as RS256, there is no problem and everything works fine.
- Take token
- Take a public key
- Checking the public key to see if the token's RSA signature is OK?
But what happens if the token happens to have, for example, HS256, which is a symmetric algorithm based on one secret? In that case, it could happen that:
- Take token
- Take the public key
- Is the token signed with a symmetric encryption key whose value is a public key?
In other words, if the code is written in this way, it may be possible for an attacker to deceive the application into performing token verification with a symmetric algorithm, using a public encryption key known to the attacker.
Attack
Start by acquiring a JWT token in the application and finding a suitable HTTP request that you can send to the repeater, allowing you to easily try again and again to see if a modified token would pass. Same thing as in the last module.
The next step is to acquire the public key of the application. In the exercise below, this has been made quite easy:
In the real world, a public key, when made public, is usually found inside the JWKS JSON structure at the address /.well-known/jwks.json.
Often the public key is not published at all. There are ways to handle this situation, but we will come back to it in a later module.
When you have a public key, take the token and transform it into symmetric, try for example HS256 algorithm. Use the public key as a symmetric encryption key, rebuild the token and try if you can get through with it!
As in the previous module, you can use the Hakatemian JWT Studio here or alternatively the extensions of BurpSuite.
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.