jwt_tool.py is a toolkit for validating, forging, scanning and tampering JWTs (JSON Web Tokens). Its functionality includes: This tool is written for pentesters, who need to check the strength of the tokens in use, and their susceptibility to known attacks. A range of tampering, signing and verifying options are available to help delve deeper into the potential weaknesses present in some JWT libraries. This tool is written natively in Python 3 (version 3.6+) using the common libraries, however various cryptographic funtions (and general prettiness/readability) do require the installation of a few common Python libraries. The preferred usage for jwt_tool is with the official Dockerhub-hosted jwt_tool docker image By using the above command you can tag on any other arguments as normal. Installation is just a case of downloading the On first run the tool will generate a config file, some utility files, logfile, and a set of Public and Private keys in various formats. To fix broken colours in Windows cmd/Powershell: uncomment the below two lines in The first argument should be the JWT itself (unless providing this in a header or cookie value). Providing no additional arguments will show you the decoded token values for review. The toolkit will validate the token and list the header and payload values. The many additional arguments will take you straight to the appropriate function and return you a token ready to use in your tests. Many options need additional values to set options. Some options such as Verifying tokens require additional parameters/files to be provided (here providing the Public Key in PEM format): All modes now allow for sending the token directly to an application. Various responses from the request are displayed: Here is a quick run-through of a basic assessment of a JWT implementation. If no success with these options then dig deeper into other modes and options to hunt for new vulnerabilities (or zero-days!). Read the token value to get a feel for the claims/values expected in the application: Run a Playbook Scan using the provided token directly against the application to hunt for common misconfigurations: If any successful vulnerabilities are found change any relevant claims to try to exploit it (here using the Inject JWKS exploit and injecting a new username): Dig deeper by testing for unexpected values and claims to identify unexpected app behaviours, or run attacks on programming logic or token processing: Review any successful exploitation by querying the logs to read more data about the request and : For a list of options call the usage function:
Some options such as Verifying tokens require additional parameters/files to be provided: A more detailed user guide can be found on the wiki page. Head over to the JWT Attack Playbook for a detailed run-though of what JWTs are, what they do, and a full workflow of how to thoroughly test them for vulnerabilities, common weaknesses and unintended coding errors. Regex for finding JWTs in Burp Search JWT Attack Playbook (https://github.com/ticarpi/jwt_tool/wiki) - for a thorough JWT testing methodology A lot of the initial inspiration for this tool comes from the vulnerabilities discovered by Tim McLean. A whole bunch of exercises for testing JWT vulnerabilities are provided by Pentesterlab (https://www.pentesterlab.com). I'd highly recommend a PRO subscription if you are interested in Web App Pentesting. PLEASE NOTE: This toolkit will solve most of the Pentesterlab JWT exercises in a few seconds when used correctly, however I'd strongly encourage you to work through these exercises yourself, working out the structure and the weaknesses. After all, it's all about learning...
It has also been successful for CTF challengers - as CTFs seem keen on JWTs at present.
It may also be useful for developers who are using JWTs in projects, but would like to test for stability and for known vulnerabilities when using forged tokens.
(An older Python 2.x version of this tool is available on the legacy branch for those who need it, although this is no longer be supported or updated)
The base command for running this is as follows:
Base command for running jwt_tool:
docker run -it --network "host" --rm -v "${PWD}:/tmp" -v "${HOME}/.jwt_tool:/root/.jwt_tool" ticarpi/jwt_tool
Note that local files in your current working directory will be mapped into the docker container's /tmp directory, so you can use them using that absolute path in your arguments.
i.e.
/tmp/localfile.txtjwt_tool.py
file (or git clone
the repo).
(chmod
the file too if you want to add it to your $PATH and call it from anywhere.)$ git clone https://github.com/ticarpi/jwt_tool
$ python3 -m pip install -r requirements.txt
jwtconf.ini
as the "jwkloc" value.
Review the other options in the config file to customise your experience.jwt_tool.py
(remove the "# " from the beginning of each line)
You will also need to install colorama: python3 -m pip install colorama
# import colorama
# colorama.init()
$ python3 jwt_tool.py <JWT>
or the Docker base command:
$ docker run -it --network "host" --rm -v "${PWD}:/tmp" -v "${HOME}/.jwt_tool:/root/.jwt_tool" ticarpi/jwt_tool
For example, to tamper the existing token run the following:
$ python3 jwt_tool.py eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.aqNCvShlNT9jBFTPBpHDbt2gBB1MyHiisSDdp8SQvgw -T
For example, to run a particular type of exploit you need to choose the eXploit (-X) option and select the vulnerability (here using "a" for the alg:none exploit):
$ python3 jwt_tool.py eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.aqNCvShlNT9jBFTPBpHDbt2gBB1MyHiisSDdp8SQvgw -X a
$ python3 jwt_tool.py eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.aqNCvShlNT9jBFTPBpHDbt2gBB1MyHiisSDdp8SQvgw -V -pk public.pem
You need to specify:
An example request might look like this (using scanning mode for forced-errors):
$ python3 jwt_tool.py -t https://www.ticarpi.com/ -rc "jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.bsSwqj2c2uI9n7-ajmi3ixVGhPUiY7jO9SUn9dm15Po;anothercookie=test" -rh "Origin: null" -cv "Welcome" -M er
$ python3 jwt_tool.py eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.aqNCvShlNT9jBFTPBpHDbt2gBB1MyHiisSDdp8SQvgw
$ python3 jwt_tool.py -t https://www.ticarpi.com/ -rc "jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.bsSwqj2c2uI9n7-ajmi3ixVGhPUiY7jO9SUn9dm15Po;anothercookie=test" -M pb
$ python3 jwt_tool.py -t https://www.ticarpi.com/ -rc "jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.bsSwqj2c2uI9n7-ajmi3ixVGhPUiY7jO9SUn9dm15Po;anothercookie=test" -X i -I -pc name -pv admin
$ python3 jwt_tool.py -t https://www.ticarpi.com/ -rc "jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.bsSwqj2c2uI9n7-ajmi3ixVGhPUiY7jO9SUn9dm15Po;anothercookie=test" -I -hc kid -hv custom_sqli_vectors.txt
$ python3 jwt_tool.py -t https://www.ticarpi.com/ -rc "jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.bsSwqj2c2uI9n7-ajmi3ixVGhPUiY7jO9SUn9dm15Po;anothercookie=test" -X i -I -pc name -pv admin
$ python3 jwt_tool.py -h
(make sure 'Case sensitive' and 'Regex' options are ticked)
[= ]eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9._-]*
- url-safe JWT version
[= ]eyJ[A-Za-z0-9_\/+-]*\.[A-Za-z0-9._\/+-]*
- all JWT versions (higher possibility of false positives)
Check out his blog on JWT weaknesses here: https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/