SQL注入攻击的核心是利用未经过滤的用户输入拼接SQL语句,改变原有查询逻辑。基于正则表达式的输入清洗方案,就是通过预设规则匹配输入中的危险内容,在输入进入SQL执行流程前完成过滤或转义,从根源上阻断注入路径。

核心防御原理
SQL注入常用的危险元素包括特殊字符和SQL关键字两类,正则表达式可以精准匹配这两类内容:
- 特殊字符:单引号
'、双引号"、分号;、注释符--、/* */、括号()等,这类字符常被用来闭合原有SQL语句结构。 - SQL关键字:
SELECT、INSERT、UPDATE、DELETE、UNION、EXEC、OR、AND等,这类关键字常被用来构造新的查询逻辑。
输入清洗的逻辑就是遍历用户输入字符串,用正则表达式匹配上述危险内容,根据业务需求选择直接拒绝请求、替换危险字符为空、或者对危险字符进行转义处理。
正则表达式编写规则
编写清洗用的正则表达式需要覆盖常见注入场景,同时避免过度过滤影响正常业务输入。以下是通用的规则参考:
1. 危险字符匹配正则
匹配常见注入特殊字符的正则表达式如下:
['"\;\-\-\/\*\(\)]
该正则可以匹配单引号、双引号、反斜杠、分号、双减号、斜杠、星号、括号这些常用于注入的特殊字符。
2. SQL关键字匹配正则
匹配常见SQL关键字的正则表达式如下,不区分大小写:
(?i)(SELECT|INSERT|UPDATE|DELETE|UNION|EXEC|OR|AND|DROP|TRUNCATE|DECLARE)
其中(?i)表示后续匹配不区分大小写,覆盖关键字的大小写变体场景。
不同场景的清洗实现示例
以下以Python和Java两种常用后端语言为例,展示输入清洗的具体实现。
Python实现示例
Python的re模块支持正则表达式操作,以下是清洗函数实现:
import re
def clean_sql_input(user_input):
# 先匹配并转义特殊字符,将单引号转义为两个单引号,符合SQL转义规范
special_char_pattern = re.compile(r"['\]")
cleaned = special_char_pattern.sub(lambda x: "''" if x.group() == "'" else "\\", user_input)
# 再匹配SQL关键字,将关键字替换为空,避免注入逻辑生效
keyword_pattern = re.compile(r"(?i)(SELECT|INSERT|UPDATE|DELETE|UNION|EXEC|OR|AND|DROP|TRUNCATE|DECLARE)")
cleaned = keyword_pattern.sub("", cleaned)
return cleaned
# 测试示例
test_input = "admin' OR 1=1 --"
print(clean_sql_input(test_input))
# 输出结果:admin'' 1=1 --
Java实现示例
Java使用java.util.regex包处理正则,实现逻辑如下:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class SqlInputCleaner {
// 特殊字符匹配正则
private static final Pattern SPECIAL_CHAR_PATTERN = Pattern.compile("['\\]");
// SQL关键字匹配正则,不区分大小写
private static final Pattern KEYWORD_PATTERN = Pattern.compile("(?i)(SELECT|INSERT|UPDATE|DELETE|UNION|EXEC|OR|AND|DROP|TRUNCATE|DECLARE)");
public static String cleanSqlInput(String userInput) {
if (userInput == null) {
return null;
}
// 转义单引号和反斜杠
String cleaned = SPECIAL_CHAR_PATTERN.matcher(userInput).replaceAll(match -> {
if ("'".equals(match.group())) {
return "''";
} else {
return "\\";
}
});
// 过滤SQL关键字
cleaned = KEYWORD_PATTERN.matcher(cleaned).replaceAll("");
return cleaned;
}
public static void main(String[] args) {
String testInput = "test; DROP TABLE user --";
System.out.println(cleanSqlInput(testInput));
// 输出结果:test; TABLE user --
}
}
方案注意事项与边界
基于正则表达式的输入清洗方案虽然简单易落地,但使用时需要注意以下问题:
- 避免过度过滤:比如业务需要支持用户输入包含
AND、OR等关键字的内容时,直接过滤会导致正常输入被篡改,此时可以选择仅转义特殊字符,或者根据输入参数类型做差异化处理,比如数字类型参数只允许输入数字,无需匹配关键字。 - 不能作为唯一防御手段:正则表达式规则难以覆盖所有新型注入变种,建议配合参数化查询、ORM框架的防注入机制一起使用,形成多层防御体系。
- 输入来源全覆盖:不仅要清洗前端表单输入,还要清洗URL参数、HTTP请求头、Cookie等所有用户可控的输入来源,避免遗漏攻击入口。
注意:输入清洗是在不可信输入进入业务逻辑前的预处理步骤,不能替代SQL语句的参数化执行,两者结合才能最大限度降低SQL注入风险。