做Web安全测试的同行都知道,靶场里的“暴力破解”模块看似最基础,却是最能反映攻防思路差异的一个环节。Pikachu系列把暴力破解单独拎出来,不是为了让你背几条命令,而是想让你真正理解“密码为什么会被试出来”以及“服务端到底从哪里堵住这条路”。这篇文章我就以Pikachu中的暴力破解场景为主线,把原理、三类不同场景的实操、工具配置、防御思路和排坑经验一次性讲透,适合刚入门Web安全的同学,也适合给做开发或运维的朋友当一份防御清单。
1. 暴力破解的本质:为什么密码会被“试”出来
1.1 从现实类比看爆破原理
暴力破解的核心逻辑其实特别朴素,就像你忘了行李箱密码锁的密码,只能从000、001、002一个一个试过去。Web暴力破解就是把这种“穷举”行为搬到HTTP请求上:攻击者不断向服务器提交用户名和密码的组合,直到某一次校验通过。
这里有个关键认知需要先纠正,很多人觉得暴力破解是“技术含量低”的攻击手法,实际上它能不能成功,取决于三个前提:密码本身是否足够弱、服务端是否做了防爆破限制、攻击者是否有足够的时间和算力。三个条件里只要有一个不满足,爆破就基本走不通。
Pikachu靶场里设置的Admin账号密码都很短小,目的就是让你把精力聚焦在“爆破流程怎么走”,而不是花时间纠结字典大小。真正生产环境里,爆破的成功率远没有靶场这么高,但这套流程的每一步——抓包、标记参数、配置字典、分析响应——都是后面做更高级测试的基础功。
1.2 成功率背后的数学账
搞爆破之前,最好先学会估算工作量。假设一个系统只要求4位数字验证码,那候选空间就是10的4次方,共10000种组合,平均试5000次就能中。如果密码策略要求8位小写字母,候选空间就是26的8次方,超过2080亿种组合,这时候纯在线爆破就不现实了,得依赖弱密码字典或者先拖库再离线跑。
这个数学账直接决定了你的测试策略。
密码位数的每一次增加,候选空间都是指数级膨胀。所以你在靶场里看到的“爆破成功”,往往是因为管理员账号用了Admin/123456这种默认弱口令,而不是因为工具跑得快。理解了这层关系,你就明白为什么安全基线里总强调“8位以上、混合字符集、定期更换”——每一条都是在抬高爆破的时间成本。
而服务端一旦加了锁定策略,比如连续5次失败锁定15分钟,攻击者的“尝试速率”就会断崖式下跌。哪怕字典里有几万个密码,锁定一开,实际能试的次数也就只有个位数。
2. 靶场里的三类暴力破解场景
2.1 表单暴力破解:最基础的爆破入口
Pikachu暴力破解模块第一个场景就是典型的表单登录页。打开页面你会看到一个普通的登录框,输入用户名和密码后提交,服务端返回“登录成功”或“用户名或密码不存在”这种明文提示。
这种场景的测试流程是固定的:
- 先把代理配置好,Burp Suite监听本地端口,浏览器流量走代理。
- 随便输入一个用户名密码,点击登录,Burp里会抓到一条POST请求。
- 请求体长这样:
username=admin&password=123456&submit=Login。 - 把这条请求发送到Intruder模块,在username或password的值上标记攻击位置。
- 选择攻击类型、挂载字典、设置线程,然后Start Attack。
这里我建议新手别急着开高线程。Pikachu靶机性能一般,线程开到20以上很容易把靶场自己跑挂,或者触发服务端临时拒绝。实际测试中,10个线程、每条请求间隔几十毫秒,这个节奏对靶场和生产环境都比较友好,也更容易观察响应差异。
响应结果的判断核心就是“长度”和“状态码”。登录成功的响应长度通常跟登录失败有明显区别,比如失败返回2310字节,成功返回2345字节,Intruder结果列表里一眼就能揪出来。这个判断思路在后面复杂场景里同样适用。
2.2 验证码绕过:从“失效”到“可预测”
第二类场景在表单基础上加了一个4位数字验证码。很多人一开始就直接去识别验证码图片,其实这个场景的考点不在“识别”,而在“验证码有没有真正起作用”。
你可以在Burp里抓一下刷新验证码和登录的请求,然后做几个测试:
- 第一次请求拿到一个验证码,登录时不刷新验证码,反复提交同一个验证码,看看服务端是否每次都校验。
- 换个思路,把当前会话的验证码请求和登录请求分成两个独立请求来发,看看验证码是否跟会话绑定。
- 甚至可以直接删掉请求体里的验证码字段,看看服务端有没有做“必填校验”。
实际操作中你会看到几种典型的漏洞形态。最常见的是验证码不更新:同一个验证码图片能用一整天,攻击者只需要找会识别的人或工具,把验证码解出来一次,后续就可以无限次试用密码,验证码形同虚设。第二种是验证码只存在Session里,但校验逻辑在登录接口里;攻击者可以先请求一次验证码接口,拿到验证码文字后再带着这个值去爆破密码。第三种最隐蔽,验证码有效但可预测,比如生成规则是当前时间戳后四位,那只要搞清楚算法,爆破成功率直接拉满。
这里要提醒一句:对验证码的测试,重点永远是“服务端是否强制校验、校验是否每次都执行”,而不是跟验证码图片的扭曲程度较劲。很多人把时间花在OCR识别上,方向就偏了。
2.3 Token防爆破:动态令牌的攻防博弈
第三类场景是token防爆破。每次登录请求里都带一个隐藏的token字段,值是一串随机字符串。第一次请求页面时,服务端在Session里存一份token,同时把token渲染到表单隐藏域里;下次登录提交时,服务端比对Session里的token和请求里的token是否一致。
这种设计理论上能让爆破变得很麻烦,因为每次请求都要先GET一次页面、提取新token、再带着这个token去POST。但靶场里给你展现的是token防爆破的“标准姿势”,你要学习的是怎么自动化它。
我这里说两种实现路径。
第一种是用Burp Suite的Macro功能。设置一个Macro,内容就是“GET登录页面并提取token”,然后在Intruder的请求发送前调用这个Macro,把提取出来的token自动替换到POST请求体里。这样每次爆破请求都会先刷新token,再提交。
第二种是写Python脚本。用requests库手动管理Session,先GET拿到token,再POST带token的登录请求,循环尝试字典里的密码。代码逻辑很直白:
import requests url = "http://target/login.php" with requests.Session() as s: for pwd in open("passwords.txt"): r = s.get(url) token = extract_token(r.text) data = {"username": "admin", "password": pwd.strip(), "token": token} resp = s.post(url, data=data) if "success" in resp.text: print("found:", pwd.strip()) break这个脚本的核心点在于Session对象会自动维护Cookie,而每次GET刷新页面后token也在更新。你不需要手动去管Cookie和隐藏域的值,只要每次循环里先取再带就行。
3. 工具实操:Burp Suite从抓包到出结果
3.1 抓包与Intruder配置细节
Burp Suite的Intruder是整个爆破流程的核心模块。但很多新手卡在第一步:不知道把攻击位置标在哪个参数上。
这里的判断标准很简单:你爆破什么,就把什么参数标记为Payload Position。爆破密码,就标记password的值;如果连用户名也不确定,就把username和password一起标记,用Cluster Bomb攻击类型做笛卡尔积组合。但实际测试中我建议尽量少用Cluster Bomb,因为组合数爆炸,比如10个用户乘以1000个密码,就是10000次请求,线程开大了容易把服务端打崩。
Intruder里还有一个容易被忽略的选项是“Request Timing”。你可以在设置里给每个请求加一个固定延迟,比如100毫秒。这个设置对绕过低配服务器限流很有用,也能降低触发WAF的概率。做安全测试不是比谁跑得快,而是比谁跑得稳、跑得准。
关于Payload Position还要注意一点:有的登录接口参数是JSON格式,比如{"username":"admin","password":"123"}。这种情况下直接在Intruder里对JSON字段值做标记也行,但要确认Content-Type是application/json。某些系统在Content-Type不匹配时会直接返回415或400,导致所有请求全部失败。
3.2 字典选择与Payload处理
字典是爆破成败的关键。但我不建议新手上来就去下载几十GB的超大字典,那既浪费时间又容易被服务器封IP。靶场和多数真实测试场景,一份Top1000弱密码列表就够用了。
我一般会维护一份精简字典,包含这些类型:
- 常见弱密码:123456、admin、password、qwerty、111111
- 键盘规律:qwertyuiop、1qaz2wsx、zxcvbnm
- 年份和后缀组合:admin123、passw0rd、root@2023
- 基于域名的变体:如果目标是某公司官网,把公司域名和常见密码组合一下
Burp Intruder的Payload Processing也是个很实用的功能。你可以在字典的每个词前后加上前缀后缀,比如给每个密码后面追加“@123”,就能把一个基础字典扩展成多个版本。这样手里一本字典,能覆盖的场景比想象中多得多。
3.3 结果判断:看长度、看状态码、看响应正文
爆破跑完之后,结果列表里可能会有几百上千条记录,怎么快速筛出真正成功的那个?我的习惯是三步走。
第一步,按响应长度排序。多数系统的成功登录和失败登录返回内容长度有明显差异,哪怕是几字节的差异,在Intruder的排序视图里也会非常突出。先把长度异常的几条挑出来。
第二步,看状态码。200不一定代表成功,302反而更可疑。很多登录成功后服务端会重定向到首页,返回302;而登录失败时可能是200加上一段错误提示。所以别只盯着200。
第三步,看响应正文。挑出候选请求后,切换到Response页签,在原始返回里搜索“success”“welcome”“dashboard”之类的关键词。这一步可以直接确认到底是翻页到了后台,还是仅有一段提示文字。
这三个步骤配合起来,基本不会漏掉结果。尤其是遇到动态token或带验证码的场景,响应长度判断法依然有效,因为这个特征很难被完全抹平。
4. 防御设计与测试边界
4.1 服务端防护的关键配置
理解了爆破的流程,再看防御就有代入感了。服务端能做的防护其实就几条,每一条我都建议开发同学对照检查。
第一,登录失败锁定。连续失败达到阈值(比如5次)后锁定账号或IP一段时间。锁定策略要区分账号粒度和IP粒度,否则攻击者可以直接换IP继续试,或者拿同一个IP去撞多个账号。
第二,强制验证码。验证码别只在前端画个花架子,服务端必须强制校验,并且每次验证完成后立即作废。如果要提高对抗性,用行为验证码或滑动验证码,传统的4位数字验证码在OCR工具面前抵抗力已经很弱了。
第三,双因素认证。密码被爆破只是一半,登录还要短信验证码或TOTP动态口令兜底。对管理员系统,这是必须项,不是可选项。
第四,限速和风控。单位时间内的登录请求次数做限制,异常高频的直接加入黑名单或弹验证码。这一条能拦住绝大多数自动化工具。
第五,密码策略和初始密码强制修改。很多爆破成功不是因为密码简单,而是管理员账号注册后没改初始密码。强制首次登录改密、定期评估弱密码,都是低成本高收益的事。
我在某个模拟项目X里做过测试,一个系统把所有弱密码全部清掉,爆破字典里跑了几百次连一个账号都没出来。可见防御的重点是把“弱密码”这个变量彻底拿掉,而不是单纯加验证码。
4.2 测试者的合规边界
说到这里必须插一段非常重要的话。暴力破解在任何生产系统上都有风险,尤其当你对不属于自己的系统发起爆破时,可能涉及法律问题。做安全测试,前提永远是获得授权。
在靶场里练手是完全合理的学习行为,因为靶场本来就是模拟漏洞环境,设计出来就是给人打的。但换到真实站点,你要先确认自己有没有测试权限,测试范围和时间窗口是不是明确。测试时设置的线程数和频率也要克制,避免把自己把系统打崩了,那反而是事故。
这里顺便提醒一下:这类测试尽量使用测试域名和测试账号,不要拿真实用户账号去验证。很多系统有账号锁定机制,对一个真实用户账号反复尝试密码,很可能把人家的账号锁死,然后你就知道什么叫“好心办坏事”了。
5. 实战常见问题与排查技巧
5.1 常见问题速查表
我把自己在靶场和某个跨平台系统项目里踩过的坑整理了一下,做成一张速查表,遇到问题直接来对照:
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 所有请求响应都一样 | 服务端加了统一提示或锁定策略 | 检查是否被限流或封IP,降低线程重试 |
| 请求数量远大于字典数量 | Cookie或Token未正确更新导致重复请求 | 检查Macro配置或Session处理逻辑 |
| 响应长度差异不明显 | 成功和失败页面结构相似 | 改用状态码+关键词双重判断 |
| 验证码明明对了还提示失败 | 验证码与Session未同步刷新 | 确认每次请求是否更新了验证码 |
| 爆破到一半被403拦截 | 触发了WAF或IP封禁 | 加随机延迟、换端口或代理池 |
| 有token的页面请求响应异常 | 登录页需要在爆破前保持会话 | 检查有没有先GET页面维护Session |
5.2 排查思路与独家技巧
第一个技巧是查响应头。有些系统在登录失败时会返回特定的响应头标记,比如X-Login-Failed: 1,或者在某一段Cookie里写入尝试次数。这些信息不一定显示在页面上,但抓包能看到。多翻Response头,经常能挖到判断依据。
第二个技巧是综合利用时长差异。一个简单的登录校验和后续复杂逻辑处理耗时不同。比如账号存在时服务端可能额外走一遍密码哈希计算,响应时间会比“账号不存在”多几十毫秒。虽然这个差异很小,但用大量样本取平均值,也可以作为账号枚举的判断依据。这个思路在某种场景下比看响应文本更稳,因为文本可以伪装,耗时很难伪装。
第三个技巧是对爆破目标做降噪。真实渗透中经常会出现大量超时请求,干扰结果判断。此时可以在Intruder的Options里设置失败重试次数和超时时间,也可以把超时请求单独标记出来。跑完后再根据状态码和长度聚类分析,而不是盯着满屏的记录硬看。
还有一个很多人忽略的点:爆破之前先手动登录一次,把正常成功请求的指纹记下来。后面判断结果时拿来对比,比凭感觉猜可靠得多。
结尾
实操下来我的体会是,Pikachu的暴力破解模块最值钱的地方不在于“能跑出密码”,而在于它把爆破这件事拆成了三个递增的难度层级:普通表单、验证码、token防爆破。每过一层,你就对服务端防护的运作机制多一分具体认知。我个人建议你在练完每一个场景后,都手动配置一遍对应的防御方案,再回来试试原来的爆破工具还能不能打通。这种“攻防对打”的循环练上几轮,你对登录安全的理解就会比别人只刷靶场深入得多。最后再分享一个小技巧:把自己常用的爆破脚本和字典整理成一套标准化流程,遇到新的登录接口,先跑一遍指纹确认有没有防护,再决定用什么姿势打,效率会翻倍。