SQL注入一直是最关键的Web安全漏洞之一,常年位居OWASP Top 10榜首。虽然参数化查询是预防的金标准,但基于正则的输入验证作为有价值的辅助防御层——特别是在遗留代码库、中间件以及AI驱动系统中(自然语言提示可被转换为SQL查询,即Prompt-to-SQL或P2SQL注入)。

本指南深入探讨如何使用正则表达式检测SQL注入模式,涵盖常见攻击向量、防御性正则策略、陷阱以及一个完整的工作示例。
为什么用正则检测SQL注入?
正则不能替代参数化查询——它绝不应成为你唯一的防御手段。然而,它在以下场景中很有用:
- 输入验证:在参数化查询未被完全采用的环境中(例如遗留系统)。
- WAF规则:在请求到达应用之前拦截可疑请求。
- 日志分析:识别过去的注入尝试。
- AI/LLM中间件:自然语言输入随后被转换为SQL——正则可标记潜在恶意提示。
常见SQL注入模式及其正则
攻击者通常依赖几种经典技术。以下是可用正则检测的模式(注意:为简化说明;真实WAF使用更复杂的规则)。
1. 经典永真式注入
模式:' OR '1'='1 或 ' OR 1=1 --
正则: (?i)(\bOR\b|\bAND\b)\s+[\d\w]+\s*[=<>!]+\s*[\d\w]+
匹配SQL关键字后跟比较操作,常见于永真式攻击。
2. 联合查询注入
模式:' UNION SELECT ...
正则: (?i)\bUNION\b\s+\bSELECT\b
3. 注释注入
模式:admin' -- 或 admin' #
正则: (--|#|/\*|\*/)
4. 堆叠查询
模式:'; DROP TABLE users; --
正则: (?i);\s*(DROP|DELETE|INSERT|UPDATE|CREATE|ALTER|EXEC|EXECUTE|SHUTDOWN|GRANT|REVOKE)
5. 基于时间的盲注
模式:' OR IF(1=1, SLEEP(5), 0) --
正则: (?i)\b(SLEEP|WAITFOR|DELAY|BENCHMARK)\b\s*\(
防御性正则策略
使用正则过滤SQL注入时,遵循以下准则:
- 白名单优于黑名单: 定义允许的模式(例如用户名仅允许字母数字),而不是试图阻止每个恶意变体。
- 不区分大小写匹配: 使用
(?i)标志或C++中的regex::icase来捕获混合大小写攻击。 - 锚定模式: 使用
^和$确保整个输入匹配安全模式,而不仅仅是子串。 - 避免灾难性回溯: 保持模式简单;避免嵌套量词如
(a+)+b。 - 结合其他防御: 正则只是一层;始终使用参数化查询和最小权限数据库账户。
工作示例:检测登录表单中的SQL注入
想象一个遗留的PHP登录表单仍然使用字符串拼接。你想添加一个基于正则的过滤器来阻止明显的注入尝试。
<?php
function is_sql_injection_safe($input) {
// 白名单:只允许字母数字、下划线、破折号和点
if (preg_match('/^[a-zA-Z0-9_\-\.]+$/', $input)) {
return true;
}
return false;
}
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
if (!is_sql_injection_safe($username) || !is_sql_injection_safe($password)) {
die("检测到无效输入。");
}
// 继续使用参数化查询(仍然推荐!)
$stmt = $db->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->execute([$username, $password]);
?>
解释: 正则^[a-zA-Z0-9_\-\.]+$确保输入只包含安全字符。这阻止了SQL元字符如'、;、--和空格。虽然并非万无一失(例如,它会阻止包含空格的合法姓名),但大大降低了风险。
对比:正则 vs 参数化查询
| 方面 | 正则验证 | 参数化查询 |
|---|---|---|
| 主要作用 | 输入过滤 | 安全查询构造 |
| 绕过风险 | 高(攻击者可构造通过正则的载荷) | 非常低(SQL结构与数据分离) |
| 性能 | 简单模式快 | 稍慢但可忽略 |
| 维护 | 正则模式需随新攻击更新 | 无需更新模式 |
| 最佳用途 | 纵深防御、WAF规则、日志分析 | 所有新开发、关键查询 |
常见陷阱
- 仅黑名单方法: 攻击者不断寻找绕过黑名单的新方法。始终优先使用白名单。
- 大小写敏感: 忘记
(?i)标志允许简单的绕过如SeLeCt。 - 过于复杂的正则: 嵌套量词可能导致灾难性回溯,引发ReDoS(正则表达式拒绝服务)。
- Unicode绕过: 简单的正则可能遗漏Unicode同形字(例如使用西里尔字母'а'代替拉丁字母'a')。
- 虚假的安全感: 正则不能替代正确的查询参数化。
常见问题解答
正则能否完全阻止SQL注入?
不能。正则是纵深防御措施,不是银弹。参数化查询是唯一可靠的预防手段。攻击者可以构造绕过正则过滤器的载荷,尤其是正则设计不佳时。
什么是Prompt-to-SQL(P2SQL)注入?
P2SQL注入是一种新的攻击向量,攻击者使用自然语言提示诱使LLM(如GPT-4)生成恶意SQL。由于输入看似无害,传统的基于正则的WAF可能无法阻止它。防御措施包括数据库权限强化、SQL查询重写和辅助LLM守卫。
如何测试我的SQL注入正则模式?
使用我们的正则测试器工具,用已知的攻击载荷测试模式。同时测试恶意和良性输入。
我应该在AI/LLM中间件中使用正则吗?
是的,但需谨慎。正则可以标记用户提示中的明显SQL关键字,但也可能阻止合法请求。结合其他技术如查询重写和权限控制。
正则过滤的性能影响如何?
简单的正则模式开销可忽略不计。然而,带有嵌套量词的复杂模式可能导致指数级回溯(ReDoS)。始终在负载下测试你的正则。
结论
正则是一个强大的检测和阻止SQL注入尝试的工具,但它必须作为分层防御的一部分使用。始终从参数化查询开始,强制执行最小权限数据库权限,并使用正则进行输入验证、WAF规则和异常检测。在P2SQL等AI驱动攻击的时代,正则仍然相关,但不能替代基础安全实践。
在我们的正则测试器中尝试你自己的模式,看看它们如何应对真实世界的注入载荷。