Jackson反序列化漏洞简介(三): JsonTypeInfo的用途
之前有段时间在搞jackson反序列化漏洞的检测,网上看到各种各样的文章,很多抄来抄去的,真是辣鸡,虽然我不懂,但也知道他们有些人在胡扯。本系列文章系统地介绍java里的json反序列化漏洞成因、防御方式、检测方式、利用方式。因为本人接触这些不久,如有错误,还请大佬留言指正。
本文是第三篇,讲之前漏掉的一种可以进行漏洞利用的写法。
一、JsonTypeInfo
先看一段代码,我们没有开启EnableDefaultTyping ,但是在类的字段里添加了一个修饰。
1 | class Person { |
打出来了
{"age":10,"name":"Alice","object":{"@class":"com.leadroyal.example.Dna","length":100}}
我们明明没有EnableDefaultTyping,但这里还是出现了类的名字。。。。。这是为什么 JsonTypeInfo有5个取值,分别是
1 |
下面我们一一介绍,其中有些是可以被反序列化时进行代码执行的。
二、详细
JsonTypeInfo.Id.NONE
输出
{"age":10,"name":"Alice","object":{"length":100}}
在没有注解的情况下,可以每个字段都可以认为是NONE,也就是最最最普通的处理,是安全的、不会被攻击的,因为字符串里根本没有包含类的信息进去。
JsonTypeInfo.Id.CLASS
输出
{"age":10,"name":"Alice","object":{"@class":"com.leadroyal.example.Dna","length":100}}
是有类的信息的,显然这个和之前的利用方式一样,而且确实可以利用,
Exp为
{"age":10,"name":"Alice","object":{"@class":"com.leadroyal.example.Vuln","cmd":"calc.exe"}}
JsonTypeInfo.Id.MANIMAL_CLASS
输出
{"age":10,"name":"Alice","object":{"@c":"com.leadroyal.example.Dna","length":100}}
区别之一是用 @c
代替 @class
,更短一点,区别之二是使用了更短的类名(这个例子里没有体现出来,因为不知道怎么构造,但官方文档是这么说的),主要是为了寻找方便,验证通过,确实可以利用,Exp为
{"age":10,"name":"Alice","object":{"@c":"com.leadroyal.example.Vuln","cmd":"calc.exe"}}
JsonTypeInfo.Id.NAME
输出
{"age":10,"name":"Alice","object":{"@type":"Dna","length":100}}
但是,反序列化失败了,提醒我Dna不是一个Object,ExcuseMe?你自己序列化过的自己不会反,岂不是在逗我么。。。
这时候把Person里的代码改成Dna object
,才可以被反出来,也就是说,一定一定要是一模一样的类型才会给反(经过尝试,子类都不给反的)
这次的比较奇怪,没有带包名也可以被反出来,这种写法第一反应是肯定会有冲突的,毕竟类SimpleName被撞掉还是可以的,但尝试了很多次,没有撞成功,仍然可以被正确反出来。这个也是符合预期的,因为是按照Java里的定义,去加载这个json;而不是按照json的定义,去创建java结构体。所以这种情况是无法利用的。
JsonTypeInfo.Id.CUSTOM
这个无法直接用,需要手写一个解析器才可以配合使用,所以直接回抛出异常。
三、结论
JsonTypeInfo.Id.CLASS 和 JsonTypeInfo.Id.MANIMAL_CLASS 仍然是不安全的,无论开启EnableDefaultTyping 与否,用它来修饰的字段是Object的话,攻击者就可以控制类型,从而有被RCE的风险。