SQL注入攻击防御详细配置:从零开始保护你的数据库
为什么你的网站需要防御SQL注入
SQL注入是攻击者通过输入恶意SQL语句,操纵后台数据库执行非授权操作的攻击方式。
轻则泄露用户数据,重则导致服务器被控制。
作为运维人员,即使你只管理一个小网站,也必须做好SQL注入攻击防御详细配置。
本文将从Web层、数据库层和服务器层三个维度,手把手教你完成防护。
第一步:在Web应用层启用参数化查询(代码层面)
如果你的网站使用PHP + MySQL,最根本的防御是禁止拼接SQL字符串,改用参数化查询。
以PDO为例,正确写法如下:
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->execute(['email' => $_POST['email']]);
$user = $stmt->fetch();
重要: 永远不要直接用 $_GET 或 $_POST 变量拼接到SQL中。
如果使用ORM框架(如Laravel Eloquent、Django ORM),它们默认启用参数化查询,你只需要确保不使用原生SQL拼接即可。
第二步:配置Web应用防火墙(WAF)拦截恶意请求
即使代码没问题,也要加上一层外部防护。
最轻量级的方式是在Nginx服务器上集成modsecurity或使用宝塔面板的Nginx防火墙。
使用宝塔面板开启Nginx防火墙(适合新手)
- 登录宝塔后台,点击左侧「软件商店」。
- 搜索「Nginx防火墙」,点击安装(免费版支持基础规则)。
- 安装后进入「设置」→「全局配置」,勾选SQL注入防御和XSS防御。
- 点击「保存」,防火墙会自动拦截常见攻击payload。
配置完成后,可以通过访问 http://你的域名/? 测试,若返回403 Blocked说明生效。
id=1' AND 1=1 --
手动在Nginx配置中添加规则(无面板)
在网站虚拟主机配置文件中添加以下规则,拦截典型的注入字符:
if ($query_string ~* ".*[\'\"].*OR.*|.*UNION.*|.*SELECT.*|.*DROP.*") {
return 403;
}
注意: 这种简单正则容易误拦正常请求,建议仅作为临时补充,生产环境应使用成熟的WAF模块。
第三步:加固数据库权限和配置
即使应用层和WAF都挡住了大部分攻击,也要假设攻击者突破了防线,限制数据库的损失。
3.1 创建专用的数据库用户
不要使用root或高权限用户连接Web应用。
在MySQL中执行:
CREATE USER 'webuser'@'localhost' IDENTIFIED BY '强密码';
GRANT SELECT, INSERT, UPDATE, DELETE ON yourdb.* TO 'webuser'@'localhost';
FLUSH PRIVILEGES;
原理: 只给应用库的增删改查权限,即使被注入,也无法执行 DROP DATABASE 或读取其他数据库。
3.2 禁用危险函数和存储过程
修改MySQL配置文件 /etc/mysql/my.cnf 或 /etc/my.cnf,在 [mysqld] 段加入:
local-infile=0
skip-show-database
local-infile=0 禁用 LOAD DATA LOCAL INFILE 防止攻击者读取服务器文件;skip-show-database 限制普通用户显示所有数据库。
第四步:高频问题与避坑指南
Q1:我已经用了参数化查询,还需要WAF吗?
需要。 参数化查询只防御SQL注入,但WAF还能防御XSS、文件包含、恶意爬虫等。
坚持多层防御原则,不要把所有希望寄托在单一环节。
Q2:防火墙拦截了我的正常请求怎么办?
先查看防火墙日志(宝塔路径:防火墙设置→攻击日志),确认是否命中规则。
如果是误拦,可以将该URL加入白名单。
对于正则规则,尽量缩小匹配范围,避免拦截包含“select”的普通词汇。
Q3:我的网站是WordPress或Discuz,如何防御?
除了上述方法,务必升级到官方最新版,并关闭不必要的REST API端点。
安装安全插件如Wordfence,启用SQL注入过滤。
插件本身也是WAF的一种形式。
第五步:验证防御效果
5.1 使用常见注入Payload测试
在网站URL后手动添加:
' OR '1'='1(单引号闭合)1; DROP TABLE users --(分号注入)-1 UNION SELECT 1,2,3(联合查询)
如果上述请求被拦截或返回空/错误页,说明防御有效。
5.2 使用自动化扫描工具
推荐安装 sqlmap(仅限授权测试),在本地执行:
sqlmap -u "http://你的网站/index.php?id=1" --batch
若输出“all tested parameters do not appear to be injectable”,则表示当前页面无注入风险。
完成以上配置后,你的网站已经从代码、网络、数据库三个层面建立了防护。SQL注入攻击防御详细配置不是一次性工作,建议每月检查一次防火墙日志和数据库用户权限,及时修补新漏洞。
如果遇到异常报错,先排查是否被WAF误拦,再看是否是代码本身的语法问题。