Jdbc Attack防护绕过浅析
字数 1932 2025-08-18 11:35:36

JDBC Attack防护绕过技术深入分析

0x00 前言

当传入DriverManager.getConnection(jdbcUrl)中的jdbcUrl用户任意可控时,通过构造恶意的jdbcUrl(恶意连接属性、恶意连接类型等),在JDBC Driver处理jdbcUrl进行连接的过程中进行恶意操作(这类JDBC Driver本身是有漏洞的),可能导致任意文件读取、RCE等严重危害。

0x01 常见防护方法

JDBC连接字符串通常格式为:

jdbc:<type>://<hosts|host:port>/<db><properties>

常见防护措施包括:

  1. 数据源类型(type)限制

    • 使用黑白名单限制可连接的数据源类型
    • 防止调用高风险数据源如mysql、postgresql等
  2. host/port/db字段格式限制

    • port限制只允许数字
    • host字段限制字符集(字母、数字、中文、点、短横线、斜杠、冒号等)
  3. 连接属性(properties)黑名单

    • 维护不同数据源的恶意连接属性黑名单
    • 以MySQL为例,防护的关键属性包括:
      private static final Map SENSITIVE_REPLACE_PARAM_MAP = new HashMap() {
          {
              put("autoDeserialize", "false");
              put("allowLoadLocalInfile", "false");
              put("allowUrlInLocalInfile", "false");
          }
      };
      
      private static final Set SENSITIVE_REMOVE_PARAM_MAP = new HashSet() {
          {
              add("allowLoadLocalInfileInPath");
          }
      };
      

0x02 绕过方式

2.1 使用特定的值替换

MySQL JDBC驱动中,autoDeserialize参数设置为trueyes效果相同:

  • 各版本实现:
    • 8.0.12:com.mysql.cj.conf.BooleanPropertyDefinitionTRUEYES等效
    • 6.0.5:com.mysql.cj.core.conf.BooleanPropertyDefinition#getAllowableValues同样处理
    • 5.1.1:BooleanConnectionProperty#getAllowableValues处理方式相同

绕过方法:使用autoDeserialize=yes代替autoDeserialize=true

2.2 大小写绕过

MySQL驱动解析时会统一转换大小写:

  • 8.0.12:调用toUpperCase()统一大写
  • 其他版本:使用equalsIgnoreCase()进行不区分大小写比较

绕过方法:使用autoDeserialize=TrUe等变体

2.3 URL编码绕过

MySQL驱动解析时会进行URL解码:

  • 8.0.x版本:

    • 对协议、path和参数都进行URL解码
    • 解析流程:getConnectionconnectConnectionUrl.acceptsUrlConnectionUrlParser#parseConnectionString
  • 5.1.x版本:

    • 仅对参数值进行解码

绕过方法

  • 8.0.x:对参数名和值都编码,如%61%75%74%6f%44%65%73%65%72%69%61%6c%69%7a%65=%74%72%75%65
  • 5.1.x:仅对参数值编码

2.4 头尾空白符绕过

当防护代码使用split分割参数时:

String[] keyValue = pair.split("=");
String key = keyValue[0];
String value = keyValue.length > 1 ? keyValue[1] : "";

而MySQL驱动(8.0.12)会调用StringUtils#safeTrim去除空白符:

绕过方法

  • 使用autoDeserialize = true(含空格)
  • 使用制表符\t等空白字符(如CVE-2023-46227案例)

2.5 使用注释符

