0X00 前言

在.NET 框架中的 XmlSerializer 类是一种很棒的工具,它是将高度结构化的 XML 数据映射为 .NET 对象。XmlSerializer类在程序中通过单个 API 调用来执行 XML 文档和对象之间的转换。转换的映射规则在 .NET 类中通过元数据属性来表示,如果程序开发人员使用Type类的静态方法获取外界数据,并调用Deserialize反序列化xml数据就会触发反序列化漏洞攻击(例如DotNetNuke 任意代码执行漏洞 CVE-2017-9822),本文笔者从原理和代码审计的视角做了相关脑图介绍和复现。

0X01 XmlSerializer序列化

.NET 框架中 System.Xml.Serialization 命名空间下的XmlSerializer类可以将 XML 文档绑定到 .NET 类的实例,有一点需要注意它只能把对象的公共属性和公共字段转换为XML元素或属性,并且由两个方法组成:Serialize() 用于从对象实例生成 XML;Deserialize() 用于将 XML 文档分析成对象图,被序列化的数据可以是数据、字段、数组、以及XmlElement和XmlAttribute对象格式的内嵌XML。具体看下面demo

XmlElement指定属性要序列化为元素,XmlAttribute指定属性要序列化为特性,XmlRoot特性指定类要序列化为根元素;通过特性类型的属性、影响要生成的名称、名称空间和类型。再创建一个TestClass类的实例填充其属性序列化为文件,XmlSerializer.Serialize方法重载可以接受Stream、TextWrite、XmlWrite类,最终生成的XML文件列出了TestClass元素、Classname特性和其它存储为元素的属性:

0x02 XmlSerialize反序列化

反序列过程:将xml文件转换为对象是通过创建一个新对象的方式调用XmlSerializer.Deserialize方法实现的,在序列化最关键的一环当属new XmlSerializer构造方法里所传的参数,这个参数来自System.Type类,通过这个类可以访问关于任意数据类型的信息,指向任何给定类型的Type引用有以下三种方式。

2.1、typeof

实例化XmlSerializer传入的typeof(TestClass) 表示获取TestClass类的Type,typeof是C#中的运算符,所传的参数只能是类型的名称,而不能是实例化的对象,如下Demo

通过typeof获取到Type之后就能得到该类中所有的Methods、Members等信息。下图运行Debug时,弹出消息对话框显示当前成员Name的值。

2.2、object.Type

在.NET里所有的类最终都派生自System.Object,在Object类中定义了许多公有和受保护的成员方法,这些方法可用于自己定义的所有其他类中,GetType方法就是其中的一个,该方法返回从System.Type派生的类的一个实例,因为可以提供对象成员所属类的信息,包括基本类型、方法、属性等,上述案例中实例化TestClass,再获取当前实例的Type,如下Demo

2.3、Type.GetType

第三种方法是Type类的静态方法GetType,这个方法允许外界传入字符串,这是重大利好,只需要传入全限定名就可以调用该类中的方法、属性等

Type.GetType传入的参数也是反序列化产生的漏洞污染点,接下来就是要去寻找可以被用来攻击使用的类。

0X03 打造攻击链

首先放上攻击链打造成功后的完整Demo,这段Demo可以复用在任意地方(这里不涉及.NET Core、MVC),如下图

只要XmlSerializer存在反序列化漏洞就可用下面Demo中的内容,涉及到三个主要的技术点,以下分别来介绍原理。

3.1、ObjectDataProvider

ObjectDataProvider类,它位于System.Windows.Data命名空间下,可以调用任意被引用类中的方法,提供成员ObjectInstance用类似实例化类、成员MethodName

调用指定类型的方法的名称、成员MethodParameters表示传递给方法的参数,参考下图

再给TestClass类定义一个ClassMethod方法,代码实现调用System.Diagnostics.Process.Start启动新的进程弹出计算器。如果用XmlSerializer直接序列化会抛出异常,因为在序列化过程中ObjectInstance这个成员类型未知,不过可以使用ExpandedWrapper扩展类在系统内部预先加载相关实体的查询来避免异常错误,改写Demo

生成data.xml内容如下:

攻击链第一步就算完成,但美中不足的是因笔者在测试环境下新建的TestClass类存在漏洞,但在生产情况下是非常复杂的,需要寻求Web程序中存在脆弱的攻击点,为了使攻击成本降低肯定得调用系统类去达到命令执行,所以需要引入下面的知识。

