做渗透测试绕不开 sqlmap,做 sqlmap 实战绕不开靶场。很多人学数据库注入时,上来就想着拿真实站点练手,这种心态很危险——技术没练熟,先把自己送进去了。我自己带新人时,一直建议先在本地靶场把流程彻底跑通,再谈下一步。这篇就手把手带你把 sqlmap 数据库注入测试完整过一遍:从靶场环境搭建、常用参数理解到一次完整的拖库实战,再到常见报错排查,全部按实操顺序来。不管你是刚入门的渗透测试学习者,还是想系统整理 sqlmap 使用的工程师,这份教程都能直接照着敲,建议先收藏再慢慢练。
1. 准备动手前,先把靶场搭起来
1.1 选哪个靶场:DVWA、SQLi-Labs 还是 Pikachu
做 sqlmap 练习,第一步不是学命令,而是准备一个安全的靶场。本地靶场的好处是:随便跑、随便炸、坏了重来。常见的选择有三个,各有侧重。
DVWA 适合入门,自带 SQL Injection 模块,难度从 low 到 impossible 分级,还能练登录后的注入场景。SQLi-Labs 是专门为 SQL 注入设计的靶场,关卡很多,从 GET 到 POST、盲注、报错注入、堆叠注入都有,练 sqlmap 最合适。Pikachu 更偏综合,里面也有一整套 SQL 注入练习,界面友好,适合做整体渗透流程练习。
我给新人的建议是首推 SQLi-Labs,因为它每一关都精心设计了不同的注入点,用 sqlmap 跑起来特别能看出命令和参数差异;DVWA 作为辅助,用来练需要登录的注入场景。两者配合,基本覆盖日常百分之八十的注入测试需求。如果你还想做点综合演练,再加一个 Pikachu,三个靶场交替练,sqlmap 的核心用法就稳了。
1.2 用 Docker 快速搭建 SQLi-Labs 和 DVWA
手动下载源码配 Apache、MySQL 比较麻烦,最省事的是用 Docker。只要机器上装了 Docker,几条命令就能把靶场跑起来。下面以 Kali 或任意 Linux 系统为例:
bash复制# 拉取 SQLi-Labs 镜像
docker pull acgpiano/sqli-labs
# 启动容器,把 80 端口映射到本机 8080
docker run -d --name sqli-labs -p 8080:80 acgpiano/sqli-labs
启动后浏览器访问 http://127.0.0.1:8080,就能看到 SQLi-Labs 的首页。先点 “Setup/reset Database for labs” 初始化数据库,然后从 Less-1 开始。这里我特意用 8080 端口而不是 80,是为了避开常见 web 服务占用,也方便映射多个靶场。
DVWA 的搭建稍微复杂一点,因为要同时启动 MySQL 和应用进程。推荐用官方编排文件:
bash复制git clone https://github.com/digininja/DVWA.git
cd DVWA
docker-compose up -d
启动后访问 http://127.0.0.1 或映射端口,默认账号 admin / password。登录后先到 “DVWA Security” 把等级调到 low,再到 SQL Injection 模块做测试。我特别提醒一下:DVWA 也有传统 XAMPP 部署方式,但 Docker 方式不会污染宿主机,重装也干净,适合反复折腾。
1.3 本地环境自检清单
靶场搭建完,先别急着跑 sqlmap。用浏览器手动测一下,确认三件事:页面能不能正常打开,数据库初始化有没有报错;登录类靶场能不能用默认密码进入;以及一个带参数的 URL 是否正常响应。比如 SQLi-Labs 的 http://127.0.0.1:8080/Less-1/?id=1,手动把 id 改成 1',看页面是否出现数据库报错。
第三步很重要,因为 sqlmap 只是自动化工具,它能不能出结果,取决于目标页面有没有可探测的入口。如果手动改参数后页面完全没变化,sqlmap 大概率也会空手而归。这一步也顺便帮你理解“注入点”这个概念:不是所有参数都能注入,要有一点可探测的异常。等这三项都通过了,再开终端敲命令。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. sqlmap 基础原理与关键参数
2.1 sqlmap 到底在干什么
一句话理解 sqlmap:它是一个自动化检测和利用 SQL 注入漏洞的工具。它的核心工作分三步:先对目标 URL 中的参数发送测试载荷,观察响应差异;一旦确认存在注入,继续探测数据库类型、版本,判断注入类型;然后根据注入类型自动选择合适的利用方式,把数据从数据库里一条条“问”出来。
在靶场练习中,你会看到 sqlmap 输出大量像 [INFO] testing connection to the target URL 这样的日志,不用慌,那是它在逐步测试。真正要重点看的输出有三个:Parameter: id (GET) 表示它发现哪个参数可疑;Type: boolean-based blind 表示注入类型;payload: ... 表示实际注入语句。理解这些输出,你才能真正明白 sqlmap 每个参数是干嘛的,而不只是机械复制命令。
2.2 高频参数速查表
sqlmap 参数很多,但日常练手和实战常用的就二十几个。我整理了一个速查表,建议直接存下来:
| 场景 | 参数 | 示例 |
|---|---|---|
| 指定目标 URL | -u |
sqlmap -u "http://.../?id=1" |
| 自动选择默认答案 | --batch |
sqlmap -u "..." --batch |
| 指定数据库类型 | --dbms |
--dbms=mysql |
| 枚举数据库列表 | --dbs |
sqlmap -u "..." --dbs |
| 选择要操作的数据库 | -D |
-D dvwa |
| 枚举表名 | --tables |
sqlmap -u "..." -D dvwa --tables |
| 选择表 | -T |
-T users |
| 枚举字段名 | --columns |
sqlmap -u "..." -D dvwa -T users --columns |
| 指定字段并导出数据 | -C |
-C user,password |
| 导出数据 | --dump |
sqlmap -u "..." -D dvwa -T users --dump |
| 设置注入难度等级 | --level |
--level=3 |
| 设置风险等级 | --risk |
--risk=2 |
| 指定注入类型 | --technique |
--technique=BEUST |
| 使用 POST 数据 | --data |
--data="user=admin&pass=123" |
| 使用 Cookie | --cookie |
--cookie="PHPSESSID=xxx" |
| 多线程 | --threads |
--threads=5 |
| 使用代理 | --proxy |
--proxy="http://127.0.0.1:8080" |
| 随机 User-Agent | --random-agent |
--random-agent |
| 延迟请求 | --delay |
--delay=1 |
这里要提醒一句:--proxy 在靶场练习时通常是配合 Burp Suite 抓包分析用的,不是用来“隐藏”什么的,千万别理解偏了。尤其在真实授权测试里,代理配合抓包工具能让你看见 sqlmap 发送的每一个请求,排查问题会方便得多。
2.3 从“测试语句”到“完整命令”的思路
很多新手拿到 sqlmap 喜欢背命令,结果一换场景就懵。我教你一个通用思路:先确认目标链路是通的,执行 sqlmap -u "http://.../?id=1",看日志有没有连接错误;然后加上 --batch 让工具自动选择默认项,先跑通一轮,不要一上来就交互式回答问题;确认能注入后,再逐步加参数,先 --dbs,再 -D,再 --tables,再 --dump;如果默认测试没识别出来,再逐步提升 --level 和 --risk。
这样做的好处是:每一步都能看到明确输出,不会因为一次命令写得太复杂,出了问题不知道卡在哪。我个人非常建议你在练习时故意不开 --batch,因为交互式提问时会问“do you want to skip test payloads specific for other DBMSes?”之类的问题,多回答几次,你就懂它内部在做哪些选择了。这种“被迫思考”的过程,比看着输出日志猜效率高得多。
3. 手把手实战:SQLi-Labs 注入流程
3.1 第一步:确认注入点
现在开始实战。假设你已经启动 SQLi-Labs,并且浏览器能打开 http://127.0.0.1:8080/Less-1/?id=1。先手动访问一下,页面会显示登录名和密码信息,周围有一个类似 “Your Login name: ... Your Password: ...” 的结构。这就是典型的从数据库查询结果渲染页面的场景。
接下来把 URL 改成 http://127.0.0.1:8080/Less-1/?id=1',浏览器多半会报一个 SQL 语法错误。这个报错不是坏事,它说明程序没有对输入做过滤,而且输入是直接拼接到 SQL 语句里的。到这一步,你已经有理由把这条 URL 交给 sqlmap 了。注意,目标 URL 最好用双引号包裹,因为参数里可能有特殊字符,避免 shell 把它拆开。
bash复制sqlmap -u "http://127.0.0.1:8080/Less-1/?id=1" --batch
如果你不熟悉 --batch 会怎么处理,可以看一眼日志:它首先会测试目标连接,然后检测数据库类型,再尝试一系列 payload。大概几十秒后,如果屏幕出现 Parameter: id (GET) 和某个注入类型,就说明这个参数存在 SQL 注入漏洞,可以继续下一步。
3.2 第二步:自动探测与注入类型识别
跑完第一步之后,sqlmap 会展示它探测到的注入点。你可能会看到多种类型,比如 boolean-based blind、error-based、time-based blind、UNION query 等。这些就是注入类型,简单解释一下:
- 布尔盲注:通过页面返回真、假来判断条件是否成立,比如
id=1 and 1=1和id=1 and 1=2页面结果不同。 - 报错注入:利用数据库报错信息回显数据。
- 时间盲注:通过延迟响应判断条件,比如执行
sleep(5)让页面延迟 5 秒返回。 - 联合注入:通过 UNION 拼接查询,直接回显数据。
在实战中,你不需要每次都手工区分,因为 sqlmap 会自动选一种能用的方式。但你至少要能看懂结果,方便判断是不是误报。看到 Type: UNION query 时,进展会比较快;看到 Type: time-based blind 时,等的时间会长一点,别以为它卡住了。如果你发现同一关在多个类型之间来回切换,说明页面对参数过滤不充分,注入方式很多样。
3.3 第三步:拖库——列库、列表、列字段、导数据
确认注入后,现在按顺序把数据一点点拿下来。以 MySQL 靶场为例,核心命令是这样的:
bash复制# 枚举所有数据库
sqlmap -u "http://127.0.0.1:8080/Less-1/?id=1" --dbs --batch
# 使用 security 库,枚举表
sqlmap -u "http://127.0.0.1:8080/Less-1/?id=1" -D security --tables --batch
# 查看 users 表结构
sqlmap -u "http://127.0.0.1:8080/Less-1/?id=1" -D security -T users --columns --batch
# 导出 users 表全部数据
sqlmap -u "http://127.0.0.1:8080/Less-1/?id=1" -D security -T users --dump --batch
第一次跑 --dump 时,sqlmap 会提示是否要猜解某些字段内容,默认选 N 即可,后面可以再用字典工具处理。它会自动把结果保存到本地目录,默认路径类似 ~/.local/share/sqlmap/output/127.0.0.1/,里面 CSV 格式的文件可以直接用表格软件打开。
这里我特别建议你别只跑一遍,而是把每一条命令都单独敲一遍,观察每个阶段输出有什么不同。比如 --tables 只返回表名,--columns 返回字段名和类型,--dump 才真正拉数据。理解这个过程,以后在真实授权测试中才能精准控制范围,而不是一把梭把所有库全拖下来。
3.4 第四步:提升效率的常用技巧
实际测试时,有几个小技巧可以明显加快速度。如果只关心某张表的某几个字段,用 -C username,password 指定字段再 --dump,能省不少时间。加 --threads=5 可以让并发请求更快,但注意太高的并发可能让靶场服务崩溃;自己练习无所谓,真实环境要谨慎使用。
加 --random-agent 可以随机 User-Agent,避免简单的 User-Agent 过滤;配合 --delay=1 可以让请求更温和。想保存完整日志,加 -v 3 或 -v 6,输出详细度不同,排错时非常有用。另外,如果你用 Burp Suite 作为代理,可以直接加 --proxy="http://127.0.0.1:8080",这样 Burp 里能看到 sqlmap 的每个请求,分析 payload 是不是你预期的那样。
如果你在靶场练习时时间比较充裕,我建议每条命令都故意加一个不太合适的参数,比如用 --dbms=mssql 指定成 SQL Server,看看 sqlmap 会报什么错,然后改成 mysql 再跑。这种“故意踩坑”的学习效率,比单纯背命令高十倍。
4. 从 GET 到 POST、Cookie:几种常见场景怎么写命令
4.1 POST 注入场景
很多页面不是通过 URL 传参,而是通过表单 POST 提交,比如登录框、搜索框。sqlmap 对这类场景最直接的写法是 --data:
bash复制sqlmap -u "http://127.0.0.1:8080/Less-11/" --data="uname=admin&passwd=admin" --batch
这里以 SQLi-Labs 的 Less-11 为例,它是 POST 登录框注入。注意,--data 里的参数值就是你在浏览器里提交表单时看到的键值对。如果不知道键名,可以用浏览器开发者工具看请求主体,或者用 Burp Suite 抓包。对新手来说,Burp Suite 抓包这一步建议学一下,因为很多靶场场景都是 POST 登录后才有注入,光看 URL 什么都看不出来。
POST 注入靶场里,你用 sqlmap 指定 --data 后,工具会把测试载荷塞进表单参数,观察登录是否成功、页面有没有报错、返回内容有没有差异。整个过程和 GET 注入本质上是一样的,换成 --data 只是为了让 sqlmap 知道“该往哪里塞数据”。如果你把 URL 里的参数留空但 --data 里写了参数,sqlmap 依然能正常识别。
4.2 用请求文件注入:省去手写参数的麻烦
还有一种很省事的办法:直接用 Burp Suite 抓包,把完整的 HTTP 请求复制保存成文件,然后让 sqlmap 读取这个请求文件。比如保存为 request.txt,里面可能是:
http复制POST /Less-11/ HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0
Content-Type: application/x-www-form-urlencoded
uname=admin&passwd=admin
然后用:
bash复制sqlmap -r request.txt --batch
这个方式的好处是,不用手动整理 URL、Cookie、POST 数据,sqlmap 会自动从请求文件里提取所有可能测试的参数。遇到复杂的登录态、多个 Cookie、JSON 请求体时,-r 比 --data 更可靠。很多真实授权测试里,我最常用的就是 -r 配合 Burp 抓包,效率极高。
4.3 Cookie 注入场景
Cookie 注入在真实系统中不算少见,因为有些开发会把用户身份信息放在 Cookie 里带进 SQL 查询。sqlmap 处理它需要先把 Cookie 原样带进来:
bash复制sqlmap -u "http://127.0.0.1:8080/Less-20/index.php" --cookie="uname=admin" --level=2 --batch
这里 --level=2 很重要,因为 sqlmap 默认只测试 GET/POST 参数,只有在 level 大于等于 2 时,才会把 Cookie 当作测试目标。你可以先不加 --level=2 跑一次,再对比加上之后的输出,能明显看出它多了一轮对 Cookie 参数的测试。
这类场景练下来,你会更理解 sqlmap 的“参数范围”概念:不是所有输入都会被默认测试,要主动通过 --level 扩展。换句话说,--level 不只是“更暴力”的开关,它是告诉 sqlmap“你要把测试范围扩大到哪一层”。
4.4 进阶:--level 和 --risk 到底怎么挑
--level 和 --risk 是新手最容易忽略但又很重要的两个参数。--level 控制测试深度:1 是默认,测试 GET/POST 参数;2 加入 Cookie;3 加入 User-Agent、Referer;再往上还会测试更多特殊场景。--risk 控制测试载荷的危险程度:1 比较安全;2 加入时间盲注等可能产生影响的测试;3 加入 OR 型 payload,可能修改数据。
在靶场里可以放心调高,但真实授权测试中,尤其是有业务写入的场景,--risk=3 可能会改变数据库中的数据,务必谨慎。我的习惯是先用默认参数跑,跑不通再慢慢提升,永远不要一上来就 --level=5 --risk=3,否则光是报告里的误报和脏数据就够你喝一壶。理解这两个参数背后的含义,比记住数值更关键。
5. 常见问题与排查实录
5.1 问题速查表
sqlmap 跑靶场时,报错翻来覆去就那么几类。我整理成一张表,遇到问题先对着查:
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
connection timed out |
靶场没启动或 IP 写错 | 先 curl 目标地址,确认能访问 |
target URL not valid |
URL 里参数格式不对 | 给参数赋值,比如 ?id=1,不要写 ?id= |
unable to connect to the target URL |
端口或服务异常 | 检查 docker ps 和防火墙 |
unknown database type |
漏了 --dbms 或探测失败 |
手动看页面报错,确认数据库类型 |
| 跑很久没有输出 | 默认注入类型不适应 | 加 --technique=BEUST 或 --level=3 |
| 导出数据是空的 | 注入点存在但字段不在当前表 | 先 --tables 确认库名、表名是否正确 |
| Python 报错缺少依赖 | 环境没配好 | 优先用 pip install -r requirements.txt 或用官方发行版 |
这张表不是让你死记,而是让你在遇到“哦?怎么不行”的时候知道往哪个方向查。对比来看,大部分问题都出在靶场服务本身,而不是 sqlmap 命令写错了,所以排查顺序永远是先确认环境,再怀疑参数。
5.2 踩坑实录:URL 报错、驱动缺失、超时
我在带新人时,最常见的坑有三个。第一个是 URL 参数问题。sqlmap 要求目标 URL 有实际参数值,比如 ?id=1。如果你写 ?id= 或者只写 http://.../?id,它可能直接报 target URL not valid。所以拿到一条 URL,先确认里面有没有可用的参数名和值。
第二个是数据库驱动缺失。sqlmap 依赖 Python 的数据库驱动,比如 MySQLdb、psycopg2。新装的 Kali 或 Python 环境经常缺这个,跑 SQLi-Labs 到一半会报 unsupported DBMS 或 missing python mysqldb。解决办法很简单,安装对应驱动即可:
bash复制apt install python3-mysqldb
# 或
pip install pymysql
第三个是时间盲注超时。如果你的靶场比较慢,或者网络波动,sqlmap 可能因为响应太慢判定为失败。这时候可以适当调大超时时间,比如 --timeout=30。注意,--delay 是让请求变慢,不是解决超时的手段,方向别搞反了。
5.3 我的避坑心得
多练、多输出、多故意踩坑,是学 sqlmap 最靠谱的路径。我自己的习惯是每学一个新参数,就在三个靶场上反复跑,比如 DVWA、SQLi-Labs、Pikachu 各来一遍,看同一个参数在不同场景下的差异。这样练下来,你至少能区分“这个参数是不是必须的”。
另外,我强烈建议你把 sqlmap 和 Burp Suite 搭配起来学。sqlmap 负责自动化,Burp 负责看请求包、改参数,两者结合能让你在真实演练中快速定位问题,而不是把 sqlmap 当黑盒乱试。学完 sqlmap 之后再回去看一些 SQL 注入原理文章,你会发现以前看不懂的地方突然就通了。工具和理论配合着学,进步会比单刷命令快很多。
6. 学完这些之后,下一步怎么走
6.1 把理论补上:SQL 注入类型与原理
工具再强,也只能替代你的手,不能替代你的脑。sqlmap 跑通之后,建议把 SQL 注入的基础理论补上:字符型注入和数字型注入的区别,单引号闭合的规律,注释符 --+ 和 # 对语句的影响,UNION 查询的字段数判断,盲注时如何通过页面差异判断条件真假。这些在 SQLi-Labs 里都能手工试,比如 Less-1 是字符型,Less-2 是数字型,你可以先手工戳一下,再用 sqlmap 验证,印象会深很多。
为什么强调理论?因为 sqlmap 输出的很多选项,比如 --prefix、--suffix、--string,都是在帮你构造更精确的 payload。你不懂闭合规则,就看不懂它为什么要加这些前缀后缀。等你能手工复现 sqlmap 的核心行为,才算真正入门了 SQL 注入测试。
6.2 把自动化与手工结合起来
自动化适合拿结果,手工适合理解过程。我见过不少新手只会敲 sqlmap 命令,让他手工判断一个注入点就完全不会。这个短板在面试或认证考试中很容易暴露。建议每关先用 sqlmap 跑通,再手工把 sqlmap 输出的核心 payload 拿到浏览器或 Burp 里复现一遍。比如看到 Type: error-based,你就手工试一下 updatexml 报错注入,理解为什么这条语句能把数据带出来。
一旦你开始手工分析 payload,你会发现 sqlmap 并没有那么“玄”,它不过是用大量请求去测试几种固定的注入模式。你在靶场上手工试过的类型越多,回头再理解 sqlmap 的日志就越轻松。这也是为什么我一直说,靶场练习要“自动化一遍,手工再一遍”。
6.3 最后几条红线
写到这里,忍不住多说几句。sqlmap 是工具,能力越大责任越大。它只能用于你自己搭建的靶场、实验环境,或者获得明确授权的渗透测试项目。不要拿在线考试系统、别人的网站、生产数据库来练手,这不仅涉及法律风险,也违背一个安全从业者最基本的职业底线。我在教新人时的第一课永远是:先学会授权,再学技术。这条红线比任何 sqlmap 参数都重要。
实际操作中,我最推荐的学习路径是:先玩 SQLi-Labs,再玩 DVWA,然后用 Pikachu 串起来做一次完整测试流程,最后再看一两本 Web 安全入门书。把这条路径走完,你对 sqlmap 的理解就不仅仅是“会敲命令”,而是真正知道它每一步在做什么、为什么这么做。遇到新场景时,你也能很快写出合适的命令,而不是翻笔记翻到头大。
嘿,这几个字我都不是白写的,全是踩了无数坑换来的。希望这份教程能让你少走点弯路。
