不想看你只看过没用过的东西被别人当成实战教程。这篇文章,就是把你带到键盘前面,一步一步走完从环境搭建到拿到第一管数据的全过程。如果你想学安全,不管以后是打CTF、做护网还是搞等保,SQL注入,尤其是配合自动化工具的攻击方式,你是躲不开的。所以今天这篇,我用DVWA这个经典靶场,手把手带你把sqlmap从入门到能实际打点,全部走一遍,该踩的坑我提前给你踩,你只需要跟着敲命令就行。
写这篇的由头很简单,我最近在带几个新人入门,发现一个特普遍的问题:很多人知道sqlmap这个工具,也背过不少参数,但真正到了自己搭了个本地靶场,反而各种连不上、扫不出、跑不完,然后就卡在那儿放弃了。问题出在哪?多半不是工具不行,而是你压根没理解sqlmap的工作方式和它说的“人话”。今天这篇就来解决这个事,全程实操,你跟着我命令敲完,脑子里有整个脉络了,以后遇到真实场景,套路也是一样的。
1. 动手之前,先把靶场环境给我搭明白
很多人一上来就急着敲sqlmap命令,结果连目标都访问不了。咱们干这活儿的铁律:先有合法可控的目标,再谈测试。DVWA(Damn Vulnerable Web Application)这种自带的“漏洞练习生”,就是干这个用的。专门为想学Web安全的兄弟们设计的一台“带病”的Web应用,你可以在里面放心大胆地折腾,搞坏了也不心疼。
1.1 DVWA靶场搭建:两种最快、最省心的姿势
搭建DVWA,我推荐在国内网络环境下优先用Docker方式。别去费劲搞什么PHPStudy加手工配置数据库,又慢又容易出幺蛾子。
方式一:Docker一条龙(强烈推荐,干净利落)
我假设你已经装好了Docker和Docker Compose。没装的,自己官网下个桌面版就行。然后我们干这几件事:
# 1. 拉取 DVWA 的官方镜像,这个镜像里面环境都给你配好了 docker pull vulnerables/web-dvwa # 2. 启动容器,映射端口 80 到本地的 8081,方便访问 docker run -d -p 8081:80 --name dvwa vulnerables/web-dvwa # 3. 启动完成后,先看一眼容器日志,确认 Apache 和 MySQL 都正常运行 docker logs -f dvwa看到日志里出现了Apache started和MySQL started的字样,就说明环境起来了。这时候你在浏览器里输入http://127.0.0.1:8081就能看到DVWA的登录界面了。默认账号密码是admin/password。
注意:我第一次拉这个镜像的时候,出现过容器能启动但数据库没初始化好的情况。最直接的办法就是
docker restart dvwa重启一下容器,多试两次基本能好。如果一直连接不上数据库,就docker exec -it dvwa /bin/bash进容器里去手动启一下 MySQL 服务。
方式二:本地手动搭建(有基础的老手专用)
如果你不想用Docker,那就自己装个PHP+MySQL环境。Windows上可以考虑用小皮面板,Mac上可以用MAMP或者自己配。
- 去 GitHub 把 DVWA 源码下载下来,扔到 Web 服务器的根目录。
- 复制
config/config.inc.php.dist为config.inc.php,改一下数据库密码。 - 然后访问
http://127.0.0.1/dvwa/setup.php,点一下 “Create / Reset Database” 按钮。
手动搭建的问题在于PHP版本和MySQL版本兼容性,我遇到过用新版本PHP直接白屏的情况,这时候宁可换老一点的PHP版本,别在这上面耗时间。
1.2 登录和初始化:拿到一个能用的“带病”目标
无论用哪种方式,第一步都是进到DVWA首页。默认账号密码是admin/password。
进去之后,你会看到左边一排菜单,User Registration、Brute Force、SQL Injection……咱们今天的主角是SQL Injection这个页面。
划个重点,页面最底下有个Security Level(安全级别)选择器。你刚开始学,务必选成 Low。这个选项代表着后端代码过滤的严格程度。Low 级别是最原始的、没有任何防护的代码,非常适合先搞清楚sqlmap的攻击流程。等你 Low 玩明白了,再调到 Medium 和 High 去看看,你就知道为什么真实环境中token、过滤和WAF会让工具寸步难行了。
2. 核心武器:扒开sqlmap的“胃”,看它怎么把注入跑出来的
在敲第一条命令之前,我强烈建议你先明白sqlmap的内部逻辑。它不是一个只会拿Payload乱怼的“脚本小子工具”,它内部是个井井有条的流水线。
2.1 从发个包到拿数据:sqlmap的工作流水线
sqlmap拿到你的目标URL后,心里其实有一本账:
- 踩点(探测):先发送一些正常的请求,看看目标站点的响应状态、Web容器、数据库指纹等基础信息。
- 检测(Detection):在一个参数里注入一些能让SQL语句“报错”的特殊字符,比如单引号
',然后观察响应内容有没有变化。如果页面报错信息显露了数据库语法,或者返回了和原请求不同结构的数据,它就认为这里有戏。 - 确认(Confirm):通过布尔逻辑盲注(?id=1 and 1=1 和 ?id=1 and 1=2)或者时间盲注(?id=1 and sleep(5))来再次确认,这个参数确实是SQL注入漏洞。
- 指纹识别(DBMS Fingerprinting):不同的数据库(MySQL、Oracle、SQL Server),注入语法和拿数据的姿势是完全不一样的。sqlmap会先判断出,当前环境是MySQL还是别的,然后决定后续用何种姿势怼。
- 数据榨取(Data Extraction):确认了漏洞和数据库类型,剩下的就是机械化地跑数据了。它会先列出所有的库名(--dbs),然后再跑表名(-D 库名 --tables),再跑字段名(-D 库名 -T 表名 --columns),最后就是把字段的具体值拖出来(--dump)。
所以,一条sqlmap命令的本质,就是告诉它“你要打哪个靶场”和“你想打到什么程度”。
2.2 新手必知的“生活化”参数类比
sqlmap的参数很多,初学者不要被吓到。我们就拿“点菜吃饭”来打个比方,一下就记住了:
| 参数/用法 | 吃饭类比 | 作用解释 |
|---|---|---|
-u或--url | 告诉服务员,你去哪家饭店 | 指定目标URL |
--batch | 让服务员全权代理,不用每道菜都问你一遍 | 自动回答所有交互式问题,用默认选项 |
--dbs | 服务员把整个菜单(所有数据库)拿给你 | 枚举出所有数据库 |
-D | 指定你这顿要去吃川菜(选库) | 指定要查的数据库名称 |
--tables | 把川菜店的所有菜品列表拿上来 | 枚举指定库中的所有数据表 |
-T | 你看上了“回锅肉”这道菜 | 指定要操作的数据表 |
--columns | 这盘回锅肉,你问老板是用了哪些材料做的 | 枚举指定表的所有字段名 |
--dump | 别问材料了,我直接把菜偷吃掉 | 将指定字段/表的数据全部拖下来 |
--level和--risk | 你这人能吃辣吗?能的话我就上魔鬼辣 | 检测深度和风险等级,越高测的点和Payload类型越多 |
--dbms | 你直接跟老板说“我就信任重庆师傅” | 指定后端数据库类型,加快检测速度 |
有了这个“菜单”,你再去看sqlmap命令,是不是就觉得顺眼多了?它就是个自动化的点菜员。
2.3 选好你的第一道菜:注入点在哪,参数怎么填
DVWA的 SQL Injection 页面,实际上是一个经典的GET型参数注入。它的请求URL长这样:
http://127.0.0.1:8081/vulnerabilities/sqlib/?id=1&Submit=Submit这里面,id=1就是我们要下手的“主菜”。所有流程都从搞这个参数开始。
注意一点,DVWA是需要登录的,所以你敲sqlmap命令时,必须带上当前浏览器的会话Cookie,不然sqlmap发出去请求,会被服务器重定向到登录页,啥也跑不出来。我会在下面实操命令中把具体做法写出来。
3. 实战!从“hello world”到“数据在手”,全流程详解
现在,请打开你的终端,跟我走一遍完整的实战。这一段就用上面提到的Docker DVWA环境来演示,目标URL我换成通用写法,你自己敲命令时记得把IP和端口换成你自己的。
开局第一步:确认靶场可用性
这一步可做可不做,但我强烈建议,先手动在浏览器里访问一下http://你的IP:8081/vulnerabilities/sqlib/?id=1&Submit=Submit,确认页面能正常显示。如果能出来一个User ID: 1,以及First name和Surname,那咱们的靶场环境就绪了。
3.1 基础探测:先让sqlmap“尝一口”,判断能否下嘴
第一轮探测,我们先用最基础的姿势让sqlmap去判断这是不是个注入点。必须带着Cookie。Cookie哪里找?用浏览器开发者工具,F12,网络(Network)选项卡,随便点一个请求,在请求头里就能看到Cookie字段。
# 这条命令,告诉sqlmap: # 1. 目标URL是什么(--url) # 2. 带上登录态的Cookie(--cookie) # 3. 所有交互问题都自动选默认(--batch) # 4. 只做检测,不进行后续的数据榨取(--current-db) sqlmap -u "http://你的IP:8081/vulnerabilities/sqlib/?id=1&Submit=Submit" --cookie="PHPSESSID=你抓到的会话ID; security=low" --batch --current-db跑完这条命令,如果一切正常,你就会在漫天的日志里看到这么几个关键信息:
Parameter: id (GET):sqlmap找到了注入参数,是id。Type: boolean-based blind:这个参数存在布尔型盲注。Type: UNION query:这个参数还存在联合查询注入。Type: error-based:还有报错注入。current database: 'dvwa':它掏出了当前数据库的名字。
看到这些,你的眼睛就可以放光了,说明第一步成功了。尤其注意current database这个词,它意味着sqlmap不仅发现了漏洞,而且已经成功连上了数据库服务器,别人家的库名都拿到手了。
3.2 进阶操作:暴力获取整个数据库里的“宝藏”
确认有洞之后,咱们干点正事,把数据都捞出来。刚才那步骤是试探,这一步是真的开吃。
# 直接把整个 dvwa 库的所有表数据都给拉下来,这会需要一点时间 sqlmap -u "http://你的IP:8081/vulnerabilities/sqlib/?id=1&Submit=Submit" --cookie="PHPSESSID=你抓到的会话ID; security=low" --batch -D dvwa --dump--dump这个参数是集成了前面--tables和--columns的“一条龙服务”,它会自动枚举出你指定的库(-D dvwa)下面所有的表,再枚举出每个表的列,最后把列里的数据全部导出。
跑完之后,sqlmap会创建一个结果的本地存储文件,路径一般是~/.local/share/sqlmap/output/你的IP地址/dump/dvwa/下面。里面会有各个表名的CSV文件。
你打开users.csv,就能看到DVWA靶场里所有用户的账号密码了。反正我本地靶场里,用户的密码Hash是一堆看不懂的密文,因为DVWA默认用了MD5加密。但这不影响我们理解整个流程,这时候你就该明白,当真实渗透时,拿到这个CSV文件,就意味着你对这个系统的账户体系已经了如指掌了。
3.3 从GET到POST:换汤不换药的注入姿势
很多新手会卡在POST型注入上。DVWA里有个 “SQL Injection (Blind)” 页面,它是POST请求。
GET请求是把参数放在URL后面,POST请求是把参数放在请求体里面。sqlmap也早就想到了,处理方式很简单:
姿势一:手动把报文存成文件
你打开Burp Suite,手动拦截一下这个POST请求,然后把整个原始HTTP报文复制出来,存成一个post.txt文件。
POST /vulnerabilities/sqli_blind/ HTTP/1.1 Host: 你的IP:8081 Cookie: PHPSESSID=你的会话ID; security=low Content-Type: application/x-www-form-urlencoded id=1&Submit=Submit然后sqlmap直接读取这个文件:
sqlmap -r post.txt --batch --dbs姿势二:直接用命令指定数据参数
不想用Burp,直接用--data参数指定POST数据也行:
sqlmap -u "http://你的IP:8081/vulnerabilities/sqli_blind/" --cookie="PHPSESSID=你的会话ID; security=low" --data="id=1&Submit=Submit" --batch --dbs说句实在话,在真实的Web渗透中,POST型注入比GET型要多得多。因为开发人员大部分情况下会把查询操作留成GET,把更新、添加操作留成POST,而POST参数又是藏起来的,所以很多人会忽略。你用-r读取HTTP报文的方式,是我个人最常用的,因为它可以最完整地还原现场,还能顺便修改报文里的一些请求头信息。
3.4 提升伤害力:认清瓶颈在哪
刚才我们直接--dump很爽,但真实环境下没那么简单。如果目标库很大,跑起来就很慢很慢。这时候就别傻等着,在命令里加个并发:
# --threads 参数能提升并发数,但别打太高,太高容易影响目标稳定性惊醒蓝队。 sqlmap -u "http://你的IP:8081/vulnerabilities/sqlib/?id=1&Submit=Submit" --cookie="PHPSESSID=你的会话ID; security=low" --batch -D dvwa --dump --threads=3而且当你明确知道这是一个MySQL数据库时,加个--dbms=mysql参数,能帮sqlmap省掉很大一部分识别数据库指纹的时间,跑起来效率能翻倍提升。
4. 工具和人,谁才是决定结果的关键?
聊完怎么跑sqlmap,咱们得聊聊比工具更重要的东西。我见过太多人依赖sqlmap跑线上目标,结果跑半天什么都跑不出来,就开始怀疑工具不行。其实问题不在这。
4.1 绕过套路一箩筐,别被“秒破”带偏
真实生产环境的数据库,十有八九不是Low级别的DVWA。开发人员会加各种过滤,WAF也有可能拦着你。针对这种情况,sqlmap提供了很多“绕WAF”的参数,但效果因站而异。
我这里可以给一个“组合拳”示例,但这是给Medium级别DVWA用的,而且不保证在真实场景一定通杀,实际上每个目标都不一样,没有银弹。把重点放在理解原理,不要把“套路”当“公式”。
# 这是一个非常基础的绕WAF思路,用注释符、大小写和解码组合:breaking LCASE等手段 # 真实环境一定要仔细看目标响应的差异,再针对性进行设计。 sqlmap -u "http://你的IP:8081/vulnerabilities/sqlib/?id=1&Submit=Submit" --cookie="PHPSESSID=你的会话ID; security=medium" --batch --tamper=space2comment --level=3 --risk=2--tamper=space2comment是一个脚本,能把Payload里的空格改成/**/去绕过过滤。这属于最常见的绕WAF思路:让检测规则认不出你的SQL语句。但各位,醒醒。这只是入门玩具。真实的WAF拦截策略比这复杂得多,什么二次编码、参数污染、分块传输……水很深。你现在最该信的那些教程,应该教会你的是如何分析WAF的拦截日志,而不是只会套用--tamper参数。
4.2 手动注入的能力,才是你的底气
sqlmap查不出来,或者被封了,怎么办?这时候你就得回归手动。手测SQL注入的基本功是必须有的,因为工具的本质是替代你发送大量请求,但确认漏洞存在、判断注入类型这些逻辑,你自己心里必须有数。
比如拿到一个id=1参数,你首先会在URL后面加个',如果页面报错或显示不正常,说明有戏。然后再试id=1 and 1=1和id=1 and 1=2,如果前者显示正常,后者显示空白或报错,那这就是个典型的布尔盲注。接着你再试id=1 union select 1,2,3,如果页面上显示了2或3,那恭喜你,联合查询注入也成立。这一套手动流程走下来,你对SQL注入的理解,绝对比只会敲--dump的人深刻十倍。
这个基本功作用很多没跑过测试的人体会不到。我就遇到过用sqlmap怎么都跑不出来,手动看了一眼才发现其实是个鉴权缺陷导致的逻辑漏洞,根本不是SQL注入的情况。工具再强,分析思路才是决定你天花板的那个东西。
5. 实战中99%的人都会碰到的报错与问题排查
最后,把大家私信问得最多的一类问题集中整理一下。这些问题我当年刚学的时候也都遇见过,现在给你提前打好预防针。
5.1 常见报错速查表
这里有一份我自己的排错备忘录,你可以保存下来,遇到问题先按表排查。
| 报错信息 / 现象 | 根本原因 | 解决办法 |
|---|---|---|
connection timed out | 网络不通,或目标地址错误 | ping 一下目标IP;确认Docker容器端口映射是否正确 |
invalid URL | URL格式不对 | 检查URL末尾是否有空格,参数是否写错 |
too many redirects或it is not a valid target | 报错说目标不是动态页面 | 加上--force-ssl强制SSL,或者去掉多余的参数;确认URL确实存在动态参数 |
unable to connect to the target URL | 目标站点拒绝连接 | 可能是需要特殊Header,比如Host头、User-Agent,用--headers带上 |
跑了几分钟还在testing connection to the target URL | 网络实在慢,或者目标环境有网络波动 | 耐心等,或者ctrl+c中断后换个--delay参数重新来 |
提示detected the back-end DBMS is MySQL后就没动静了 | 正在跑数据库指纹识别,很正常 | 喝口水,等它自己跑完。如果很久没反应,可以加--dbms=mysql指定数据库类型,加快速度 |
中途报错failed to retrieve the data | 可能是目标数据库有写入保护或临时表被锁 | 换个时间段重试;加--no-cast参数去掉强转类型;或者--hex强制使用十六进制查询 |
5.2 解决“跑得太慢”的核心思路
很多人反馈,sqlmap跑数据的时候,一条一条滚,跟老牛拉车一样,特别急人。这其实特别正常。盲注的机制就是一次问数据库一个问题,根据是或否来判断数据内容,慢是它的天性。
遇到这种情况,你的第一反应不该是加--threads无限加速,而是去想能不能换个注入类型。比如,把--technique=B(纯布尔盲注)改成--technique=U(联合查询),如果目标存在联合查询注入,那速度简直就像从走楼梯变成了坐电梯。核心思想是,快没快的道理,慢有慢的原因,先搞清楚目标支持哪种注入技术,再去对症下药。
5.3 别忘了,日志和输出文件是你的救命稻草
sqlmap在你运行结束后,会自动把结果存在本地的文件里。路径通常是:
~/.local/share/sqlmap/output/你的目标IP/这个文件夹里的log文件记录了sqlmap运行的全过程,dbs、tables、columns等CSV文件就是你要的数据。我强烈建议你,每跑完一个目标就去翻一下这个目录里的日志,想想为什么sqlmap能成功,为什么中间会报错,这里面信息量巨大。
顺便多说一句,不同版本的sqlmap行为差别挺大的。老版本的--batch行为可能和新版本不一致,所以我在指导新人时,一般会让他们先跑个sqlmap --version确认一下自己的版本,再按对应的参数来操作。
最后,说点实在话
搞渗透测试,工具可以让你跑得很快,但只有思路能让你走得很远。sqlmap是每个Web安全从业者手上一个必备的锤子,但你要知道,什么时候该用锤子,什么时候该换用螺丝刀、换用剪刀。这篇文章带你把sqlmap在DVWA上的流程完整走了一遍,你把这个过程摸索透了,之后再去看那些精妙的绕过技巧,才能入木三分。
我这边的经验是,学这种攻击工具最好的方式,就是把它丢进各种故意的、带漏洞的靶场里去反复蹂躏,摸清它每一步做了什么、为什么这么做。等你拿着sqlmap,能在一台陌生的靶机上跑出库名和表名的瞬间,你才能体会到那种“我把它拿下了”的快感。别急着上真站,也别迷信单一工具,多练边界,多关注防御的思路。这条路很长,我还在走,希望你也能保持好奇,踩坑不回头。