很多刚接触Web方向CTF的同学,看到题目标签写着“爆破”,第一反应就是打开Burp Suite,把字典往Intruder里一甩,然后盯着进度条等结果。我刚开始也是这样,但结局通常比较尴尬:要么几千条记录跑完全是同一个状态码,要么正确结果淹没在一堆长响应里根本认不出来。后来我才意识到,CTF里的爆破,尤其是入门阶段的爆破,真正考的从来不是“跑得快”,而是“看得懂”——你得先弄清楚这个登录逻辑有没有校验、哪个参数参与了判断、返回包给了你什么信号,然后才知道该不该爆、怎么爆、用什么字典爆。
这篇内容主要围绕ctfshow这类Web入门靶场的“爆破”专题展开,适合刚接触Web题、想系统搞懂Burp Intruder用法、以及卡在爆破题不知道如何分析响应结果的初学者。我会从题目逻辑、工具配置、实战场景、响应分析、字典构造这几个维度拆开讲,最后再把那些让我白跑过N次的坑一并列出来。读完不敢说你立刻能打穿所有爆破题,但至少遇到“爆破”标签时,你不会再像个没头苍蝇一样乱撞。
1. 爆破题到底在考什么:先看清题目再说跑不跑
1.1 遇到“爆破”标签先别急着上字典
很多人拿到题的第一步就错了。看到标签写“爆破”,下意识觉得“这不就是暴力破解吗”,于是赶紧加载字典开始跑。但CTF的出题思路和现实渗透不一样,它更看重你对逻辑的理解,而不是计算速度。爆破标签往往只代表“你需要通过枚举某个参数来得到答案”,至于这个参数是密码、验证码、token还是某个隐藏文件名,题目不会直接告诉你。
拿最典型的登录爆破来说,一个看起来普普通通的登录框,可能藏了三种完全不同的考法:第一种就是纯弱口令,字典里有就出;第二种是密码虽然弱,但服务端对用户名和密码分别返回不同提示,比如“用户名不存在”和“密码错误”,这时候你不需要暴力破解密码,先把用户名枚举出来就赢了一大半;第三种是整个登录逻辑有缺陷,密码参数压根没参与校验,你随便填个密码都能过。
所以我的习惯是:拿到爆破题,先别开Intruder,先手动拿Burp抓一次包,仔细看请求参数、响应内容、有没有奇怪的头,再决定下一步。这个习惯让我少跑了很多冤枉字典。
1.2 入门爆破题的三种常见隐藏逻辑
我刷入门题刷多了之后,发现所谓“爆破”基本可以归纳成三种隐藏逻辑,你可以在做题时照着这个思路去套。
第一种是“弱口令即答案”。出题人把密码设成admin、123456、password这类常见值,然后故意不告诉你,让你用字典去试。这种题最单纯,但坑在于它可能在某个请求头里加了一个自定义字段,或者在表单里藏了一个默认值,你没注意到就会一直失败。
第二种是“条件差异暴露信息”。服务端逻辑写得不严谨,比如登录失败时,对“用户不存在”和“密码错误”返回两套不同的响应文案。这种题考的其实是信息收集和差异比对,而不是真正的穷举。你只需要把常见用户名跑一遍,通过响应差异找到存在的用户,然后再针对这个用户枚举密码,工作量直接小一个数量级。
第三种是“校验参数可绕过”。最常见的就是验证码只在页面前端做了校验,或者验证码参数根本没传到后端;也有的是token参数固定不变,甚至删掉token请求照样成功。这类题表面看需要爆破,实际考的是你有没有认真看请求包和响应包。逻辑一旦被你识破,甚至不需要跑字典,手改一个包就能出结果。
1.3 为什么爆破题适合Web入门阶段练手
说实话,爆破专题放在入门阶段是有道理的。它不像注入、反序列化那样需要大量底层知识铺垫,你只要会用Burp抓包、能看懂HTTP请求和响应,就能动手做。而恰恰是这个过程,能帮你快速建立起一个非常重要的思维闭环:抓包、改包、看响应、判断结果。
这个闭环几乎是所有Web题的基础能力。刷完爆破题之后,你再看别的题目,至少知道“登录框不一定只是登录框”“响应包里的每个字段都有可能是信号”。所以别小看爆破专题,它不只是让你学会点Intruder的按钮,而是在帮你建立Web题最基本的分析习惯。
2. 工具准备:Burp Suite Intruder 的四种攻击模式怎么选
2.1 为什么首选Burp Intruder而不是一把梭Python
入门阶段我强烈推荐先把Burp Intruder用熟,而不是一上来就写Python脚本。原因很简单:Intruder把“导入字典、标记参数、跑请求、看响应”整个流程做成了可视化操作,前后对比非常直观。你用Python的话,光是处理会话、编码、请求头、响应过滤就要写一大堆代码,如果某个地方写错了还不好排查,很容易把精力耗在调试脚本上,而不是题目本身。
等把Intruder的套路玩明白了,再上手Python脚本会轻松很多。因为那时候你已经清楚“我需要循环替换哪个参数、响应里什么样的特征代表成功”,写脚本就只是把工具里的逻辑翻译成代码而已。而且Python有一说一,在处理动态token、复杂加解密、自定义编码这些场景时,确实比Intruder灵活得多。所以顺序应该是:先用工具建立思路,再用脚本解决进阶问题。
2.2 Sniper、Battering Ram、Pitchfork、Cluster Bomb 的实际适用场景
Intruder的Attack Type有四种,很多人从来只用Sniper,遇到需要多参数组合的题就懵了。我直接说结论,怎么选其实只看一件事:你有几组需要枚举的数据,它们之间是什么关系。
Sniper(狙击手)是单payload模式。你只标记一个位置,用一个字典去跑。适合枚举密码、枚举用户名、枚举目录名这种场景。注意如果你标记了两个位置,它也只会一个一个轮流跑,不是同时替换两个位置,这个细节经常有人搞混。
Battering Ram(撞锤)是同一个payload同时替换多个位置。适合那种多个参数取值必须一致的场景,比如用户名和密码都是同一个值,或者请求里有两个字段需要保持同步变化。
Pitchfork(草叉)是多组payload按行并行。它要求每个字典的行数一致,第一组的第一行配第二组的第一行,第一组的第二行配第二组的第二行。适合“用户名+密码”的组合枚举,前提是你已经整理好了一一对应的账号密码列表,而不是两堆独立字典交叉匹配。
Cluster Bomb(集束炸弹)是笛卡尔积。它会拿第一组字典的每一行,分别去配第二组字典的所有行,产生的请求数量是两组字典行数相乘。适合你既不知道用户名也不知道密码,只能从两组字典里交叉试的情况。但代价是请求量爆炸,比如100个用户名乘1000个密码就是10万次请求,做这道题前先想想适不适合。
为了方便你记忆,我整理了下面这个表:
| 攻击模式 | payload组数 | 组合逻辑 | 典型场景 |
|---|---|---|---|
| Sniper | 1 | 逐个替换 | 单个参数枚举 |
| Battering Ram | 1,但替换多个位置 | 同值替换 | 账号密码相同 |
| Pitchfork | 多组 | 按行一一对应 | 已知账号密码对应关系 |
| Cluster Bomb | 多组 | 笛卡尔积 | 完全未知的组合枚举 |
2.3 使用Intruder前必须确认的三件事
工具配置不难,但有几个细节搞错了会浪费大量时间。
第一,确认请求包完整。有些登录接口需要特定的Cookie、Referer或者Content-Type,如果直接抓包后丢进Intruder,可能会因为缺少某个请求头而全部失败。我建议在Proxy History里找到那条登录请求,右键Send to Intruder,不要自己手敲请求包。
第二,确认变量标记的边界。双击选中参数值时要精确,比如password=123456,只需要标记123456这六个字符,不要把password=也框进去。如果框错了,服务端收到的是password=123456这种畸形数据,你跑一整天也不会有结果。
第三,确认线程数。别一上来就开50个线程,很多入门靶场都有简单防护,跑太快直接给你返回429或者封IP,后面什么都做不了。一般先从1到5个线程开始,跑一个小字典确认流程能通,再慢慢加。速度不是爆破题的核心,稳定才是。
3. 实战场景拆解:从登录表单到token验证
3.1 场景一:最朴素的账号密码枚举
先讲最常规的登录爆破。假设你抓到的登录请求长这样:
POST /login HTTP/1.1 Host: target Content-Type: application/x-www-form-urlencoded username=admin&password=123456这种题的正解流程是:先把payload标记在password=后面,加载一个常见弱口令字典,用Sniper模式跑一遍,然后重点看响应状态码和长度。手动先发一次错误密码请求,记住响应长度是多少,跑完后凡是长度跟基线不一样的,基本都是重点观察对象。
如果跑完所有密码都没看到差异,那就要回头想是不是用户名不是admin。有些题故意把用户名藏在一个备注里,或者要你先通过用户名枚举找出存在的账号,再回来爆破密码。别死磕一个点,多换几个思路。
3.2 场景二:验证码形同虚设的登录接口
入门爆破题特别喜欢在验证码上做文章。你以为有验证码就不能爆破了,但实际上很多靶场的验证码只是前端画了个图,后端根本没校验,或者校验逻辑只在某个本地JS函数里。
判断方法很简单:抓登录请求,看提交的参数里有没有验证码字段。如果页面显示验证码,但请求包里压根没这个参数,那说明验证码就是个摆设,直接忽略就行。如果请求包里有captcha参数,你随意填一个值,响应里如果只提示“用户名或密码错误”而没提示“验证码错误”,那同样说明它没参与真正的认证逻辑。
这种题真正要爆破的依然是密码,不是验证码。千万别傻到去搞OCR识别验证码,那就完全跑偏了。这类题隐藏的逻辑本质是:你以为有两道锁,其实第二把锁是塑料做的,掰开就行。
3.3 场景三:token参与校验时怎么爆破
稍微进阶一点,有些题会在登录逻辑里加入token参数,每次访问登录页会返回一个随机token,提交登录时必须带上。这类题如果用Intruder直接跑,大概率全军覆没,因为token已经过期了。
面对这种情况,入门阶段更多考的其实是“你有没有发现token能删掉”。很多靶场虽然生成了token,但后端代码压根没校验,你试着把token参数从请求里去掉,发现照样能登录,那token就只是个心里安慰。真正的隐藏逻辑就又回到了“参数是否参与校验”上。
如果删掉token确实会报错,那我会选择用Python脚本:先请求登录页提取token,再带着新token去提交密码,循环这个过程。核心代码不复杂,就是requests加正则提取:
import requests import re url = "http://target/login" data = {"username": "admin", "password": "guess", "token": ""} for pwd in ["admin", "123456", "password"]: resp = requests.get(url) token = re.search(r'name="token" value="(.*?)"', resp.text).group(1) data["token"] = token data["password"] = pwd r = requests.post(url, data=data) if "success" in r.text: print(pwd) break当然这只是个示意,实际提取规则要看你抓到的HTML结构。重点在于思路:动态参数不能靠固定包硬跑,要么找到它的规律,要么让它每次请求都重新获取。
3.4 场景四:靠状态码和响应内容区分的题目
还有一些题,爆破的结果不是返回到页面正文里,而是藏在状态码或者响应头里。比如密码正确时返回302跳转到首页,密码错误时返回200并显示错误信息;又比如正确时会set一个Cookie,错误时则没有。
这种题交给Intruder跑,不要只看最后一条,要学会用排序和过滤。跑完之后点击Status列或者Length列排序,异常值一眼就能看出来。如果响应头里的Set-Cookie算是成功标志,那就在Columns里把Response Header那部分展开来看,耐心一点,答案就是那个和别人不一样的包。
4. 响应分析的判断逻辑:别被200迷惑,也别放过302
4.1 状态码不是唯一标准
刚开始刷题的人有个通病:只盯着状态码200看,以为返回200就是成功。其实在爆破场景里,200恰恰是最大的干扰项。错误密码返回200,正确密码可能也返回200,只是页面文案不同;有些靶场正确密码会返回302跳转,有些则干脆返回404来迷惑你。
我的建议是:把状态码当成参考信号之一,而不是唯一标准。每次爆破前,先手动提交一次错误密码,记录“错误基线”,也手动提交一次你觉得可能是密码的值,记录对照,然后看这两者之间到底哪些字段不同。不同点就是你的筛选依据,它可能是状态码、响应长度、返回头、Set-Cookie,甚至是响应时间。先把差异找出来,再决定怎么看Intruder的结果。
4.2 响应长度排序是最快的筛选手段
当你跑完几千条请求,最直观的筛选方式就是看Length列。大多数错误响应的内容都是同一个模版,长度完全一致。只要有一条响应长度跟其他都不一样,十有八九就是正确答案。
比如错误密码的响应长度稳定在600字节左右,突然有一条跑到800字节,那多出来的200字节大概率就是登录成功后的欢迎语或者flag信息。反过来也一样,如果正确密码返回的是一个极简的302页面,长度比所有错误响应都短,那短的那条就是目标。所以在Intruder结果页里,我第一个看的列永远是Length,其次才看Status。
4.3 用Grep-Match锁定关键回显
除了手动看长度,你还可以在Intruder的Attack Configuration里加Grep-Match选项,匹配一些你认为成功时会出现的关键词,比如“success”“flag”“welcome”“登录成功”之类。跑完之后,结果页会多出一列,直接显示每条响应是否包含这些关键词,一眼就能定位答案。
不过这里有个细节:关键词别选太泛的词,比如“error”,因为错误响应里可能全是“error”,你等于没筛。最好先随便发一个正确请求,从响应里复制一段独一无二的文本作为匹配目标。还有一种情况是flag本身就是动态的,比如只告诉你“密码为8位数字”,成功后会直接返回flag,那你就用Grep-Match匹配“flag{”,不管后面内容是什么,只要响应里出现这个前缀就是成功。
5. 字典与Payload构造:为什么你爆破失败而别人能出结果
5.1 字典不是越大越好,关键词优先
很多人解题失败,总觉得是字典不够大,于是去网上找那种几十GB的超大字典。真实情况是,入门靶场的口令大概率就在一个很小的范围里,你拿超大字典不仅慢,还容易因为请求量太大触发限制。相反,一个几百条精心整理的常见密码表往往就够了。
我自己的习惯是先准备一份“入门级弱口令表”,里面包含admin、123456、password、admin123、123456789、qwerty、000000、888888、666666、test、root这类高频弱口令,再补充一些跟题目场景相关的词,比如题面提到“生日”就加日期格式,提到“手机号”就加手机号段。先拿小范围跑通,再用大字典兜底,效率高得多。
5.2 根据题目提示“定制”你的字典
这里说的定制,是指根据题面信息生成精确的payload集合。很多爆破题会给你暗示,比如“密码是6位数字”“密码是姓名的拼音”“密码是4位小写字母”。这种题用通用字典反而低效,直接用脚本生成才是正解。
如果是6位数字,范围就是000000到999999,一百万条。有些人嫌多,但你可以先跑000000-099999这一段,因为大部分人设置六位密码时不会以0开头,这样其实可以先测一部分概率高的。生成数字字典用Python非常简单:
with open("digits_6.txt", "w") as f: for i in range(1000000): f.write(f"{i:06d}\n")如果是拼音,就把常见人名拼音和拼音加数字组合生成一版。比如题目提示“密码是管理员名字的拼音加123”,那字典核心就是zhangsan123、lisi123这种。说白了,定制字典靠的是读题和耐心,不是靠工具魔法。
5.3 参数变形与编码处理的几个细节
同一个参数值,经过大小写变化、URL编码、加前缀后缀之后,含义可能完全不一样。有些题目不会直接验证你提交的明文,而是先做一层转换,这时候你就需要用到Burp的Payload Processing。
比如你在字典里加了admin,但服务端可能把密码转成大写后再比对,那你就需要在Payload Processing里添加“Convert to uppercase”规则;又比如接口对某些特殊字符敏感,你得添加URL-encode规则。不过入门阶段这种题不算多,更常见的是你需要在payload前后加固定前缀,比如密码统一是“abc+数字”的组合,这时可以用“Add prefix”和“Add suffix”规则,不用手动改字典。
还有个小技巧:如果字典里的词都试过了没结果,可以试试在Burp的Payload Processing里加“Toggle case”规则,把每个词的大小写变体都跑一遍。有些出题人就喜欢把admin改成Admin或者ADMIN来增加一点干扰。
6. 比爆破更快的思路:先找漏洞入口再动手
6.1 翻源码、看JS、抓接口,三步快速侦察
每次拿到爆破题,我建议你先做一轮快速侦察:右键查看页面源代码,翻一翻有没有注释;把页面引用的JS文件打开看看,经常有登录逻辑写在前端;再到F12的Network面板里过一遍请求,看看有没有更多接口。这一轮侦察可能只需要两三分钟,但经常能省下跑字典的十几分钟。
我印象里有个典型的例子,页面登录框下面藏着一行注释,写着“for test: admin/admin888”,这题其实就变成了一道填空题。你甚至都不需要Intruder,手动输进去就出了。所以爆破题的答案有时候不在字典里,而在你看没看页面。
除了看注释,还要关注接口。很多登录页不止有/login一个接口,可能还有/api/debug、/init、/getflag这类隐藏接口。如果你发现某个接口直接返回了敏感信息,那爆破就更没必要了。做Web题最怕的就是“只会按部就班跑爆破”,一点信息收集意识都没有。
6.2 能绕就绕:前端校验、默认凭证、接口泄露
爆破题的“爆破”有时候只是标签,实际上的正解是绕过。比如验证码只在前端校验,后端不管,你把验证码参数直接删了就行。再比如密码虽然设置了弱口令,但你先试admin/admin、admin/123456这种默认凭证,很可能一把就过。这些思路不是偷懒,而是做题效率的体现。
当然,也要强调一下:这些技巧只在CTF靶场和自己搭的实验环境里用。放在真实系统上是违规行为,而且现实中的系统远没有这么好说话。CTF题本身就是设计出来让你找逻辑漏洞的,这跟真实世界的渗透测试完全是两码事。
6.3 从“爆破失败”反推题目设计者的意图
跑完一轮字典,没有任何一个响应出现异常,这时候该怎么办?我的建议是别急着换大字典,先停下来反推。
第一,检查请求参数名。题目可能真正接收的是passwd字段而不是password,你爆了一晚上password当然没反应。第二,检查是否缺少某个必填参数。有的登录接口除了用户名密码,还必须传一个固定的hidden字段,这个字段往往在登录页面的HTML里,你没带上就会一直登录失败。第三,考虑题目是否根本不是“爆破密码”,而是“爆破文件名”或“爆破目录”。你要用Intruder去试的东西可能不是密码,而是某个路径。
一句话,爆破失败通常不是因为运气差,而是因为思路没对齐。花两分钟检查一下请求包和目标页面,比盲目堆字典有用的多。
7. 实操中容易踩的坑与我的习惯性检查清单
7.1 四个让我白跑N次的坑
第一个坑是请求频率太高。有一段时间我跑爆破题习惯性开50个线程,结果跑了不到一百条请求,后面全部变成403。后来我学乖了,线程降到3到5个,问题立刻消失。CTF靶场虽然有防护逻辑,但不是用来拦住所有人,它只是希望你像个正常人一样发请求。
第二个坑是忘记处理Cookie。有些登录题的第一步是先访问登录页拿一个Session Cookie,你再携带这个Cookie去登录。如果你直接抓包也不带Cookie,或者Cookie已经过期,那Intruder里所有请求都进不了正常逻辑,你怎么跑都没用。
第三个坑是攻击模式选错。我见过有人把两个参数都标记了,然后用Sniper跑,结果发现每次只有一个参数在变,另一个始终保持初始值。还有用Pitchfork跑了两组长度不一样的字典,结果跑完第一组就停了。模式选错不是工具的问题,是没理解每种模式的组合逻辑,建议对照我前面那个表重新读一遍。
第四个坑是只盯着响应正文,不看响应头。有些题目的成功标志是Set-Cookie或者Location变化,正文内容反而不变。如果你只看Length和正文,就会完美错过正确答案。
7.2 我每次跑爆破前的固定检查流程
我现在跑爆破题已经形成了一套固定流程,基本不会再出现“跑完一脸懵”的情况。这套流程很简单,但每一步都绕不开:
- 抓包后先手动发一次错误请求,记录返回的状态码、长度和关键文案。
- 在浏览器里或者通过抓包,检查页面上有没有隐藏字段、注释、JS逻辑。
- 确认要爆破的参数在请求中的位置,标记准确。
- 根据题目提示选择字典:有提示就生成定制字典,没提示就先跑常见弱口令。
- 选择攻击模式,单参数用Sniper,多参数组合才考虑Cluster Bomb。
- 线程数设置在5以内,先放一个只包含几条payload的小字典验证流程能不能跑通。
- 跑完后先按Length排序,再看Status,最后用Grep-Match对敏感关键词做二次筛选。
- 如果所有结果看起来都一样,回到第一步,重新检查请求包是否少了参数,或者题目思路是不是真的需要爆破。
这套流程真正花时间的只有跑字典那一步,前面所有检查加起来不过几分钟。大多数爆破题卡住人,卡的都是前期的信息判断,而不是字典本身。
7.3 给小白的最后建议
如果让我给正在刷爆破题的人一个建议,我会说:做完一道题,别急着下一道,回头把整个流程再走一遍,想想哪些步骤是真正让你出结果的。尤其是那种你跑了很久、最后发现其实跟爆破无关的题,一定要好好复盘,因为你可能从中学到的不是工具用法,而是一种“不要被标签带偏”的审题意识。
我自己刷CTF的体会是,爆破专题是所有Web方向题目里最不吃天赋、最吃细心的一块。它不像逆向或者密码学那样需要大量数学功底,你只要养成抓包、改包、看响应的习惯,多踩几次坑之后自然就会了。字典可以慢慢积累,工具快捷键可以慢慢记忆,但“先分析后动手”这个习惯一定要从一开始就刻意练习。
希望这篇内容能帮你少走一些弯路。如果你正在刷ctfshow的Web入门爆破专题,遇到某道具体题目卡住了,不妨按我前面说的流程走一遍,大概率问题不在字典,而在你没注意到的某个参数上。