练SQL注入,很多人卡住的第一关不是“怎么注入”,而是“去哪练”。直接拿线上站点试,既不合规也容易出事;只对着文章看原理,看完就忘,下次遇到换个参数照样一脸懵。我的建议一直很明确:搭一个本地靶场,把注入的整个过程亲手走一遍,从报错、判断、猜字段到拿数据,每一步都看到实实在在的结果,这才叫练习。
这篇文章就是围绕“SQL注入练习”这条主线展开的,内容包括靶场环境搭建、注入点探测、显错注入和联合查询的完整流程、万能密码绕过登录的拆解、盲注场景的排查思路,以及最后从防御侧反推攻击原理。适合三类人看:刚接触Web安全、想系统入门SQL注入的新手;准备CTF比赛、需要刷注入题型的选手;以及后端开发人员——只有真正理解注入是怎么发生的,写代码时才会下意识避开这些坑。
1. 搭建本地靶场:练习环境是认真学习的前提
1.1 为什么推荐用靶场而不是自己写测试页
我见过不少新手自己写一个PHP页面来测试注入,代码大概长这样:
php复制$id = $_GET['id'];
$sql = "SELECT * FROM users WHERE id = $id";
$result = mysqli_query($conn, $sql);
这种写法确实存在注入漏洞,但作为练习环境有两个问题:第一,没有难度梯度,注入成功了就结束了,学不到更深的绕过技巧;第二,缺少“正确答案”,你不知道当前这个注入点到底有哪些字段、哪些表,练起来心里没底。
所以我的建议是用现成的开源靶场。这类靶场本身带了完整的数据库结构、多个漏洞场景和难度分级,每一步注入结果都能对照预期,排查问题也方便。目前社区里用得比较多的几个:
| 靶场名称 | 特点 | 适合阶段 |
|---|---|---|
| sqli-labs | 共100+关,覆盖报错注入、盲注、堆叠注入、宽字节等 | 入门到进阶全覆盖 |
| DVWA | 带漏洞等级切换(low/medium/high/impossible) | 适合理解防御对比 |
| pikachu | 中文界面,注入场景贴近开发实际 | 适合新手快速上手 |
| Sqli-labs Plus | 在sqli-labs基础上增加了更多过滤绕过场景 | 进阶选手 |
我个人最推荐sqli-labs,原因是它的关卡设计非常像CTF题目,每一关都是一个明确的挑战,而且覆盖了几乎所有常见的注入类型和过滤场景。练完一遍再去看CTF的SQL注入题,你会觉得很多套路都见过。
1.2 基于Docker的环境搭建步骤
sqli-labs的搭建方式有很多种,但我最推荐用Docker,省去了PHP、MySQL环境配置的麻烦,几分钟就能跑起来。
bash复制# 拉取镜像并启动容器
docker pull acgpiano/sqli-labs
docker run -dt --name sqli-labs -p 8080:80 acgpiano/sqli-labs
# 初始化数据库
# 访问 http://localhost:8080/ 后点击"Setup/reset Database"按钮
启动后浏览器访问http://localhost:8080,页面会显示关卡列表。第一件事是点击Setup/reset Database初始化数据库,这一步会创建靶场所需的数据库和表结构,不初始化的话后面所有关卡都会报错。
这里有一个容易忽略的细节:sqli-labs默认数据库用户是root,密码是root,数据库连接配置在sql-connections/sql-connect.php里。如果你用的镜像连不上数据库,多半是账号密码和镜像内置的MySQL不一致,改一下这个文件里的$dbpass变量就行。
1.3 一句话说清楚靶场的请求结构
sqli-labs的每个关卡都对应一个PHP页面,通过URL参数传递输入。比如第一关的URL是:
http复制http://localhost:8080/Less-1/?id=1
id参数就是注入点。靶场页面上会显示当前要解决的SQL查询语句的一部分(有些关卡显示,有些不显示),方便你有针对性地构造payload。练习时建议浏览器装一个修改请求的插件(比如HackBar或者直接用Burp Suite),因为后面构造复杂payload时需要在URL里反复修改、编码、重放,纯手打地址栏太容易出错。
提示:练SQL注入建议全程开着一个数据库管理工具(如phpMyAdmin或Navicat),连上靶场的MySQL,随时查看表结构和数据内容。这样你能清楚地看到自己注入出来的每一个结果到底对应数据库里的哪条记录——这个“看见因果”的过程,比刷一百道题都有用。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 从一条看似正常的SQL说起:注入发生的本质
2.1 SQL注入的前提:输入被拼进了查询语句
很多人把SQL注入想得很玄,其实它发生的条件就一个:用户输入的数据直接拼接到SQL查询语句中,且拼接后的语句被数据库当作命令执行。
看这个最常见的例子,后端代码是这样的:
php复制$id = $_GET['id'];
$sql = "SELECT * FROM users WHERE id = $id";
当你正常访问?id=1时,SQL变成:
sql复制SELECT * FROM users WHERE id = 1
一切正常。但当你传?id=1 OR 1=1时,SQL变成:
sql复制SELECT * FROM users WHERE id = 1 OR 1=1
OR 1=1恒为真,所以这条语句会把users表里的所有记录都查出来。这就是注入的基本原型——你在输入框里输入的不
