本文是ASP.NET反序列化漏洞的相关介绍。在PHP反序列化漏洞文章已经简单介绍过了序列化与反序列化的基本概念,最近抽空学习了一下.Net反序列化,于是简单总结一下学习到知识,首先简单介绍一下什么是序列化:
序列化是将对象处理为字节流的方式以便通过数据库、文件、网络方式传递与保存对象等。其主要目的是保存对象的状态保证数据易于存储和传输,以便可以在需要时重新创建对象。序列化的反过程称为反序列化,目的是将流恢复为对象。
.NET提供了多种反序列化方法,本文简单介绍一下XML序列化。
XML序列化
使用该序列化用到的类为System.Xml.Serialization.XmlSerializer。该反序列化过程可以注意的特点如下:
反序列化过程会调用反序列化类的构造器。
反序列化类为成员赋值时会调用setter方法,因此setter可以作为利用链的入口。
反序列化过程只能控制公共成员。
使用System.Xml.Serialization.XmlSerializer进行序列化的类不需要声明Serializable标识,因此可以利用的Gadget范围就变大了。
Gadget,顾名思义就是用来协助我们从调用setter方法到代码执行的工具类。
System.Windows.Data.ObjectDataProvider
要实现任意代码执行,主要依靠的就是该类。该类中的三个成员(MethodName、ObjectType、ObjectInstance)在调用setter方法时,会判断MethodName方法参数是否足够,足够则执行该方法。
通过这个类可以实现:
调用非默认构造方法。
所有不带参数的公共实例方法。
所有带可控参数的公共方法(包括静态、实例)。
比如执行以下代码:
执行后,即调用了Evil类中EvilMethod方法,参数为par。
这样,利用链第一步可以调用某类中某成员setter方法,通过使用ObjectDataProvider这个Gadget即转变为可调用某类中的方法。
为了方便理解,编写了一个常见的简化例子。
程序员使用XmlSerializer进行反序列化,反序列化的类型与数据用户可控。以下是代码,应该非常容易理解,用于接收用户提交的参数为xml、反序列化类型参数为type,使用该两者进行反序列化。
我们的目的是通过各种类构造利用链最终实现在反序列化过程调用Process.Start(“calc”),即弹出计算器,利用链并不是直接通过ObjectDataProvider直接调用Process类的Start方法即可完成,而需要调用XamlReader类Parse方法,间接调用Process类的Start方法,以下是最终payload。
提交的XML参数值:
提交的Type参数值:
直接提交,即可弹出计算器。
可以看到,使用XmlSerializer进行反序列化时,类型用户可控即可直接实现代码执行。
例子:DotNetNuke (CVE-2017-9822),该CMS从cookie接收序列化的信息,反序列化的类型用户可控,与上述例子想当接近。
参考链接:
https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf#page=33
使用XmlSerializer进行反序列化时,预先定义可反序列化的类型,不可以接收用户传入的类型进行反序列化。