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。该反序列化过程可以注意的特点如下:

  1. BinaryFormatter仅能反序列化声明了Serializable的类。

  2. 反序列化对象时,类的常规构造函数不会被调用,任何依赖于常规构造函数的代码不会执行。

  3. 反序列化过程会调用OnDeserializedOnDeserializing方法。

  4. 反序列化的类实现了ISerializable接口,反序列化过程会调用用户自定义的反序列化过程方法,方法名定义类似构造函数,方法为类名加两个参数(SerializationInfoStreamingContext),如classname(SerializationInfo info,StreamingContext context)

  5. 反序列化的类实现了IDeserializationCallback接口,反序列化过程会调用IDeserializationCallback.OnDeserialization(Objectsender)方法。

  6. 反序列化的类实现了IObjectReference接口,反序列化过程会调用GetRealObject(StreamingContext context)方法。

  7. 反序列化的类如果自定义了析构方法,也存在风险,虽然反序列化过程并不会直接调用析构方法,但在对象被垃圾回收器回收的时候,析构函数被GC自动调用。自定义析构方法名为类名前加~,如~classname()

总结就是下图中定义的类,在反序列化该类时会调用图中定义的除析构方法外的所有方法。

0x03 Gadget

.NET Framework的部分类可以协助攻击者完成一些危险操作。在2012James Forshaw演讲的议题《Are you my Type?》就已经提到过一些可被利用的类:

TempFileCollection

该类自定义了析构方法,当该类对象被回收时,会调用自定义析构方法,该析构方法中会删除files字段上的文件,导致任意文件删除漏洞。

Younge学习.NET反序列化漏洞

System.IO.FileSystemInfo

FileSystemInfo类是提供文件系统信息(如FileInfoDirectoryInfo)类的基类,它实现了ISerializable接口,反序列化期间会调用自定义的反序列化方法,使得可自动创建SMB请求。

Younge学习.NET反序列化漏洞

SortedSet & ComparisonComparer

而在174月,他又提出了可以通过SortedSet类与ComparisonComparer类实现反序列化时代码执行。下面简单分析利用链的原理(作者水平有限,难免存在不足,请指出):

ComparisonComparer类中定义了委托变量_comparisonComparison<T>是一个接收两个相同类型参数的委托类型,委托C#的特性,可以将其看作是一个安全的'函数指针')。ComparisonComparer类中方法Compare(T x, T y)中调用_comparison(x, y),我们可以通过控制_comparison的值,通过多路广播委托实现调用IComparer::Compare时,调用Process::Start,下面是ComparisonComparer类的源码

Younge学习.NET反序列化漏洞

回到SortedSet类,该类会对插入的元素(Add方法)自动调用比较器IComparer::Compare方法对比排序,比较器由用户创建时SortedSet类确定,那么我们就可以使用上述ComparisonComparer类作为比较器,使得进行对比时调用Process::Start,即SortedSet对象调用Add ->IComparer::Compare->Process::Start

观察SortedSet类源码,注意到反序列化时的OnDeserialization方法,调用了Add方法。如下图所示:

Younge学习.NET反序列化漏洞

payload生成示例代码如下,运行后会产生一个序列化文件,使用该文件进行反序列化即可弹出计算器:

Younge学习.NET反序列化漏洞

借用原文中的图片,整个反序列化过程的调用链如下:

Younge学习.NET反序列化漏洞

除了上述Gadget外,17Black Hat议题《JSON Attacks》上同样提出了可实现远程代码执行的类PSobject,但在经过CVE-2017-8565的补丁修复后,已经无法利用。

0x04 缺陷代码示例

为了方便理解,编写了一个常见的使用BinaryFormatter进行反序列化例子。程序首先从用户提交的参数中接收一段字符串,对该进行Base64解码恢复成流,最后将该字节流反序列化为对象。

Younge学习.NET反序列化漏洞

使用以下代码,生成payload

Younge学习.NET反序列化漏洞

运行后产生以下payload

Younge学习.NET反序列化漏洞

payload提交至刚刚编写的反序列化位置可以看到计算器被弹出。

Younge学习.NET反序列化漏洞

除了BinaryFormatter,在ObjectStateFormatterNetDataContractSerializerLosFormatter中均可使用SortedSet ComparisonComparer类实现反序列化过程代码执行。

0x05 实例 NancyFX (CVE-2017-9785)

Nancy.NET 平台的微框架。在受到Ruby社区的Sinatra框架启发下,NancyFx框架提供一个.NET平台下的低门槛、易上手的可用于Web开发工具包。

1.4.3版本下使用该框架进行开发时,开启了CsrfToken校验会导致任意代码执行。

其中可看到csrf.cs文件中4647行代码,从cookie中接收了值,并进行反序列化。

Younge学习.NET反序列化漏洞

其中Deserialize的具体实现如下,可以看到与我们上述示例代码非常类似,对字符串进行Base64解码恢复成流,最后将该字节流反序列化为对象。

Younge学习.NET反序列化漏洞

使用上述提供的payload生成代码即可产生payload,将payload放置到cookie相关字段中即可利用。

0x06 防护建议

  1. 不应该从用户处接受序列化数据,并进行反序列化。

0x07 参考资料

  1. .NET 源码——http://referencesource.microsoft.com

  2. 12Blackhat议题《Are you my Type?》——https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf

  3. Exploiting .NET Managed DCOM——https://googleprojectzero.blogspot.com.es/2017/04/exploiting-net-managed-dcom.html


以上是关于Younge学习.NET反序列化漏洞的主要内容,如果未能解决你的问题,请参考以下文章

.net 的xxe漏洞和反序列化漏洞

.NET编码库存在严重的反序列化漏洞

初探Java反序列化漏洞学习笔记

PHP反序列漏洞学习

漏洞挖掘:一次反序列化漏洞学习

利用.NET反序列化漏洞获取NTLM Hashes