Git Product home page Git Product logo

jwt_tool's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jwt_tool's Issues

json encoding differences cause canary value test to fail

Firstly, thanks for a great tool!

I'm not sure there's much that can be done about this, but I wanted to log it in case anyone else has the same experience.

If the original JWT token includes a (correctly) escaped forward slash in the issuer, such as {"iss":"my.domain.com\/iss-endpoint"}, then jwt_tool fails to recognise the canary value test has been met, such as:

[+] Sending token
jwttool_b5c2514b08df054d76b80e7d6a98c70d Sending token Response Code: 403, 91 bytes
Running Scanning Module:
Running prescan checks...
[+] FOUND "clickref" in response:
jwttool_86deb84549be4dcfd8661a928c5b76f8 Prescan: original token Response Code: 200, 254 bytes
Canary value (myvalue) was not found in base request - check that this token is valid and you are still logged in
Do you wish to continue anyway? ("Y" or "N")
Here you can see the original request failed with a 403 response, this seems to be due to how the rejigToken function works.

Having spent sometime looking in to this, it appears to be due to the json decoding and re-encoding not resulting in the same result, which invalidates the original signature.

This Python code may help illustrate it more:

import json

json_string = '{"iss":"my.domain.com\/iss-endpoint"}'#

json_object = json.loads(json_string)

new_json_string = json.dumps(json_object)

if json_string == new_json_string:
        print("json remains unchanged:" + new_json_string)
else:
        print("json had changed!  original:"+ json_string + "  new:" + new_json_string)

Running this will output:

$ python example.py
json had changed! original:{"iss":"my.domain.com\/iss-endpoint"} new:{"iss": "my.domain.com/iss-endpoint"}

For clarity my jwt_tool command was like:
python jwt_tool.py -pd "{MY POST DATA}" -t {MY URL} -rh "Authorization: Bearer {MY JWT}" -M pb -cv "myvalue"

The escaping of the forward slash as "\/" is valid (but optional) according to the specification.

I'm not sure whether it would be possible to "fix" this in jwt_tool or not?

base64.b64decode - Could not base64-decode payload

Hello,
The JTW token i was playing with contained some URL encoding in the payload.
Changing
payl = base64.b64decode(...)
to
payl = base64.urlsafe_b64decode(..)

Fixed the issue for me. :) Great tool btw.

MemoryError for too big dictionary

When you load a too big dictionary (here rockyou.txt that is 134Mo):

,----.,----.,----.,----.,----.,----.,----.,----.,----.,----.
----''----''----''----''----''----''----''----''----''----'
     ,--.,--.   ,--.,--------.,--------.             ,--.
     |  ||  |   |  |'--.  .--''--.  .--',---.  ,---. |  |
,--. |  ||  |.'.|  |   |  |      |  |  | .-. || .-. ||  |
|  '-'  /|   ,'.   |   |  |,----.|  |  ' '-' '' '-' '|  |
 `-----' '--'   '--'   `--''----'`--'   `---'  `---' `--'
,----.,----.,----.,----.,----.,----.,----.,----.,----.,----.
'----''----''----''----''----''----''----''----''----''----'
Traceback (most recent call last):
  File "jwt_tool/jwt_tool.py", line 253, in <module>
    keyLst = f.readlines()
MemoryError

Invalid token

I've seen a lot of this recently, but it's a valid token.
Invalid token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3VzZXJkYXRhIjoie1wiVXNlcklEXCI6MjMyLFwiVXNlck5hbWVcIjpcImFkbWluXCIsXCJEb21haW5OYW1lXCI6XCJDUERcIixcIk1vYmlsZVBob25lXCI6XCIxMzI0NDQ0NDQ0NFwiLFwiSUVNSVwiOlwiXCIsXCJXb3JrUm9sZU5hbWVcIjpcIuezu-e7n-euoeeQhuWRmFwiLFwiV29ya1JvbGVDb2RlXCI6XCIxXCIsXCJJc1JlZ2lvblwiOjAsXCJQYXJlbnRJRFwiOm51bGwsXCJQYXJlbnROYW1lXCI6XCJcIixcIlN0YXR1c0lEXCI6MyxcIlJlZ2lvbklEXCI6bnVsbCxcIlJlZ2lvbk5hbWVzXCI6XCLlhajlm71cIixcIkNpdHlJRFwiOjEsXCJMb2dpbklEXCI6XCJhZG1pblwiLFwiUGFyZW50TG9naW5JRFwiOlwiXCIsXCJEb21haW5JRFwiOjEsXCJUaGlyZENvbXBhbnlJRFwiOm51bGwsXCJJc1RoaXJkQ29tcGFueVVzZXJcIjp0cnVlLFwiRFBSb2xlVHlwZVwiOjksXCJEUFR5cGVJRFwiOm51bGwsXCJQZXJtaXNzaW9uc1wiOm51bGwsXCJVc2VyQ2hhbm5lbFR5cGVcIjpudWxsLFwiQXZhdGFyVXJsXCI6XCIvc2ZhaW1hZ2UxLzIwMTkwMzIxLzIzMlxcXFw1MDcwNzdfMjAxOTAzMjExNjU1NTlmMGIwZTYxZS1hMDNiLTQyNjUtOWRlNi03NWE4ZDFiNDY5YjYuanBnXCIsXCJJc1Byb21vdGVyVGVhbVwiOm51bGwsXCJCdXNpbmVzc01vZGVsSURTXCI6bnVsbCxcIkNvdW50ZXJCcmFuZElEU1wiOm51bGwsXCJDaGFpbnN0b3JlSURTXCI6bnVsbCxcIkVtYWlsXCI6bnVsbH0iLCJuYmYiOjE1NzUwMDMxNTAsImV4cCI6MTU3NTAwNDk1MCwiaWF0IjoxNTc1MDAzMTUwLCJpc3MiOiJBNUZHREU2NC1FODRELTQ4NUEtQkU1MS01NkUyOTNEMDlBNjkiLCJhdWQiOiIwOTkxNTNjMjYyNTE0OWJjOGVjYjNlODVlMDNmMDAyMiJ9.xp5TmBFi0Nr89SeClOIcbtIRcU4BTZDCMNVZiBew9W4