3.2、ResourceDictionary

ResourceDictionary,也称为资源字典通常出现在WPF或UWP应用程序中用来在多个程序集间共享静态资源。既然是WPF程序,必然设计到前端UI设计语言XAML。 XAML全称Extensible Application Markup Language (可扩展应用程序标记语言) 基于XML的,且XAML是以一个树形结构作为整体,如果对XML了解的话,就能很快的掌握,例如看下面Demo

  • 第一个标签ResourceDictionary,xmlns:Runtime表示读取System.Diagnostics命令空间的名称起个别名为Runtime

  • 第二个标签ObjectDataProvider指定了三个属性,x:key便于条件检索,意义不大但必须得定义;ObjectType 用来获取或设置要创建其实例的对象的类型,并使用了XAML扩展;x:Type相当于C#中typeof运算符功能,这里传递的值是System.Diagnostics.Process;MethodName用来获取或设置要调用的方法的名称,传递的值为System.Diagnostics.Process.Start方法用来启动一个进程。

  • 第三个标签ObjectDataProvider.MethodParameters内嵌了两个方法参数标签,通过System:String分别指定了启动文件和启动时所带参数供Start方法使用。

介绍完攻击链中ResourceDictionary后,攻击的Payload主体已经完成,接下来通过XamlReader这个系统类所提供的XML解析器来实现攻击。

3.3、XamlReader

XamlReader位于System.Windows.Markup空间下,顾名思义就是用来读取XAML文件,它是默认的XAML读取器,通过Load读取Stream流中的XAML数据,并返回作为根对象,而另外一个Parse方法读取指定字符串中的XAML输入,也同样返回作为根对象,自然Parse方法是我们关心和寻求的。

只需使用ObjectDataProvider的ObjectInstance方法实例化XamlReader,再指定MethodName为Parse,并且给MethodParameters传递序列化之后的资源字典数据,这样就可以完成XmlSerializer反序列化攻击链的打造。

0x04 代码审计视角

从代码审计的角度其实很容易找到漏洞的污染点,通过前面几个小节的知识能发现序列化需要满足一个关键条件Type.GetType,程序必须通过Type类的静态方法GetType,例如以下demo

首先创建XmlDocument对象载入xml,变量typeName通过Xpath获取到Item节点的type属性的值,并传给了Type.GetType,紧接着读取Item节点内的所有Xml数据,最终交给Deserialize方法反序列化,这是一个近乎完美的利用点。再来看笔者在github上收集到的XmlSerializer反序列化类:XmlSerializeUtil.cs

此处值参数类型为Type,代码本身没有问题,问题在于程序开发者可能会先定义一个字符串变量来接受传递的type值,通过Type.GetType(string)返回 Type对象再传递进DeserializeXml,在代码审计的过程中也需要关注此处type的来源。

0x05 案例复盘

最后再通过下面案例来复盘整个过程,全程展示在VS里调试里通过反序列化漏洞弹出计算器。

1.输入http://localhost:5651/Default?node=root&value=type加载了远程的(192.168.231.135)1.xml文件

2.    通过xmlHelper.GetValue得到root节点下的所有XML数据

3. 这步最关键,得到root节点的type属性,并提供给GetType方法,XmlSerializer对象实例化成功

4.    XmlSerializer.Deserialize(xmlReader)成功调出计算器

最后附上动图

0x06 总结

由于XmlSerializer是系统默认的反序列类,所以在实际开发中使用率还是比较高的,攻击者发现污染点可控的时候,可以从两个维度去寻找利用的点,第一从Web应用程序中寻求可以执行命令或者写WebShell的类和方法;第二就是本文中所说的利用ObjectDataProvider、ResourceDictionary、XamlReader组成的攻击链去执行命令或者反弹Shell ,最后.NET反序列化系列课程笔者会同步到 https://github.com/Ivan1ee/、https://ivan1ee.gitbook.io/,后续笔者将陆续推出高质量的.NET反序列化漏洞文章,大致课程大纲如下图

