SQL注入拦截工具-动态order by

💖简介

业务场景经常会存在动态order by 入参情况,在处理动态 order by 参数时,需要防止SQL注入攻击。SQL注入是一种常见的安全漏洞,攻击者可以通过这种手段操纵查询来执行恶意代码。

📖措施

  1. 使用预编译语句(Prepared Statements):
    预编译语句是防止SQL注入的有效方法之一。它们允许将SQL语句和参数分开发送到数据库服务器,这样数据库引擎就可以预先编译SQL语句,并确保参数作为数据而不是可执行代码被处理。
  2. 参数化查询:
    使用参数化查询同样可以帮助防止SQL注入。在这种方式下,即使用户输入包含恶意的SQL代码,这些输入也会被视为纯文本而不是可执行的命令。
  3. 白名单验证:
    限制 ORDER BY 子句中的列名只能是从一个已知的安全列表中选择。这意味着你需要有一个明确的列名列表,只有当用户的输入匹配这个列表中的某个值时,才允许使用它来排序。
  4. 正则表达式检查:
    可以使用正则表达式来验证传入的列名是否符合预期格式。例如,只允许字母、数字以及特定的字符如下划线等。
  5. 框架或库提供的安全特性:
    如果你正在使用某种编程语言的框架或ORM(对象关系映射),请利用其内置的安全特性来处理SQL查询。许多现代框架都提供了防止SQL注入的功能。
  6. 避免直接拼接SQL字符串:
    不要直接将用户输入的数据拼接到SQL查询字符串中。这通常是导致SQL注入的主要原因之一。

🌟工具

通过正则表达式判断order by 入参是否符合预期

import org.apache.commons.lang3.StringUtils;

import java.util.regex.Pattern;

/**
 * @program: ZK
 * @description: order by 检查工具
 * @author: zk
 * @create: 2024-09-30 17:42
 **/
public class OrderByCheckUtil {

    /**
     * 适用于 a-zA-Z0-9_.等限定字符 拼接asc/desc 及多个字段
     * t.id desc, t.name
     */
    private static final Pattern FILTER_PATTERN = Pattern.compile("^([a-zA-Z0-9_/\\.]+)(\\s+)?(asc|desc)?$");

    private static final String COMMA= ",";
    
    public static boolean check(String orderBy) {
        if(StringUtils.isBlank(orderBy)){
            return true;
        }
        String[] split = orderBy.split(COMMA);
        for (String s : split) {
            if(!FILTER_PATTERN.matcher(s.trim()).matches()){
                return false;
            }
        }
        return true;
    }
}


⭐测试

  • test
        // 正常场景
        System.out.println(OrderByCheckUtil.check("id"));
        System.out.println(OrderByCheckUtil.check("id asc"));
        System.out.println(OrderByCheckUtil.check("id desc"));
        System.out.println(OrderByCheckUtil.check("id desc, name"));
        System.out.println(OrderByCheckUtil.check("id desc, name asc"));
        System.out.println(OrderByCheckUtil.check("t.id"));
        System.out.println(OrderByCheckUtil.check("t.id asc"));
        System.out.println(OrderByCheckUtil.check("t.id desc"));
        System.out.println(OrderByCheckUtil.check("t.id desc, t.name"));
        System.out.println(OrderByCheckUtil.check("t.id desc, t.name asc"));
        System.out.println(OrderByCheckUtil.check("table_t.id"));
        System.out.println(OrderByCheckUtil.check("table_t.id asc"));
        System.out.println(OrderByCheckUtil.check("table_t.id desc"));
        System.out.println(OrderByCheckUtil.check("table_t.id desc, table_t.name"));
        System.out.println(OrderByCheckUtil.check("table_t.id desc, table_t.name asc"));

        // 非法字符
        System.out.println(OrderByCheckUtil.check("id; DROP TABLE users; --"));
        System.out.println(OrderByCheckUtil.check("id, (SELECT * FROM information_schema.tables) --"));
        System.out.println(OrderByCheckUtil.check("(id), (SELECT * FROM users WHERE 'x'='x')"));
        System.out.println(OrderByCheckUtil.check("id; EXEC master..xp_cmdshell 'dir c:\\' --"));
        System.out.println(OrderByCheckUtil.check("id ASC, CASE WHEN (1=1) THEN 1 ELSE 0 END"));
        System.out.println(OrderByCheckUtil.check("id, CONCAT(username, ':', password)"));
  • result
true
true
true
true
true
true
true
true
true
true
true
true
true
true
true
false
false
false
false
false
false

结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丿似锦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值