MySQL 8.0.x支持#作为注释符:

  • 解析时使用正则[^#]*匹配查询参数,忽略#后内容
  • 5.1.x不支持此特性

绕过方法

  • 在8.0.x中:autoDeserialize=true#&autoDeserialize=false

2.6 注入拼接

当jdbcUrl通过拼接用户输入构建时:

StringBuilder url = new StringBuilder("jdbc:mysql://");
url.append(host).append(":").append(port).append("/").append(dbname);
url.append("?user=").append(user).append("&password=").append(password);

绕过方法

  • 在user/password字段注入恶意参数,如user=root&autoDeserialize=true

0x03 防护建议

  1. 组件升级

    • 升级数据源组件至安全版本(如mysql-connector/j 8.0.21+)
    • 考虑使用替代组件(如mariadb-java-client替换mysql-connector-java)
  2. 输入归一化处理

    • 统一大小写
    • URL解码
    • 去除所有空白字符(包括\t等)
    • 处理注释符#
  3. 严格输入校验

    • 限制数据源type为预期值
    • port字段严格限制为数字
    • user/password字段禁止包含=等敏感字符
  4. 参数处理优化

    • 使用java.net.URI解析jdbcUrl,利用其非法字符检测
    • 修复示例:
      String jdbcUrl = url.replaceAll("\\s", "");
      URI uri = new URI(jdbcUrl.replace("jdbc:", ""));
      String query = uri.getQuery();
      
  5. 黑名单维护

    • 长期维护各数据源的恶意属性黑名单
    • 覆盖所有可能的变体(如yes/true、大小写、编码等)

通过综合应用以上防护措施,可有效降低JDBC Attack的风险。

JDBC Attack防护绕过技术深入分析 0x00 前言 当传入 DriverManager.getConnection(jdbcUrl) 中的jdbcUrl用户任意可控时,通过构造恶意的jdbcUrl(恶意连接属性、恶意连接类型等),在JDBC Driver处理jdbcUrl进行连接的过程中进行恶意操作(这类JDBC Driver本身是有漏洞的),可能导致任意文件读取、RCE等严重危害。 0x01 常见防护方法 JDBC连接字符串通常格式为: 常见防护措施包括: 数据源类型(type)限制 : 使用黑白名单限制可连接的数据源类型 防止调用高风险数据源如mysql、postgresql等 host/port/db字段格式限制 : port限制只允许数字 host字段限制字符集(字母、数字、中文、点、短横线、斜杠、冒号等) 连接属性(properties)黑名单 : 维护不同数据源的恶意连接属性黑名单 以MySQL为例,防护的关键属性包括: 0x02 绕过方式 2.1 使用特定的值替换 MySQL JDBC驱动中, autoDeserialize 参数设置为 true 或 yes 效果相同: 各版本实现: 8.0.12: com.mysql.cj.conf.BooleanPropertyDefinition 中 TRUE 和 YES 等效 6.0.5: com.mysql.cj.core.conf.BooleanPropertyDefinition#getAllowableValues 同样处理 5.1.1: BooleanConnectionProperty#getAllowableValues 处理方式相同 绕过方法 :使用 autoDeserialize=yes 代替 autoDeserialize=true 2.2 大小写绕过 MySQL驱动解析时会统一转换大小写: 8.0.12:调用 toUpperCase() 统一大写 其他版本:使用 equalsIgnoreCase() 进行不区分大小写比较 绕过方法 :使用 autoDeserialize=TrUe 等变体 2.3 URL编码绕过 MySQL驱动解析时会进行URL解码: 8.0.x版本: 对协议、path和参数都进行URL解码 解析流程: getConnection → connect → ConnectionUrl.acceptsUrl → ConnectionUrlParser#parseConnectionString 5.1.x版本: 仅对参数值进行解码 绕过方法 : 8.0.x:对参数名和值都编码,如 %61%75%74%6f%44%65%73%65%72%69%61%6c%69%7a%65=%74%72%75%65 5.1.x:仅对参数值编码 2.4 头尾空白符绕过 当防护代码使用 split 分割参数时: 而MySQL驱动(8.0.12)会调用 StringUtils#safeTrim 去除空白符: 绕过方法 : 使用 autoDeserialize = true (含空格) 使用制表符 \t 等空白字符(如CVE-2023-46227案例) 2.5 使用注释符 MySQL 8.0.x支持 # 作为注释符: 解析时使用正则 [^#]* 匹配查询参数,忽略 # 后内容 5.1.x不支持此特性 绕过方法 : 在8.0.x中: autoDeserialize=true#&autoDeserialize=false 2.6 注入拼接 当jdbcUrl通过拼接用户输入构建时: 绕过方法 : 在user/password字段注入恶意参数,如 user=root&autoDeserialize=true 0x03 防护建议 组件升级 : 升级数据源组件至安全版本(如mysql-connector/j 8.0.21+) 考虑使用替代组件(如mariadb-java-client替换mysql-connector-java) 输入归一化处理 : 统一大小写 URL解码 去除所有空白字符(包括 \t 等) 处理注释符 # 严格输入校验 : 限制数据源type为预期值 port字段严格限制为数字 user/password字段禁止包含 = 等敏感字符 参数处理优化 : 使用 java.net.URI 解析jdbcUrl,利用其非法字符检测 修复示例: 黑名单维护 : 长期维护各数据源的恶意属性黑名单 覆盖所有可能的变体(如yes/true、大小写、编码等) 通过综合应用以上防护措施,可有效降低JDBC Attack的风险。