🔒 如何有效防止 SQL 注入攻击?
SQL 注入(SQL Injection)是黑客通过构造恶意输入,篡改 SQL 查询语句的攻击方式。以下是 7 大防御策略,涵盖开发、测试和运维全流程。
✅ 1. 使用参数化查询(Prepared Statements)
最有效的方法! 让数据库区分 代码 和 数据,避免恶意输入被当作 SQL 执行。
📌 示例(Java + JDBC)
❌ 危险写法(拼接 SQL)
String query = "SELECT * FROM users WHERE username = '" + userInput + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query); // 可被注入!
✅ 安全写法(参数化查询)
String query = "SELECT * FROM users WHERE username = ?";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(1, userInput); // 自动转义特殊字符
ResultSet rs = pstmt.executeQuery();
📌 其他语言示例
-
Python(SQLite)
cursor.execute("SELECT * FROM users WHERE username = ?", (user_input,))
-
PHP(PDO)
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username"); $stmt->execute(['username' => $userInput]);
✅ 2. 使用 ORM(对象关系映射)
ORM 框架(如 Hibernate、Django ORM、Sequelize)自动处理 SQL 转义,减少手写 SQL 的风险。
📌 示例(Django ORM)
# 完全避免手写 SQL
user = User.objects.get(username=user_input)
✅ 3. 输入验证 & 白名单过滤
-
校验数据类型(如数字、邮箱、日期)。
-
限制输入长度(防止超长恶意 payload)。
-
白名单 (只允许特定字符,如
a-zA-Z0-9_-
)。
📌 示例(PHP 过滤)
if (!preg_match('/^[a-z0-9_]+$/i', $username)) {
die("Invalid username!");
}
✅ 4. 最小权限原则
-
数据库用户只授予 最小必要权限 (如
SELECT
,而非DROP TABLE
)。 -
避免使用
root
/sa
账号连接数据库。
📌 MySQL 示例
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'password';
GRANT SELECT, INSERT ON app_db.* TO 'app_user'@'localhost';
✅ 5. 转义特殊字符(Escaping)
如果必须拼接 SQL,确保转义特殊字符(如 '
→ \'
)。
📌 示例(PHP + MySQLi)
$username = $mysqli->real_escape_string($userInput);
$query = "SELECT * FROM users WHERE username = '$username'";
⚠️ 注意 :转义不如参数化查询安全,某些场景可能失效(如
LIKE
语句)。
✅ 6. 禁用动态 SQL & 存储过程
-
避免直接拼接 SQL 执行(如
EXEC('SELECT ... ' + @input)
)。 -
存储过程也要用参数化调用。
✅ 7. 安全审计 & WAF(Web 应用防火墙)
-
代码扫描工具:SQLMap、SonarQube、OWASP ZAP。
-
WAF:Cloudflare、ModSecurity 可拦截常见注入攻击。
-
日志监控 :记录异常 SQL 查询(如
UNION SELECT
)。
📌 SQL 注入攻击示例
假设登录 SQL 如下:
SELECT * FROM users WHERE username = '[input]' AND password = '[input]'
黑客输入:
用户名:admin' --
密码:任意
最终 SQL 变为:
SELECT * FROM users WHERE username = 'admin' --' AND password = '任意'
--
是 SQL 注释,直接绕过密码验证!
🚀 总结:7 层防御
防御措施 | 作用 |
---|---|
参数化查询 | ✅ 最佳实践,分离代码与数据 |
ORM | ✅ 减少手写 SQL,自动防注入 |
输入验证 | ✅ 过滤非法字符 |
最小权限 | ✅ 限制数据库账号权限 |
转义字符 | ⚠️ 应急方案,不如参数化安全 |
禁用动态 SQL | ✅ 避免 EXEC() 高危操作 |
WAF & 审计 | ✅ 额外防护,监控攻击 |
💡 记住: 永远不要信任用户输入! 使用参数化查询 + ORM 是黄金标准。