.NET高级代码审计(第二课) Json.Net反序列化漏洞
0X00 前言
Newtonsoft.Json,这是一个开源的Json.Net库,官方地址:https://www.newtonsoft.com/json ,一个读写Json效率非常高的.Net库,在做开发的时候,很多数据交换都是以json格式传输的。而使用Json的时候,开发者很多时候会涉及到几个序列化对象的使用:DataContractJsonSerializer,JavaScriptSerializer 和 Json.NET即Newtonsoft.Json。大多数人都会选择性能以及通用性较好Json.NET,这个虽不是微软的类库,但却是一个开源的世界级的Json操作类库,从下面的性能对比就可以看到它的性能优点。
用它可轻松实现.Net中所有类型(对象,基本数据类型等)同Json之间的转换,在带来便捷的同时也隐藏了很大的安全隐患,在某些场景下开发者使用DeserializeObject方法序列化不安全的数据,就会造成反序列化漏洞从而实现远程RCE攻击,本文笔者从原理和代码审计的视角做了相关介绍和复现。
0X01 Json.Net序列化
在Newtonsoft.Json中使用JSONSerializer可以非常方便的实现.NET对象与Json之间的转化,JSONSerializer把.NET对象的属性名转化为Json数据中的Key,把对象的属性值转化为Json数据中的Value,如下Demo,定义TestClass对象
并有三个成员,Classname在序列化的过程中被忽略(JsonIgnore),此外实现了一个静态方法ClassMethod启动进程。 序列化过程通过创建对象实例分别给成员赋值,
用JsonConvert.SerializeObject得到序列化后的字符串
Json数据中并没有包含方法ClassMethod,因为它是静态方法,不参与实例化的过程,自然在testClass这个对象中不存在。这就是一个最简单的序列化Demo。为了尽量保证序列化过程不抛出异常,笔者引入 SerializeObject方法的第二个参数并实例化创建JsonSerializerSettings,下面列出属性
修改代码添加 TypeNameAssemblyFormatHandling.Full、TypeNameHandling.ALL
将代码改成这样后得到的testString变量值才是笔者想要的,打印的数据中带有完整的程序集名等信息。
0x02 Json.Net反序列化
2.1、反序列化用法
反序列过程就是将Json字符串转换为对象,通过创建一个新对象的方式调用JsonConvert.DeserializeObject方法实现的,传入两个参数,第一个参数需要被序列化的字符串、第二个参数设置序列化配置选项来指定JsonSerializer按照指定的类型名称处理,其中TypeNameHandling可选择的成员分为五种
默认情况下设置为TypeNameHandling.None,表示Json.NET在反序列化期间不读取或写入类型名称。具体代码可参考以下
2.2、攻击向量—ObjectDataProvider
漏洞的触发点也是在于TypeNameHandling这个枚举值,如果开发者设置为非空值、也就是对象(Objects) 、数组(Arrays) 、自动识别 (Auto) 、所有值(ALL) 的时候都会造成反序列化漏洞,为此官方文档里也标注了警告,当您的应用程序从外部源反序列化JSON时应谨慎使用TypeNameHandling。
笔者继续选择ObjectDataProvider类方便调用任意被引用类中的方法,具体有关此类的用法可以看一下《.NET高级代码审计(第一课)XmlSerializer反序列化漏洞》,首先来序列化TestClass
指定TypeNameHandling.All、TypeNameAssemblyFormatHandling.Full后得到序列化后的Json数据
如何构造System.Diagnostics.Process序列化的Json字符串呢?笔者需要做的工作替换掉ObjectInstance的$type、MethodName的值以及MethodParameters的$type值,删除一些不需要的Member、最终得到的反序列话Json数据如下
再经过JsonConvert.DeserializeObject反序列化(注意一点指定TypeNameHandling的值一定不能是None),成功弹出计算器。
2.3、攻击向量—WindowsIdentity
WindowsIdentity类位于System.Security.Principal命名空间下。顾名思义,用于表示基于Windows认证的身份,认证是安全体系的第一道屏障肩负着守护着整个应用或者服务的第一道大门,此类定义了Windows身份一系列属性
对于用于表示认证类型的AuthenticationType属性来说,在工作组模式下返回NTLM。对于域模式,如果操作系统是Vista或者以后的版本,该属性返回Negotiate,表示采用SPNEGO认证协议。而对于之前的Windows版本,则该属性值为Kerberos。Groups属性返回WindowsIdentity对应的Windows帐号所在的用户组(User Group),而IsGuest则用于判断Windows帐号是否存在于Guest用户组中。IsSystem属性则表示Windows帐号是否是一个系统帐号。对于匿名登录,IIS实际上会采用一个预先指定的Windows帐号进行登录。而在这里,IsAnonymous属性就表示该WindowsIdentity对应的Windows帐号是否是匿名帐号。
2.3.1、ISerializable
跟踪定义得知继承于ClaimsIdentity类,并且实现了ISerializable接口
查看定义得知,只有一个方法GetObjectData
在.NET运行时序列化的过程中CLR提供了控制序列化数据的特性,如:OnSerializing、OnSerialized、NonSerialized等。为了对序列化数据进行完全控制,就需要实现Serialization.ISeralizable接口,这个接口只有一个方法,即 GetObjectData,第一个参数SerializationInfo包含了要为对象序列化的值的合集,传递两个参数给它:Type和IFormatterConverter,其中Type参数表示要序列化的对象全名(包括了程序集名、版本、公钥等),这点对于构造恶意的反序列化字符串至关重要
另一方面GetObjectData又调用SerializationInfo 类提供的AddValue多个重载方法来指定序列化的信息,AddValue添加的是一组<key,value> ;GetObjectData负责添加好所有必要的序列化信息。
2.3.2、ClaimsIdentity
ClaimsIdentity(声称标识)位于System.Security.Claims命名空间下,首先看下类的定义
其实就是一个个包含了claims构成的单元体,举个栗子:驾照中的“身份证号码:000000”是一个claim、持证人的“姓名: Ivan1ee”是另一个claim、这一组键值对构成了一个Identity,具有这些claims的Identity就是ClaimsIdentity,通常用在登录Cookie验证,如下代码
一般使用的场景我想已经说明白了,现在来看下类的成员有哪些,能赋值的又有哪些?参考官方文档可以看到 Lable、BootstrapContext、Actor三个属性具备了set
查阅文档可知,这几个属性的原始成员分别为actor、bootstrapContext、lable如下
ClaimsIdentity类初始化方法有两个重载,并且通过前文介绍的SerializationInfo来传入数据,最后用Deserialize反序列化数据。
追溯的过程有点像框架类的代码审计,跟踪到Deserialize方法体内,查找BootstrapContextKey才知道原来它还需要被外层base64解码后带入反序列化
2.3.3、打造Poc
回过头来想一下,如果使用GetObjectData类中的AddValue方法添加“key : System.Security.ClaimsIdentity.bootstrapContext“、”value : base64编码后的payload“,最后实现System.Security.Principal.WindowsIdentity.ISerializable接口就能攻击成功。首先定义WindowsIdentityTest类
笔者用ysoserial生成反序列化Base64 Payload赋值给BootstrapContextKey,实现代码如下
到这步生成变量obj1的值就是一段poc,但还需改造一下,将$type值改为System.Security.Principal.WindowsIdentity完全限定名
最后改进后交给反序列化代码执行,抛出异常之前触发计算器,效果如下图
0x03 代码审计视角
从代码审计的角度其实很容易找到漏洞的污染点,通过前面几个小节的知识能发现需要满足一个关键条件非TypeNameHandling.None的枚举值都可以被反序列化,例如以下Json类
都设置成TypeNameHandling.All,攻击者只需要控制传入参数 _in便可轻松实现反序列化漏洞攻击。Github上很多的json类存在漏洞,例如下图
代码中改用了Auto这个值,只要不是None值在条件许可的情况下都可以触发漏洞,笔者相信肯定还有更多的漏洞污染点,需要大家在代码审计的过程中一起去发掘。
0x04 案例复盘
最后再通过下面案例来复盘整个过程,全程展示在VS里调试里通过反序列化漏洞弹出计算器。
1. 输入http://localhost:5651/Default Post加载value值
2. 通过JsonConvert.DeserializeObject 反序列化 ,并弹出计算器
最后附上动图
0x05 总结
Newtonsoft.Json库在实际开发中使用率还是很高的,攻击场景也较丰富,作为漏洞挖掘者可以多多关注这个点,攻击向量建议选择ObjectDataProvider,只因生成的Poc体积相对较小。最后.NET反序列化系列课程笔者会同步到 https://github.com/Ivan1ee/ 、https://ivan1ee.gitbook.io/ ,后续笔者将陆续推出高质量的.NET反序列化漏洞文章,请大伙持续关注。
.NET高级代码审计(第二课) Json.Net反序列化漏洞的更多相关文章
- .NET高级代码审计(第三课)Fastjson反序列化漏洞
0X00 前言 Java中的Fastjson曾经爆出了多个反序列化漏洞和Bypass版本,而在.Net领域也有一个Fastjson的库,作者官宣这是一个读写Json效率最高的的.Net 组件,使用内置 ...
- .NET高级代码审计(第四课) JavaScriptSerializer反序列化漏洞
0X00 前言 在.NET处理 Ajax应用的时候,通常序列化功能由JavaScriptSerializer类提供,它是.NET2.0之后内部实现的序列化功能的类,位于命名空间System.Web.S ...
- .NET高级代码审计(第一课)XmlSerializer反序列化漏洞
0X00 前言 在.NET 框架中的 XmlSerializer 类是一种很棒的工具,它是将高度结构化的 XML 数据映射为 .NET 对象.XmlSerializer类在程序中通过单个 API 调用 ...
- .NET高级代码审计(第五课) .NET Remoting反序列化漏洞
0x00 前言 最近几天国外安全研究员Soroush Dalili (@irsdl)公布了.NET Remoting应用程序可能存在反序列化安全风险,当服务端使用HTTP信道中的SoapServerF ...
- Asp.Net Web API 2(CRUD操作)第二课
Asp.Net Web API 2(CRUD操作)第二课 Asp.Net Web API 导航 Asp.Net Web API第一课:入门http://www.cnblogs.com/aehyok ...
- 【Web探索之旅】第二部分第二课:服务器语言
内容简介 1.第二部分第二课:服务器语言 2.第二部分第三课预告:框架和内容管理系统 第二部分第二课:服务器语言 介绍了Web的客户端,我们来谈谈Web的服务器端. 既然客户端有客户端的编程语言(HT ...
- 【C++探索之旅】第一部分第二课:C++编程的必要软件
内容简介 1.第一部分第二课:C++编程的必要软件 2.第一部分第三课预告:第一个C++程序 C++编程的必要软件 经过上一课之后,大家是不是摩拳擦掌,准备大干一场了呢. 这一课我们来做一些C++开发 ...
- 【C语言探索之旅】 第二部分第二课:进击的指针,C语言的王牌!
内容简介 1.课程大纲 2.第二部分第二课: 进击的指针,C语言的王牌 3.第二部分第三课预告: 数组 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言 ...
- 【C语言探索之旅】 第二课:工欲善其事,必先利其器
内容简介 1.课程大纲 2.第一部分第二课:工欲善其事,必先利其器 3.第一部分第三课预告:你的第一个程序 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C ...
随机推荐
- 人机大战中AlphaGo及其执子人黄士杰
2016年3月9日注定要写入围棋界的历史.IT界的历史以及科学界的历史.当天,韩国著名围棋棋手李世石VS谷歌AlphaGo的人机大战赛在韩国首尔举行.对弈的一方为拥有1200多个处理器的谷歌人工智能系 ...
- 慕课网access_token的获取(下)
接口调用返回的结果是两个字段:access_token和expires_in,所以需要创建一个实体类封装这两个字段 运行测试类WeixinTest.java控制台打印出错误信息 重置开发者密钥试试看 ...
- 兼容主流浏览器的css渐变色
网页中的渐变色区域,渐变色背景,一般都是通过ps图片方法来实现,但是图片放得多了会影响网页的打开速度,本文介绍的就是用纯 CSS 实现 IE .Firefox.Chrome 和 和Safari都支持的 ...
- iis 应用程序连接池 在计算机“.”上没有找到WAS服务
重新打开控制面板----打开或关闭windows功能,全部勾选internet information services 可承载的web核心. internet信息服务.microsoft.net f ...
- IBM MQ 与spring的整合
文件名:applicationContext-biz-mq.xml 新浪博客把里面的代码全部转换成HTML了,所以无法粘贴 可以查看CSDN里面的:http://blog.csdn.net/xiazo ...
- mybatis结合redis实战二级缓存
之前的文章中我们意见分析了一级缓存.二级缓存的相关源码和基本原理,今天我们来分享下了mybatis二级缓存和redis的结合,当然mybatis二级缓存也可以和ehcache.memcache.OSC ...
- java的PDF纵横向打印
PDF默认是纵向打印的,通过rotate()来让其改变为横向打印,一般在打印A4 12*21纸以及发票的时候会用横向打印.横向打印时页面会出现行转列以及列转行的情况,因此在设置页面大小的时候一定要宽度 ...
- vsftp上传文件出现553 Could not create file
没有权限创建文件或是目录,原因是selinux引起的登陆问题. 通过如下命令查看状态: > sestatus -b|grep ftp 设置allow_ftpd_full_access为on. 在 ...
- Mysql的内存优化
老师 vi mysqld_safe# executing mysqld_safe 后面增加export LD_PRELOAD=/usr/local/lib/libtcmalloc.so 可以做一 ...
- Package gtk+-3.0 was not found in the pkg-config search path
问题描述: 在fedora21系统上通过rpmbuild构建fcitx的二进制包时出现以上错误,经老程序员指点:“是相应的开发包没有安装” 解决办法: yum installl gtk3-devel ...