jwt_tool
jwt_tool copied to clipboard
Fix castInput crash on list/dict JWT claim values
I'm facing an issue with a JWT with nested claims; Anonymized JWT:
{"sessionId":"1234","sessionState":"loggedIn","user":{"id":"[email protected]","email":"[email protected]","displayName":"Foo Bar","groups":[{"id":"4321","name":"BAZ"}]},"iat":1,"exp":2}
Original JWT: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXNzaW9uSWQiOiIxMjM0Iiwic2Vzc2lvblN0YXRlIjoibG9nZ2VkSW4iLCJ1c2VyIjp7ImlkIjoiZm9vQGJhci5iYXoiLCJlbWFpbCI6ImZvb0BiYXIuYmF6IiwiZGlzcGxheU5hbWUiOiJGb28gQmFyIiwiZ3JvdXBzIjpbeyJpZCI6IjQzMjEiLCJuYW1lIjoiQkFaIn1dfSwiaWF0IjoxLCJleHAiOjJ9.
This resulted in:
./jwt_tool.py -t https://example.com -rh "Cookie: jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXNzaW9uSWQiOiIxMjM0Iiwic2Vzc2lvblN0YXRlIjoibG9nZ2VkSW4iLCJ1c2VyIjp7ImlkIjoiZm9vQGJhci5iYXoiLCJlbWFpbCI6ImZvb0BiYXIuYmF6IiwiZGlzcGxheU5hbWUiOiJGb28gQmFyIiwiZ3JvdXBzIjpbeyJpZCI6IjQzMjEiLCJuYW1lIjoiQkFaIn1dfSwiaWF0IjoxLCJleHAiOjJ9." -M at
\ \ \ \ \ \
\__ | | \ |\__ __| \__ __| |
| | \ | | | \ \ |
| \ | | | __ \ __ \ |
\ | _ | | | | | | | |
| | / \ | | | | | | | |
\ | / \ | | |\ |\ | |
\______/ \__/ \__| \__| \__| \______/ \______/ \__|
Version 2.3.0 \______| @ticarpi
/home/kali/.jwt_tool/jwtconf.ini
Original JWT: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXNzaW9uSWQiOiIxMjM0Iiwic2Vzc2lvblN0YXRlIjoibG9nZ2VkSW4iLCJ1c2VyIjp7ImlkIjoiZm9vQGJhci5iYXoiLCJlbWFpbCI6ImZvb0BiYXIuYmF6IiwiZGlzcGxheU5hbWUiOiJGb28gQmFyIiwiZ3JvdXBzIjpbeyJpZCI6IjQzMjEiLCJuYW1lIjoiQkFaIn1dfSwiaWF0IjoxLCJleHAiOjJ9.
=====================
Decoded Token Values:
=====================
Token header values:
[+] alg = "HS256"
[+] typ = "JWT"
Token payload values:
[+] sessionId = "1234"
[+] sessionState = "loggedIn"
[+] user = JSON object:
[+] id = "[email protected]"
[+] email = "[email protected]"
[+] displayName = "Foo Bar"
Traceback (most recent call last):
File "/home/kali/Python_VirtualEnvironments/jwt_tool/./jwt_tool.py", line 2152, in <module>
rejigToken(headDict, paylDict, sig)
~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/kali/Python_VirtualEnvironments/jwt_tool/./jwt_tool.py", line 1318, in rejigToken
comparestamps, expiredtoken = dissectPayl(paylDict)
~~~~~~~~~~~^^^^^^^^^^
File "/home/kali/Python_VirtualEnvironments/jwt_tool/./jwt_tool.py", line 1222, in dissectPayl
if type(castInput(paylDict[claim][subclaim])) == str:
~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/kali/Python_VirtualEnvironments/jwt_tool/./jwt_tool.py", line 610, in castInput
jsonInput = json.loads(newInput)
File "/usr/lib/python3.13/json/__init__.py", line 339, in loads
raise TypeError(f'the JSON object must be str, bytes or bytearray, '
f'not {s.__class__.__name__}')
TypeError: the JSON object must be str, bytes or bytearray, not list
jwt_tool crashes when decoding JWTs containing claims with list/dict values because castInput() always calls json.loads() and doesn’t handle non-string types, causing a TypeError: the JSON object must be str, bytes or bytearray, not list.
Sorry to do this, but it was the fastest/most direct approach for me to fix the issue; Buddy-boy ChatGPT proposed the following adjustment in the function castInput, which appears to be working for me.
def castInput(newInput):
# short-circuit for already structured types
if isinstance(newInput, (list, dict)):
return newInput
if isinstance(newInput, (bytes, bytearray)):
newInput = newInput.decode('utf-8', errors='replace')
if "{" in str(newInput):
try:
return json.loads(newInput)
except ValueError:
pass
if "\"" in str(newInput):
return str(newInput).strip("\"")
elif newInput in ("True", "true"):
return True
elif newInput in ("False", "false"):
return False
elif newInput == "null":
return None
else:
try:
numInput = float(newInput)
try:
return int(newInput)
except ValueError:
return numInput
except (ValueError, TypeError):
return str(newInput)