.NET高级代码审计(第一课)XmlSerializer反序列化漏洞的更多相关文章

  1. .NET高级代码审计(第五课) .NET Remoting反序列化漏洞

    0x00 前言 最近几天国外安全研究员Soroush Dalili (@irsdl)公布了.NET Remoting应用程序可能存在反序列化安全风险,当服务端使用HTTP信道中的SoapServerF ...

  2. .NET高级代码审计(第三课)Fastjson反序列化漏洞

    0X00 前言 Java中的Fastjson曾经爆出了多个反序列化漏洞和Bypass版本,而在.Net领域也有一个Fastjson的库,作者官宣这是一个读写Json效率最高的的.Net 组件,使用内置 ...

  3. .NET高级代码审计(第四课) JavaScriptSerializer反序列化漏洞

    0X00 前言 在.NET处理 Ajax应用的时候,通常序列化功能由JavaScriptSerializer类提供,它是.NET2.0之后内部实现的序列化功能的类,位于命名空间System.Web.S ...

  4. .NET高级代码审计(第二课) Json.Net反序列化漏洞

    0X00 前言 Newtonsoft.Json,这是一个开源的Json.Net库,官方地址:https://www.newtonsoft.com/json ,一个读写Json效率非常高的.Net库,在 ...

  5. Python的一些高级特性以及反序列化漏洞

    0x01 简述 文章主要记录一下python高级特性以及安全相关的问题 python作为脚本语言,其作为高级语言是由c语言开发的,关于python的编译和链接可以看向这里https://github. ...

  6. [代码审计]四个实例递进php反序列化漏洞理解【转载】

    原作者:大方子 原文链接:https://blog.csdn.net/nzjdsds/article/details/82703639 0x01 索引 最近在总结php序列化相关的知识,看了好多前辈师 ...

  7. 【JavaWeb】CVE-2016-4437 Shiro反序列化漏洞分析及代码审计

    Shiro反序列化漏洞分析及代码审计 漏洞简介 Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理.   Apache Shiro默认使用了CookieRe ...

  8. PHP反序列化漏洞代码审计—学习资料

    1.什么是序列化 A.PHP网站的定义: 所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示.unserialize()函数能够重新把字符串变回php原来的值. ...

  9. php代码审计9审计反序列化漏洞

    序列化与反序列化:序列化:把对象转换为字节序列的过程称为对象的序列化反序列化:把字节序列恢复为对象的过程称为对象的反序列化 漏洞成因:反序列化对象中存在魔术方法,而且魔术方法中的代码可以被控制,漏洞根 ...

随机推荐

  1. The partial charge density (1)

    ============================================================================================= The pa ...

  2. nyoj86-找球号(一) 【set 二分查找 hash】

    http://acm.nyist.net/JudgeOnline/problem.php?pid=86 找球号(一) 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 ...

  3. 【C基础】之联合体

    1.联合体 联合体(union)与结构体(struct)有一些相似之处.但两者有本质上的不同.在结构体中,各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和.而在联合体中,各成员共享一段内 ...

  4. 3sum, 3sum closest

    [抄题]: Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find ...

  5. php中正则案例分析

    案例一如下: $regex='/[\s\S]*/'; $str='lemon'; $matches=array(); if(preg_match($regex,$str,$matches)){ var ...

  6. google中guava类库:AsyncEventBus

    1.guava事件总线(AsyncEventBus)使用 1.1引入依赖 <dependency> <groupId>com.google.guava</groupId& ...

  7. discuz回贴通知插件实现-页面嵌入点(钩子)

    1.如何保证主题被回复时业务代码被执行. 2.获得主题,主题发布者,贴子等信息. 3.discuz发送email邮件.   discuz使用嵌入点(钩子)来处理代码的执行时机. 当用户开启插件开发者模 ...

  8. Extended Backus–Naur Form

    From Wikipedia, the free encyclopedia In computer science, Extended Backus–Naur Form (EBNF) is a fam ...

  9. NABCD模型--软件工程

    1.N (Need 需求) 我们通过网络调查问卷的方式,收集样本数据,并对其进行分析和总结. 1.你是否为在校学生? 7.如果用过,你觉得还应该需要添加什么功能 通过调查发现,大多数学生并不是特别了解 ...

  10. [BAT]操作系统定时任务调用批处理忽略error继续运行的方法

    如下,通过forfiles删除7天以前生成的一些文件,当不存在满足搜索条件的文件时,就会报错:ERROR: No files found with the specified search crite ...