No space between curl and url

There is no space between the curl command and its parameter (injectUrl). Is it done purposely? In what situation would it execute properly?

newheadDict, newHeadB64 = injectheaderclaim("kid", "|curl"+injectUrl)

{"typ":"JWT","alg":"HS256","kid":"|curlhttp://example.com/RCE_in_kid"}

Is jwt_tool support /dev/null attack?

PS C:\Users\WhoAmI\Desktop> python3 $jwt_tool eyJraWQiOiJlYThmNjRjNi1hM2VmLTRiZDctOWRmYi1iNjM0YmRkZjViMmIiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsInN1YiI6IndpZW5lciIsImV4cCI6MTY1NTM4NDY1NX0.MCxsDgrmR5GDgncc7o0hh1eM5jcnzOnl7eKPoCiZ6Yc -I -hc kid -hv "../../../../../../dev/null" -S hs256 -p ""
usage: jwt_tool.py [-h] [-b] [-t TARGETURL] [-rc COOKIES] [-rh HEADERS] [-pd POSTDATA] [-cv CANARYVALUE] [-np]
                   [-M MODE] [-X EXPLOIT] [-ju JWKSURL] [-S SIGN] [-pr PRIVKEY] [-T] [-I] [-hc HEADERCLAIM]
                   [-pc PAYLOADCLAIM] [-hv HEADERVALUE] [-pv PAYLOADVALUE] [-C] [-d DICT] [-p PASSWORD] [-kf KEYFILE]
                   [-V] [-pk PUBKEY] [-jw JWKSFILE] [-Q QUERY] [-v]
                   [jwt]
jwt_tool.py: error: argument -p/--password: expected one argument

RFE: support for XMLDSIG algorithms for alg header

I recently encountered a valid JWT (well, valid at least for the app that used it) that could not be handled by jwt_tools because it used an invalid value in the 'alg' header; instead of HS512 it contained "http://www.w3.org/2001/04/xmldsig-more#hmac-sha512". This is apparently used for XML formatted data, and is detailed in RFC 4051.
I am not sure if this is commonly used, maybe it could be interesting to support it.
Commit of a quick and dirty implementation for my use case: DidierA@d3b1bb8

Timestamp difference reported incorrectly?

On version 2.2.1 but I think i saw it on the previous version as well:

Seen timestamps:
[] exp was seen <-nothing here
[
] iat is earlier than exp by: 0 days, 0 hours, 0 mins

JSON dump separators

In jwt_tool.py, after a payload is modified, you use json.dumps() to convert the ordered dictionary into a json object, then b64 encode it.

newPaylB64 = base64.urlsafe_b64encode(json.dumps(newpaylDict,separators=(",",":")).encode()).decode('UTF-8').strip("=")

My question is regarding the json.dumps() compact encoding (i.e. the separators=(",",":")). The result is that spaces in the json object are removed so a payload like this {"login": "taylor"}becomes {"login":"taylor"}. The space after the colon has been removed.

Referring to RFC 7519 standard:
"The JSON object consists of zero or more name/value pairs (or members), where the names are strings and the values are arbitrary JSON values. These members are the claims represented by the JWT. This JSON object MAY contain whitespace and/or line breaks before or after any JSON values or structural characters ..."

Thank you for the tool!

why python 2?

I'm new to Python, and also newer to security.

This seems like a newer project.
Why did you write it in Python 2 when end of life for python 2 now has a definite date?

