SQL注入攻击的核心原理是攻击者通过在输入参数中插入恶意的SQL片段,篡改原有查询逻辑,从而获取、篡改甚至删除数据库数据。过滤输入内容中的非法SQL字符是最基础也最有效的防护手段之一,正则表达式可以精准匹配需要拦截的字符和关键字,快速实现输入校验逻辑。

需要拦截的非法SQL字符与关键字
常见的需要拦截的SQL相关内容可以分为以下几类:
- SQL注释符号:
--、/*、*/,攻击者常用注释符号截断原有SQL逻辑 - SQL关键字:
SELECT、INSERT、UPDATE、DELETE、DROP、UNION、EXEC等,这些关键字是构建恶意SQL的核心元素 - 特殊符号:
'、"、;、(、)、%、@等,这些符号常被用来拼接恶意语句或者绕过校验 - 逻辑运算符:
AND、OR、NOT,攻击者常用这些运算符构造恒真条件绕过登录校验
正则表达式编写思路
编写拦截正则时需要注意几个要点:首先关键字匹配要忽略大小写,因为SQL关键字不区分大小写;其次要匹配关键字前后的边界,避免误拦截正常内容中的部分字符;最后要覆盖常见的变形写法,比如关键字的空格、换行分隔情况。
基础的正则表达式可以设计为匹配上述所有类型的非法内容,示例如下:
(?i)(--|/*|*/|;|'|"|(|)|%|@|union|select|insert|update|delete|drop|exec|and|or|not)
这个正则的含义是:(?i)表示忽略大小写,后面的分组匹配所有需要拦截的注释符号、特殊符号和SQL关键字,只要输入内容中出现任意一个匹配项,就判定为非法输入。
不同场景下的实现示例
PHP场景实现
PHP中可以使用preg_match函数结合正则实现输入过滤,代码如下:
<?php
/**
* 过滤SQL非法字符
* @param string $input 用户输入内容
* @return bool 返回true表示输入合法,false表示包含非法内容
*/
function filter_sql_input($input) {
// 定义拦截正则
$pattern = '/(?i)(--|/*|*/|;|'|"|(|)|%|@|union|select|insert|update|delete|drop|exec|and|or|not)/';
// 匹配输入内容,匹配到则返回false
if (preg_match($pattern, $input)) {
return false;
}
return true;
}
// 测试示例
$test_input1 = "admin' OR 1=1 --";
$test_input2 = "张三";
var_dump(filter_sql_input($test_input1)); // 输出false
var_dump(filter_sql_input($test_input2)); // 输出true
?>
JavaScript前端校验实现
前端也可以先做一层正则校验,减少无效请求提交,代码如下:
/**
* 校验输入是否包含非法SQL字符
* @param {string} input 输入内容
* @returns {boolean} true表示合法,false表示非法
*/
function checkSqlInput(input) {
const pattern = /(?i)(--|/*|*/|;|'|"|(|)|%|@|union|select|insert|update|delete|drop|exec|and|or|not)/;
return !pattern.test(input);
}
// 测试
console.log(checkSqlInput("admin' OR 1=1 --")); // false
console.log(checkSqlInput("李四")); // true
正则过滤的局限性与补充措施
正则过滤虽然简单高效,但存在一定局限性:一方面正则规则如果不够完善,可能被攻击者通过编码、大小写变形等方式绕过;另一方面过于严格的正则可能会误拦截正常业务内容,比如用户输入中包含正常的单引号或者英文单词。
因此正则过滤需要配合其他措施共同使用:
- 优先使用参数化查询(预编译语句),这是防范SQL注入的根本方案,从数据库层面避免恶意语句拼接
- 对输入内容做长度限制,避免超长输入包含恶意内容
- 对特殊字符做转义处理,比如使用数据库提供的转义函数处理单引号等特殊字符
- 最小权限原则,数据库账号只赋予必要的操作权限,即使被注入也无法执行高危操作
注意:输入过滤和正则拦截只是安全防护的一环,不能替代参数化查询等核心防护措施,多层防护结合才能最大程度保障应用安全。