Younge学习.NET反序列化漏洞
Posted 神月资讯
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Younge学习.NET反序列化漏洞相关的知识,希望对你有一定的参考价值。
0x01 前言
在上一篇文章《》已经简单介绍了错误使用XmlSerializer类进行反序列化时可能造成远程代码执行的问题,除了XmlSerializer外,.NET下还提供了其他序列化类,错误使用其他序列化类同样可导致远程代码执行。
0x02 序列化与反序列化
.NET提供了多种序列化方法,上文简单介绍了使用XmlSerializer进行序列化,攻击者可通过ObjectDataProvider类、System.Windows.Markup.XamlReader类实现反序列化过程代码执行,而除了该类外,常用的还有二进制序列化。
二进制序列化
二进制序列化用到的类为System.Runtime.Serialization.Formatters.Binary.BinaryFormatter。该反序列化过程可以注意的特点如下:
BinaryFormatter仅能反序列化声明了Serializable的类。
反序列化对象时,类的常规构造函数不会被调用,任何依赖于常规构造函数的代码不会执行。
反序列化过程会调用OnDeserialized、OnDeserializing方法。
反序列化的类实现了ISerializable接口,反序列化过程会调用用户自定义的反序列化过程方法,方法名定义类似构造函数,方法为类名加两个参数(SerializationInfo与StreamingContext),如classname(SerializationInfo info,StreamingContext context)。
反序列化的类实现了IDeserializationCallback接口,反序列化过程会调用IDeserializationCallback.OnDeserialization(Objectsender)方法。
反序列化的类实现了IObjectReference接口,反序列化过程会调用GetRealObject(StreamingContext context)方法。
反序列化的类如果自定义了析构方法,也存在风险,虽然反序列化过程并不会直接调用析构方法,但在对象被垃圾回收器回收的时候,析构函数被GC自动调用。自定义析构方法名为类名前加~,如~classname()。
总结就是下图中定义的类,在反序列化该类时会调用图中定义的除析构方法外的所有方法。
0x03 Gadget
.NET Framework的部分类可以协助攻击者完成一些危险操作。在2012年James Forshaw演讲的议题《Are you my Type?》就已经提到过一些可被利用的类:
TempFileCollection:
该类自定义了析构方法,当该类对象被回收时,会调用自定义析构方法,该析构方法中会删除files字段上的文件,导致任意文件删除漏洞。
System.IO.FileSystemInfo:
FileSystemInfo类是提供文件系统信息(如FileInfo和DirectoryInfo)类的基类,它实现了ISerializable接口,反序列化期间会调用自定义的反序列化方法,使得可自动创建SMB请求。
SortedSet & ComparisonComparer:
而在17年4月,他又提出了可以通过SortedSet类与ComparisonComparer类实现反序列化时代码执行。下面简单分析利用链的原理(作者水平有限,难免存在不足,请指出):
ComparisonComparer类中定义了委托变量_comparison(Comparison<T>是一个接收两个相同类型参数的委托类型,委托是C#的特性,可以将其看作是一个安全的'函数指针')。ComparisonComparer类中方法Compare(T x, T y)中调用_comparison(x, y),我们可以通过控制_comparison的值,通过多路广播委托实现调用IComparer::Compare时,调用Process::Start,下面是ComparisonComparer类的源码。
回到SortedSet类,该类会对插入的元素(Add方法)自动调用比较器IComparer::Compare方法对比排序,比较器由用户创建时SortedSet类确定,那么我们就可以使用上述ComparisonComparer类作为比较器,使得进行对比时调用Process::Start,即SortedSet对象调用Add ->IComparer::Compare->Process::Start。
观察SortedSet类源码,注意到反序列化时的OnDeserialization方法,调用了Add方法。如下图所示:
payload生成示例代码如下,运行后会产生一个序列化文件,使用该文件进行反序列化即可弹出计算器:
借用原文中的图片,整个反序列化过程的调用链如下:
除了上述Gadget外,17年Black Hat议题《JSON Attacks》上同样提出了可实现远程代码执行的类PSobject,但在经过CVE-2017-8565的补丁修复后,已经无法利用。
0x04 缺陷代码示例
为了方便理解,编写了一个常见的使用BinaryFormatter进行反序列化例子。程序首先从用户提交的参数中接收一段字符串,对该进行Base64解码恢复成流,最后将该字节流反序列化为对象。
使用以下代码,生成payload。
运行后产生以下payload。
将payload提交至刚刚编写的反序列化位置可以看到计算器被弹出。
除了BinaryFormatter,在ObjectStateFormatter、NetDataContractSerializer、LosFormatter中均可使用SortedSet 与 ComparisonComparer类实现反序列化过程代码执行。
0x05 实例 NancyFX (CVE-2017-9785)
Nancy是.NET 平台的微框架。在受到Ruby社区的Sinatra框架启发下,NancyFx框架提供一个.NET平台下的低门槛、易上手的可用于Web开发工具包。
1.4.3版本下使用该框架进行开发时,开启了CsrfToken校验会导致任意代码执行。
其中可看到csrf.cs文件中46、47行代码,从cookie中接收了值,并进行反序列化。
其中Deserialize的具体实现如下,可以看到与我们上述示例代码非常类似,对字符串进行Base64解码恢复成流,最后将该字节流反序列化为对象。
使用上述提供的payload生成代码即可产生payload,将payload放置到cookie相关字段中即可利用。
0x06 防护建议
不应该从用户处接受序列化数据,并进行反序列化。
0x07 参考资料
.NET 源码——http://referencesource.microsoft.com
12年Blackhat议题《Are you my Type?》——https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf
Exploiting .NET Managed DCOM——https://googleprojectzero.blogspot.com.es/2017/04/exploiting-net-managed-dcom.html
以上是关于Younge学习.NET反序列化漏洞的主要内容,如果未能解决你的问题,请参考以下文章