No judgement here...I'm just trying to learn.

cprint() miss the color arg

error:

File "/mnt/hgfs/Tools/jwt_tool/jwt_tool.py", line 1238, in validateToken
    cprintc(head.decode('UTF-8'))

line 1238 and 1248 miss the color arg.

key length VS hash length

Thanks for the tool, it works very well. However, I was a little confused when I resigned a token with RS256 with a private key I had because the tool asked me for the key length. So i checked the private key and it was a key with a key length of 1024bit, but I was only able to choose from an option of 256, 384, 512:

if keyLength == 256:

https://github.com/ticarpi/jwt_tool/blob/master/jwt_tool.py#L1035
So what you wanted to ask was the hash length (or signature length), because you will use it to determine the hash algorithm to use. Key length is something different.

TypeError

When running python3 jwt_tool.py -T or -R i get:

Traceback (most recent call last):
File "jwt_tool.py", line 1393, in
tamperToken(paylDict, headDict, sig)
File "jwt_tool.py", line 761, in tamperToken
comparestamps, expiredtoken = dissectPayl(paylDict, count=True)
File "jwt_tool.py", line 1187, in dissectPayl
elif type(castInput(paylDict[claim][subclaim])) == str:
File "jwt_tool.py", line 91, in castInput
newInput = json.loads(newInput)
File "C:**\AppData\Local\Programs\Python\Python38-32\lib\json_init_.py", line 341, in loads
raise TypeError(f'the JSON object must be str, bytes or bytearray, '
TypeError: the JSON object must be str, bytes or bytearray, not list

or

Traceback (most recent call last):
File "jwt_tool.py", line 1483, in
rejigToken(headDict, paylDict, sig)
File "jwt_tool.py", line 1280, in rejigToken
comparestamps, expiredtoken = dissectPayl(paylDict)
File "jwt_tool.py", line 1187, in dissectPayl
elif type(castInput(paylDict[claim][subclaim])) == str:
File "jwt_tool.py", line 91, in castInput
newInput = json.loads(newInput)
File "C:**\AppData\Local\Programs\Python\Python38-32\lib\json_init_.py", line 341, in loads
raise TypeError(f'the JSON object must be str, bytes or bytearray, '
TypeError: the JSON object must be str, bytes or bytearray, not list

Error when running -M at at windows

Hello :)

I have an error when i run the tool at windows with the following command:

python jwt_tool.py -M at -t "https:///api/auth/myself" -rh "Authorization: Bearer *" -rc "COOKIES"

The following error occurred (like in the screenshot):

UnicodeDecodeError: 'charmap' codec can't decode byte 0x8f in position 1824: character maps to <undefined>

Can you take care of it?

Thanks

image

[Feature Suggestion] Test exposure to CVE-2022-21649

Hi,

After reading this blog post about the CVE-2022-21449, I was wondering if it can be interesting to add a test case with a JWT token for which the signature will be filled with 0 and the algorithm will be ES256, ES256K, ES384 or ES512 (see here)?

Example:

eyJhbGciOiJFUzI1NiJ9.eyJzdWIiOiJURVNUIn0.MAYCAQACAQA

image

Sample vulnerable app:

https://github.com/DataDog/security-labs-pocs/tree/main/proof-of-concept-exploits/jwt-null-signature-vulnerable-app

It is just a suggestion so feel free to close this issue if it is not relevant ๐Ÿ˜ƒ

Support for HTTP/2

Hi,
are you thinking to add support for HTTP/2 reuqests?
I was able to replace the protocol with a proxy but a native support would be great.
Thanks

Error during signature verification.

Hi, I'm using jwt_tool to perform attacks on a JWT token using the RS256 algorithms. I have the public key to check for the signature, but the tool is telling me that the signature is invalid. My token is valid, I can use it on my application and I checked with the PyJWT library which also say that the token is valid. So I'm wondering why the jwt_tool.py script say that the signature is not valid.

$ cat key.pub
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq/Uptco13UyCUkJA9yTB
ZXsQWDA7UeAXr6qzD8TlEgwrV+bygZfa/sENCEf1c+ih78nlcxAYcnOE5tBToxH4
p7RqhosrshZnfQa7vycP4U9z0LEAJLOrfVi/FOEoIyXJXQ4A3wLDOm2kWLGUZTpA
A+RaQKkunwNkUbATL1N9jbG19VEH0/hsBPr5JDs9UlIqTs8h1DjzDfXr6dapdUd6
3ZjBzO+GTheyZoRf93Aqfp54f/AN0VsZ5QhUcFRqr6koZPB7cPDK4HsYAhRuf4xD
pTeILoQ72teCrpLfCZKh0nAView8MbJP3UYZZNmzMOlaE/zTi2W3HWVp4uDEkF8B
cQIDAQAB
-----END PUBLIC KEY-----

$ python3 jwt_tool.py -V -pk key.pub eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJWLWluY0lORkJRUF9Ucm9MbGZuYUFvdnk0VGgxNUxLQzNBR2IzZFI5cVg0In0.eyJleHAiOjE2MTc4ODM4MzYsImlhdCI6MTYxNzg4MzUzNiwiYXV0aF90aW1lIjoxNjE3ODgzNTM1LCJqdGkiOiI4MTllMWM3ZC1mNTAwLTQ3MmQtODk1ZC01NmVjMWQ4NTEzY2EiLCJpc3MiOiJodHRwczovLzAuMC4wLjA6ODQ0My9hdXRoL3JlYWxtcy90ZXN0IiwiYXVkIjoiYWNjb3VudCIsInN1YiI6IjI3ZTYzNWFjLTEyMDAtNGRiYy05ZmIzLWFkNjE2ZWI2MjZmMCIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFjY291bnQtY29uc29sZSIsIm5vbmNlIjoiYjQwOWM5ZTctZjVhOC00YzFkLTg2NTctOGIyODAyZTdhZWM5Iiwic2Vzc2lvbl9zdGF0ZSI6IjFkMjJkODM2LTVjY2MtNDBjZi1hNzNlLWYxNGYzYjhjYTdhNSIsImFjciI6IjEiLCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIl19fSwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicHJlZmVycmVkX3VzZXJuYW1lIjoidGVzdCJ9.koCgf_1AIzusXLsiMuKTBKP0-dBdC8SPXEe1Bk5KeAZFQptXeMW8RZWWOEarJy9mp9HCVTv4eQRRx7lTjmVlVvpd2InrdjzcLjesmhOYYz7jBPPfFQm9lsu04WaSw9IBXeYp7f0m45kxjwX8eb36rtLUKQDssFyWWdjE5-_JRrHjA7wxHsHRFwcf4lSCnTnULXsA-7tvSHb7bnN93u2FBP9-J97eInb89pCoM13xKiwD9UBrkVoXiWNCqRPaq20zTyH9tajh8J9ebaIkBklb9xby1_224o6g6ilqQUy_8Hwy6ByEBL6q83EfQxfwpi8tVTyqCsNtlXBAEO1OorXy5Q
                                   
        \   \        \         \          \                    \ 
   \__   |   |  \     |\__    __| \__    __|                    |
         |   |   \    |      |          |       \         \     |
         |        \   |      |          |    __  \     __  \    |
  \      |      _     |      |          |   |     |   |     |   |
   |     |     / \    |      |          |   |     |   |     |   |
\        |    /   \   |      |          |\        |\        |   |
 \______/ \__/     \__|   \__|      \__| \______/  \______/ \__|
 Version 2.2.2                \______|             @ticarpi      

Original JWT: 

RSA Signature is INVALID

With the PyJWT library the signature verification suceeds:

>>> token = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJWLWluY0lORkJRUF9Ucm9MbGZuYUFvdnk0VGgxNUxLQzNBR2IzZFI5cVg0In0.eyJleHAiOjE2MTc4ODM4MzYsImlhdCI6MTYxNzg4MzUzNiwiYXV0aF90aW1lIjoxNjE3ODgzNTM1LCJqdGkiOiI4MTllMWM3ZC1mNTAwLTQ3MmQtODk1ZC01NmVjMWQ4NTEzY2EiLCJpc3MiOiJodHRwczovLzAuMC4wLjA6ODQ0My9hdXRoL3JlYWxtcy90ZXN0IiwiYXVkIjoiYWNjb3VudCIsInN1YiI6IjI3ZTYzNWFjLTEyMDAtNGRiYy05ZmIzLWFkNjE2ZWI2MjZmMCIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFjY291bnQtY29uc29sZSIsIm5vbmNlIjoiYjQwOWM5ZTctZjVhOC00YzFkLTg2NTctOGIyODAyZTdhZWM5Iiwic2Vzc2lvbl9zdGF0ZSI6IjFkMjJkODM2LTVjY2MtNDBjZi1hNzNlLWYxNGYzYjhjYTdhNSIsImFjciI6IjEiLCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIl19fSwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicHJlZmVycmVkX3VzZXJuYW1lIjoidGVzdCJ9.koCgf_1AIzusXLsiMuKTBKP0-dBdC8SPXEe1Bk5KeAZFQptXeMW8RZWWOEarJy9mp9HCVTv4eQRRx7lTjmVlVvpd2InrdjzcLjesmhOYYz7jBPPfFQm9lsu04WaSw9IBXeYp7f0m45kxjwX8eb36rtLUKQDssFyWWdjE5-_JRrHjA7wxHsHRFwcf4lSCnTnULXsA-7tvSHb7bnN93u2FBP9-J97eInb89pCoM13xKiwD9UBrkVoXiWNCqRPaq20zTyH9tajh8J9ebaIkBklb9xby1_224o6g6ilqQUy_8Hwy6ByEBL6q83EfQxfwpi8tVTyqCsNtlXBAEO1OorXy5Q"
>>> pub_key = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq/Uptco13UyCUkJA9yTBZXsQWDA7UeAXr6qzD8TlEgwrV+bygZfa/sENCEf1c+ih78nlcxAYcnOE5tBToxH4p7RqhosrshZnfQa7vycP4U9z0LEAJLOrfVi/FOEoIyXJXQ4A3wLDOm2kWLGUZTpAA+RaQKkunwNkUbATL1N9jbG19VEH0/hsBPr5JDs9UlIqTs8h1DjzDfXr6dapdUd63ZjBzO+GTheyZoRf93Aqfp54f/AN0VsZ5QhUcFRqr6koZPB7cPDK4HsYAhRuf4xDpTeILoQ72teCrpLfCZKh0nAView8MbJP3UYZZNmzMOlaE/zTi2W3HWVp4uDEkF8BcQIDAQAB\n-----END PUBLIC KEY-----"
>>> jwt.decode(token, key=pub_key, algorithms=['RS256'], verify_signature=True, audience="account")
{'exp': 1617883836, 'iat': 1617883536, 'auth_time': 1617883535, 'jti': '819e1c7d-f500-472d-895d-56ec1d8513ca', 'iss': 'https://0.0.0.0:8443/auth/realms/test', 'aud': 'account', 'sub': '27e635ac-1200-4dbc-9fb3-ad616eb626f0', 'typ': 'Bearer', 'azp': 'account-console', 'nonce': 'b409c9e7-f5a8-4c1d-8657-8b2802e7aec9', 'session_state': '1d22d836-5ccc-40cf-a73e-f14f3b8ca7a5', 'acr': '1', 'resource_access': {'account': {'roles': ['manage-account', 'manage-account-links']}}, 'scope': 'openid email profile', 'email_verified': False, 'preferred_username': 'test'}

Thanks !

Annoying quotation marks at input when tampering JWT

Hi @ticarpi

While trying to tamper JWT values, I figured out that, when providing an input, it adds annoying quotation marks, resulting in an error for integers (e.g. ValueError: invalid literal for int() with base 10: '"12345"') and making invalid strings.

ValueError: year 53831 is out of range

Traceback (most recent call last):
  File "/opt/jwt_tool/jwt_tool.py", line 2028, in <module>
    rejigToken(headDict, paylDict, sig)
  File "/opt/jwt_tool/jwt_tool.py", line 1291, in rejigToken
    comparestamps, expiredtoken = dissectPayl(paylDict)
  File "/opt/jwt_tool/jwt_tool.py", line 1185, in dissectPayl
    timestamp = datetime.fromtimestamp(int(paylDict[claim]))
ValueError: year 53831 is out of range

Codecmap issues because no encoding type specified in the lines [269, 1495]

This issue happened for me on Windows 10.
JWT_Tool 2.2.5

The following error happened:-

Traceback (most recent call last):
  File "C:\Users\PC\Desktop\jwt_tool-2.2.5\jwt_tool-2.2.5\jwt_tool.py", line 2104, in <module>
    runScanning()
  File "C:\Users\PC\Desktop\jwt_tool-2.2.5\jwt_tool-2.2.5\jwt_tool.py", line 1697, in runScanning
    scanModePlaybook()
  File "C:\Users\PC\Desktop\jwt_tool-2.2.5\jwt_tool-2.2.5\jwt_tool.py", line 1496, in scanModePlaybook
    commonPass = commonPassList.readline().rstrip()
  File "C:\Users\PC\AppData\Local\Programs\Python\Python39\lib\encodings\cp1252.py", line 23, in decode
    return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8f in position 1734: character maps to <undefined>

I fixed it by adding the argument "encoding='utf-8'" to the open() function in line 1495.

After that the following error happened:-

Traceback (most recent call last):
  File "C:\Users\PC\Desktop\jwt_tool-2.2.5\jwt_tool-2.2.5\jwt_tool.py", line 2104, in <module>
    runScanning()
  File "C:\Users\PC\Desktop\jwt_tool-2.2.5\jwt_tool-2.2.5\jwt_tool.py", line 1697, in runScanning
    scanModePlaybook()
  File "C:\Users\PC\Desktop\jwt_tool-2.2.5\jwt_tool-2.2.5\jwt_tool.py", line 1499, in scanModePlaybook
    jwtOut(newContents+"."+newSig, "Checking for alternative accepted HMAC signatures, based on common passwords. Testing: "+commonPass+"", "This token can exploit a hard-coded common password in the config")
  File "C:\Users\PC\Desktop\jwt_tool-2.2.5\jwt_tool-2.2.5\jwt_tool.py", line 261, in jwtOut
    setLog(token, genTime, logID, fromMod, curTargetUrl, additional)
  File "C:\Users\PC\Desktop\jwt_tool-2.2.5\jwt_tool-2.2.5\jwt_tool.py", line 270, in setLog
    logFile.write(logID+" - "+logLine+" - "+jwt+"\n")
  File "C:\Users\PC\AppData\Local\Programs\Python\Python39\lib\encodings\cp1252.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode characters in position 152-182: character maps to <undefined>

I fixed it by adding the argument "encoding='utf-8'" to the open() function in line 269.

After that the script worked totally fine, the "encoding" argument should always be specified in any call for the "open()" function to prevent any confusion for characters that is not included in ASCII charset, other argument can be added to to ignore any characters that don't exist even in the utf-8 charset, the "ignore" parameter.

OrderedDict mutated during iteration

Hi,
for me, launching the tool produces the following error when checking for external interaction :

Traceback (most recent call last):
File "/home/csaudit/jwt_tool/jwt_tool.py", line 2098, in
runScanning()
File "/home/csaudit/jwt_tool/jwt_tool.py", line 1703, in runScanning
scanModePlaybook()
File "/home/csaudit/jwt_tool/jwt_tool.py", line 1489, in scanModePlaybook
for payloadClaim in backupDict:
RuntimeError: OrderedDict mutated during iteration

It seems to be caused by the del statement in the function injectExternalInteractionPayload (line 1639), as replacing it with a print statement fixes the issue. Am I doing anything wrong or is this a bug?

Best,
FH

-T and -X k -pk do not seem to combine

In version 2.2.3, when -T is combined with -X k -pk, the output does not contain the tampered results. It seems these flags cannot be used together.

Workaround: Using -T alone works. The output from a -T run can then be used as the input for a -X k -pk run to get the desired results.

URL Encoding of JWKS URL Fails Parsing

Expected Behavior

The JWKS URL (specified with -ju) should be able to handle % encoded URL characters.

Current Behavior

A parsing error happens when a % encoded URL character is found during parsing.

Possible Solution/Implementation

It looks like pythons configParser libary attempts to interpolate anything with a % sign preceding it, possibly replace all single % signs with a double % sign (%%) as this should escape the configParser trying to interpolate the string.

image

Steps to Reproduce

  1. ./jwt_tool.py -X s -ju http://notarealsite.net/?value=test%20 eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.bsSwqj2c2uI9n7-ajmi3ixVGhPUiY7jO9SUn9dm15Po
  2. observe parsing error
    image

In the meantime, I might just write a small script that uses regex to replace single % with double %% before passing it through to the tool.

nested jwt token error

when i try to tamper the nested value of a jwt token i got this error :

Traceback (most recent call last):
File "/usr/local/bin/jwt_tool", line 1403, in
tamperToken(paylDict, headDict, sig)
File "/usr/local/bin/jwt_tool", line 795, in tamperToken
newVal[subclaim] = paylDict[pair][subclaim]
TypeError: 'int' object is not subscriptable

Load postdata from file

It seems like loading postdata from a file is not supported (or if it is it's not obvious). This would be a really nice feature to have for those times when a the request is larger.

TIMESTAMP Error

Hello there,

I get the following error message. It looks like it is failing on the TIMESTAMP:

> python3 jwt_tool.py [JWT_TOKEN]

=====================
Decoded Token Values:
=====================

Token header values:
[+] typ = "JWT"
[+] alg = "HS512"

Token payload values:
[+] UserId = "215"
[+] App = "C467**********************"
[+] iss = "************* JWT"
[+] VenueId = 265
[+] UserName = "*************"
[+] VenueName = "*************"
[+] VenueType = 1
[+] SysCategory = 0
[+] aud = "C46***************************************"
[+] exp = 1594211740    ==> TIMESTAMP = 2020-07-08 13:35:40 (UTC)
Traceback (most recent call last):
  File "jwt_tool.py", line 1483, in <module>
    rejigToken(headDict, paylDict, sig)
  File "jwt_tool.py", line 1280, in rejigToken
    comparestamps, expiredtoken = dissectPayl(paylDict)
  File "jwt_tool.py", line 1171, in dissectPayl
    timestamp = datetime.datetime.fromtimestamp(int(paylDict[claim]))
ValueError: invalid literal for int() with base 10: '07/07/2020 12:35:40'

Thanks

wordlist loaded entirely into RAM

When using crackstation's wordlist (which is about 15GB) I went into swapping hell but luckily the python interpreter was nice and killed the process. Is there an easy way to load the wordlist in batches?

Access is Denied

hi, i followed everything in the readme document

im on windows 10, have python3.8 install

i pip installed the repo and tried to run it with

python3 jwt_tool.py (token)

but it just returns "access is denied".

any ideas on how to proceed? Many thanks

image

Regex doesn't recognize JWT token

In the latest version (2.2.5) the regex to find the JWT token is set to the following. However, the payload of the token I was about to test started with eyI. This didn't match the regex and resulted in Cannot find a valid JWT.

eyJ[A-Za-z0-9_\/+-]*\.eyJ[A-Za-z0-9_\/+-]*\.[A-Za-z0-9._\/+-]*

Modifying all regexes in the code to the following resolved my issue.

eyJ[A-Za-z0-9_\/+-]*\.ey[A-Za-z0-9_\/+-]*\.[A-Za-z0-9._\/+-]*

Crack with values

When i add values choosing 1 but after that no cracking options shows.

Error

Traceback (most recent call last):
File "/home/emily/Tools/jwt_tool/jwt_tool.py", line 2024, in
rejigToken(headDict, paylDict, sig)
File "/home/emily/Tools/jwt_tool/jwt_tool.py", line 1327, in rejigToken
jwtOut(newContents+"."+sig, "Sending token")
File "/home/emily/Tools/jwt_tool/jwt_tool.py", line 231, in jwtOut
resData = sendToken(token, cookiedict, logID, headertoken[0], posttoken[0])
File "/home/emily/Tools/jwt_tool/jwt_tool.py", line 150, in sendToken
response = requests.get(url, headers=headers, cookies=cookiedict, proxies=False, verify=False)
File "/usr/lib/python3/dist-packages/requests/api.py", line 76, in get
return request('get', url, params=params, **kwargs)
File "/usr/lib/python3/dist-packages/requests/api.py", line 61, in request
return session.request(method=method, url=url, **kwargs)
File "/usr/lib/python3/dist-packages/requests/sessions.py", line 528, in request
prep = self.prepare_request(req)
File "/usr/lib/python3/dist-packages/requests/sessions.py", line 456, in prepare_request
p.prepare(
File "/usr/lib/python3/dist-packages/requests/models.py", line 317, in prepare
self.prepare_headers(headers)
File "/usr/lib/python3/dist-packages/requests/models.py", line 451, in prepare_headers
check_header_validity(header)
File "/usr/lib/python3/dist-packages/requests/utils.py", line 957, in check_header_validity
raise InvalidHeader("Invalid return character or leading space in header: %s" % name)
requests.exceptions.InvalidHeader: Invalid return character or leading space in header: Authorization

I made sure to triple check that the character/leading space in the header Authorization is correct as well as the rest of the syntax for my arguments. Any ideas? Thanks!!
I am using the most recent version of Kali Linux that's running on virtualbox installed on my Windows machine.

Inventory notification

Your tool/software has been inventoried on Rawsec's CyberSecurity Inventory.

https://inventory.rawsec.ml/tools.html#jwt_tool

What is Rawsec's CyberSecurity Inventory?

An inventory of tools and resources about CyberSecurity. This inventory aims to help people to find everything related to CyberSecurity.

More details about features here.

Note: the inventory is a FLOSS (Free, Libre and Open-Source Software) project.

Why should you care about being inventoried?

Mainly because this is giving visibility to your tool and improve its referencing.

Badges

The badge shows to your community that your are inventoried. It looks good but also shows you care about your project, that your tool is referenced.

Feel free to claim your badge here: http://inventory.rawsec.ml/features.html#badges, it looks like that Rawsec's CyberSecurity Inventory, but there are several styles available.

Want to thank us?

If you want to thank us, you can help make our open project better known by tweeting about it! For example: Twitter URL

So what?

That's all, this message is just to notify you if you care. Else you can close this issue.

Infinite loop on error

$ python jwt_tool.py 'ew...Ry' /usr/share/wordlists/password/rockyou.txt
Token header values:                                                                                                                                                                                                                                                            
[+] alg = ES512                                                                                                                                                                                                                                                                 
[+] typ = JWT
#  6: Crack signature with supplied dictionary file    #

When I use option 6 on a ES512, I have the following error.

Algorithm is not HMAC-SHA - cannot test with this tool.                                                                                                                                                                                                                         

Which seems normal but the problem is that it loops over it indefinitely.

Asciinema

I made a asciinema "video" of it.

asciinema.zip

To play it: asciinema play xxx.cast

Exit code 1 on success

On shells, the exit code 1 means error. However, if you run these commands below, they all exit the error code 1

python3 jwt_tool.py eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.bsSwqj2c2uI9n7-ajmi3ixVGhPUiY7jO9SUn9dm15Po
python3 jwt_tool.py --exploit n eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.bsSwqj2c2uI9n7-ajmi3ixVGhPUiY7jO9SUn9dm15Po
python3 jwt_tool.py --query jwttool_298d3877b773b51a46e8dc441d1a9453

What are the reasons of using exit(1) instead of exit(0)?

And thinking about integration with other tools (like CI/CD for automated testing, like I am doing here with CORScanner for securing our own applications), could we change the behavior to the one below?

  • Exit code 1 when there is an error on CLI params/options (Ex: python3 jwt_tool.py -X hello -p)
  • Exit any code in 3-125 range for vulnerabilities found with given tests (Ex: found CVE-2015-2951 alg=none on https://example.com/)
  • Exit code 0 (for success) when no vulnerability is found with the given tests (Ex: tested https://example.com/ against CVE-2018-0114 Key injection but website passed test)

How to add multiple headers?

Hey! I'm trying to add multiple headers to the request but i'm getting erros.
How the syntax is supposed to be? In my example I need to use three headers: Authorization, Origin and Host

Appreciate any help

Nested Cookie values not working for tampering

Selecting to modify the second element with an intention to modify the username causes an error

Please select an option from above (1-5):
> 2
[1] status = "success"
[2] data = JSON object:
    [+] id = true
    [+] username = ""

Results in:

(or 0 to Continue)
id
Traceback (most recent call last):
  File "jwt2_tool.py", line 1888, in <module>
    runActions()
  File "jwt2_tool.py", line 1590, in runActions
    tamperToken(paylDict, headDict, sig)
  File "jwt2_tool.py", line 370, in tamperToken
    newVal[subclaim] = paylDict[pair][subclaim]
TypeError: 'int' object is not subscriptable

Supporting GET method

I know this is really bad practise, but currently I'm pentesting an API which is sending the JWT as a simple get parameter. JWT_Tool does not support this case.
Maybe it can/should be added for such cases?

Thanks for this great tool!

stripping off "=" on line 320 in jwt_tool.py caused invalid payload.

command used
python3 ./jwt_tool.py "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1c2VybmFtZSI6InRlc3QifQ.GU72t7mfy31jMvyY7hSinJBtAntSqjeuqJa6el2PGPaq36hkZtn8fVo8JEgv7hnEdOHkibVLz9MLUca12yLmbylSxl-Nh2_pMf2s03JBsKs7oIJeBKjj7Pw4lXp1TQQj6ISTwzeBNAUlv4VXJ11G-mPFKwYxTOQg7IX0FxyGMlGbLKoe3TXbw7trXwXevC9O_q_cxHRFMINg9vPAATKI0_PfMJPGBdewILLf1aExd37QhTUts8IE11ak3To8TDnQZ14h14evccnWfVp8sQOFo81Rlp5r1j3WBQnaEsYhVMKuBgW2osceqgFG8ABIYj8eF7vtRzaJUMTVe_dUk0x43A8Meb5Xe2TdyIOkhoQPHTZ3BYxLX4pW_yrjjPSAWSfCAEm07fqYc4tP7IXvZ7rtlGwq_eMoBotGj8KJAI1FqAc1kh6fC0KdQvvAY2XhifJZArCpXsRiyoSdjB5oJVeDlsjyQ4HUcgfn8Yn0sEdC6tqyATIAMMWaGMDb54Iw0NX7F4P2VrCeZ75A3K-patffZFxyssqeS-rMYkbn8O7lXfaxoe8us-IKN5wCwNBp82CSU0qR8U2iWU4Or22kNBRFuVV5sr2huMkIf1dodVmpodAExfiwEs28DCkKf9y5uV6fHJohX1Bo31JdghbsgPufM_z3GD1HSfBaMUpUSO6vJME" -v -X k -I -pc username -pv admin -pk ../public.pem

new payload generated

eyJ1c2VybmFtZSI6ImFkbWluIn0 with '=' stripped off. I understand that during transport = can be stripped off and but then inserted before decoding. Some server APIs processing jwt don't do that, hence it causes the failure. I would request not to strip off "=" signs to be safe.

I spent several hours trouble shooting this.

echo eyJ1c2VybmFtZSI6ImFkbWluIn0 | base64 -d. ( this causes the } in payload to strip off
{"username":"admin%
------- correct
echo eyJ1c2VybmFtZSI6ImFkbWluIn0= | base64 -d
{"username":"admin"}%

jwtconf.ini wrong path

Windows 10
JWT_Tool 2.2.5

When jwt_tool.py run for the first time, it mentioned the creation of jwtconf.ini, but I couldn't find it in the jwt_tool.py directory (C:\Users\PC\Desktop\jwt_tool-2.2.5\jwt_tool-2.2.5), and still jwt_tool worked totally fine like it found that config file.

So I added a print statement for the path variable, and it printed this path (C:\Users\PC/.jwt_tool)

I not sure why it created it there and why the path separation character is inverted, but it seems like the function "os.path.join()" wasn't used to create paths, it handles the operating system pathing standards.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.