1. 爆破到底是什么,ctfshow的爆破专题在训练什么
先说说我自己的感受。如果你玩过几道ctfshow的web入门题,你大概已经发现了,爆破这个专题放在web入门阶段,位置相当巧妙:它不要求你有多深的代码审计功底,也不会让你拿着一堆看不懂的字节流发呆,它本质上是让你学会跟服务器"对话"——通过反复的、有策略的请求,把服务器藏在代码逻辑里的漏洞给"问"出来。
很多新手第一次听到"爆破",会觉得这是一个纯体力活,拿着burpsuite挂上字典跑就完事了。这么想就错了。爆破在CTF里其实是最讲"性价比"的一种手法:什么情况下才值得爆破?答案永远是"枚举空间足够小,且结果可以被自动判定"。服务器端没有限速、没有锁定机制、没有有效校验,这时候你才用得上爆破;如果对方有WAF、有图形验证码、有高频封禁,那你还在傻乎乎地跑大字典,只会把自己跑进小黑屋。ctfshow的爆破专题题目,恰恰把这几类"该爆破"和"看似该爆破但其实要另想办法"的场景都覆盖了,这是它作为入门训练最值钱的地方。
再说得直白一点,爆破题训练的是三件事:第一,抓包和分析请求的能力;第二,选择合适payload和字典的能力;第三,确定"成功信号"的能力。最后这一条经常被忽略——很多人跑了半天,其实flag早就出现在响应包里了,但他盯着状态码看,硬是没认出来。所以这篇文章我不打算只教你怎么点按钮,而是想带着你把爆破的完整链路捋顺:从分析请求包开始,到配置工具,到写脚本,到判断结果,最后再说说那些用血泪换来的避坑经验。
对于刚准备入门CTF Web的新人,这个专题也是性价比最高的起点之一。因为爆破牵扯到的知识点不会太深,但覆盖面广:HTTP协议、编码方式、Cookie机制、验证码逻辑、甚至一点点的Python脚本能力,全都能在这里练到。你不需要先啃完一整本HTTP权威指南,只需要开着burpsuite,跟着题目一步一步看请求和响应,很多概念自然就通了。
2. 爆破题的常见目标拆解:口令、验证码、token、cookie
2.1 口令爆破:最经典的弱口令与HTTP认证
口令爆破是Web世界里最常见的爆破场景。你在ctfshow爆破专题里遇到的第一批题目,大概率就是从登录框开始的:一个用户名输入框,一个密码输入框,点击登录,POST请求发出去,服务器返回"用户名或密码错误"。
这类题目的漏洞点通常不在加密,而在"没有任何防爆破机制"。没有图形验证码,没有登录失败次数锁定,没有连续请求限制,于是攻击者可以无限次地猜测口令。这时候爆破就变成了一个纯粹的穷举问题:把字典里的密码一个一个试过去。
实操上,你需要先在burpsuite里抓到这个登录请求,看清楚POST参数名。比如可能是username=admin&password=123456这种,也可能像某些题目那样参数名做了混淆,比如name=xxx&pwd=yyy,甚至是用JSON格式提交的{"username":"admin","password":"admin123"}。参数名搞对了,爆破就成功了一半。
这里有个新手容易踩的坑:参数位置选错。有时候你要爆破的字段不只一个,比如用户名和密码都要猜,这时候你需要把Intruder模块的Attack Type切换成Cluster bomb,在username和password两个值上分别标记变量。如果你用Sniper模式只标了一个变量,那等于一次只能试一个字段,另一个字段永远是固定值,自然什么都爆不出来。Sniper和Cluster bomb的区别,一句话总结就是:Sniper适合"多个候选值依次替换一个位置",Cluster bomb适合"多个位置组合遍历"。
除了常规的POST表单登录,HTTP Basic认证也是口令爆破的常客。ctfshow爆破专题里有一道典型题,响应头里出现了WWW-Authenticate: Basic realm=...,浏览器弹出一个原生的用户名密码输入框。这种认证的原理是把用户名:密码用Base64编码后放到Authorization请求头里,格式是Authorization: Basic base64(user:pass)。
爆破这种题目有两种思路:
- 在burpsuite里对Authorization头的值标记变量,payload类型选Custom iterator,让burpsuite自动生成
用户名:密码组合后做Base64编码——实际操作比较繁琐; - 更推荐的方式:写Python脚本,把用户名和密码都读进来,命令行里用
base64.b64encode编码后拼接请求头,循环发送请求。几行代码就能搞定。
我个人的经验是,在ctfshow这类靶场上遇到Basic认证,不要急着用Intruder硬跑,因为每次请求都要重新编码,脚本处理的效率远高于GUI操作。而且脚本能方便地做二次判断——比如响应里出现了"flag"字样就停下来并打印当前请求信息,这在跑大字典时省事得多。
2.2 验证码绕过:一次性校验、参数可控、可预测
验证码爆破是ctfshow爆破专题里比较有意思的一类题目。表面上登录框带着一个图片验证码,让你觉得"这不是没法爆了吗",但仔细一测,发现验证码压根没起任何作用。
常见的验证码缺陷有三种,我分别说一下,这都属于"实战中你会反复遇到"的类型:
第一种是验证码只校验一次、且校验过后可以复用。你随便输一个错误验证码,点击登录,服务器返回"验证码错误";但如果你抓包,把验证码参数改成一次成功请求里用过的某个值,再配合正确的用户名密码,就能登录成功。这类题目的核心是:验证码的校验状态在服务端没有正确更新,或者校验逻辑放在了"用户名密码正确之后"才做——一旦登录成功,验证码标记就失效了。
第二种是验证码参数可控、可绕过。有的题目验证码校验逻辑是"如果验证码参数为空则跳过验证",或者"如果验证码参数是一个特定值就放行",再或者验证码值根本没存session,而是藏在某个前端JS代码里。拿到源码稍微审计一下就能发现。
第三种是验证码有效期太长、且可预测。有些验证码是4位数字、存了session、有效期内无限次校验通过,那么你完全可以忽略图片识别,直接对4位数字做0到9999的枚举爆破。服务器根本不会因为你试的次数多而更换验证码。
验证码类题目的一个通用测试技巧:先不提交验证码参数,直接看看响应是不是和带了验证码参数时一样。如果一样,说明服务端根本没做校验,那你可以把验证码参数删掉,专心爆破用户名和密码。如果响应不一样,再考虑固定一个历史有效验证码值来复用。这个"删参数对比响应"的思路,在ctfshow爆破专题里屡试不爽,也是我在真实授权测试中排查登录接口时最先做的动作。
2.3 token与时间戳爆破:随机数不够随机
有CTF经验的师傅应该都知道,token类题目玩的是"代码审计 + 爆破"的组合拳。ctfshow爆破专题里token型题目的经典套路是这样的:登录时需要提交一个token参数,这个token不是随机的,而是根据某个可预测的规则生成的,比如md5(时间戳)、md5(用户名+固定字符串),或者更简单的:token本身就存在响应里的某个字段中,你只需要把它动态取出来,下一步请求时带上即可。
很多新手看到"token"就开始慌,觉得token这种东西没法爆破。其实完全相反:凡是按规则生成的token,比随机密码更容易搞定。因为密码你还是不知道取值范围,token的生成规则一旦被你弄明白了,枚举空间可能只有几万个甚至几百个。
在处理这类题目时,我习惯的流程是:
- 打开开发者工具看源码(F12),或者直接看题目是否贴出了部分PHP/Python源码;
- 在源码里找token相关的逻辑,比如
time()、rand()、mt_rand()、md5、substr这类关键词; - 确认token的生成规则后,写一个脚本同步生成token,替换到你爆破请求的token字段里。
这里有个重要的实操心得:token的时效性往往很短。如果你用burpsuite的Intruder跑,它不会自动帮你同步更新token,你可能跑了几百次请求,token字段全部用的是同一个值,服务器在第几次请求之后就开始拒绝你了。这种场景下纯GUI工具反而不如写脚本灵活——脚本里的token生成函数可以做到每请求一次就重新算一次,完全模拟合法客户端的逻辑。所以我一直建议,玩到token类爆破题的时候,尝试动手写Python脚本,宁可多花半小时,也不要拿Intruder硬刚。
2.4 cookie字段爆破:会话信息的越权遍历
最后一类常见的爆破对象是cookie。Cookie里保存的某些字段如果设计得不够安全,就变成了你的"身份凭证",且这个凭证是可以被枚举遍历的。
ctfshow爆破专题里有一道题,登录成功后服务器下发一个cookie,里面有一个字段值类似user=0或者vip=0。你尝试手动把0改成1再访问一个需要管理员权限的页面,就发现权限验证通过了。这种漏洞严格来说不算爆破,而是逻辑漏洞中的"水平越权"或"垂直越权"。但有时候这个字段值不是简单改一个数能搞定的,比如它经过某种编码或混淆,此时就需要爆破出正确的cookie值。
cookie类爆破的关键是搞清楚cookie值的生成规则。有些题目直接用自增数字作为cookie里的标识符,你只要遍历1到1000就能撞出管理员;也有的题目用md5(uid)或者固定盐值拼出来的hash,这时候你第一反应应该是去源码里找生成这个cookie的函数,而不是盲目爆。
我在做这类题目时,习惯先把响应头里的Set-Cookie字段和请求头里的Cookie字段全部看一遍,用burpsuite的Repeater手动改几个值试试响应差异。如果改一个值就出现明显变化,说明服务端对cookie值的校验很弱,这种题往往不需要大规模爆破,手工就能搞定。
四类爆破目标的对比
| 爆破对象 | 典型漏洞成因 | 判断要点 | 推荐工具 |
|---|---|---|---|
| 口令(POST/HTTP Basic) | 无限速、无锁定、弱口令 | POST参数或Authorization头,响应差异明显 | Burp Intruder / Python脚本 |
| 验证码 | 校验未生效、可复用、可预测 | 删除验证码参数观察响应变化 | Burp Repeater + 脚本 |
| token | 生成规则可逆、可预测 | 源码审计发现生成规律 | Python脚本 |
| cookie字段 | 弱会话标识、可枚举字段 | Set-Cookie值简单、改值后响应不同 | Repeater手工 + 脚本 |
3. 实操全流程:从配置burpsuite到拿到flag
3.1 环境准备:代理、浏览器、证书一次配齐
爆破的第一步不是开burpsuite,而是先保证你能拿到完整的请求包。我见过太多新手在"抓包"环节就已经卡住了,其实这个环节十分钟内就能搞定。
工具准备其实就三样:一个浏览器(Chrome或Firefox都行)、一个burpsuite(社区版完全够用,ctfshow的题目用不到专业版功能)、以及一个可用的靶场账号。我第一次跑ctfshow爆破题时用的就是burpsuite社区版,你连破解的需求都不会有。
配代理的步骤我捋一遍:
- 打开burpsuite,切到Proxy标签页,确认Options里面的Proxy Listeners列表里有一条
127.0.0.1:8080的记录。如果没有,自己Add一条,绑定地址写127.0.0.1,端口8080; - 浏览器设置里配置代理:HTTP代理指向127.0.0.1,端口8080;
- 浏览器访问
http://burp,下载CA证书并安装到系统信任列表。这一步是为了抓HTTPS流量,ctfshow大部分题目都是HTTP,但如果某些题目用了HTTPS,你不装证书就只能看到无法解析的加密报文; - 装完证书回到burpsuite的Proxy Intercept标签页,确认Intercept按钮不是亮着的,保持关闭状态,这样流量会直接经过但不拦截,方便你在HTTP history里翻请求记录。
证书安装这块我提醒一句:安装证书时一定要选择"受信任的根证书颁发机构",而不是随意导入。有些新手装完证书后发现浏览器仍然报证书错误,多数是因为导入位置选错了。安装完记得重启浏览器,让证书生效。
3.2 抓包定位:先看请求长什么样
环境准备好之后,打开ctfshow的爆破专题第一道题,在登录框里随便输入一个用户名和密码,点击登录。这时候切到burpsuite的HTTP history,找到刚才那个POST请求。
你要学会读这个请求里的几样东西:
- 请求行:
POST /login.php HTTP/1.1,说明往login.php提交数据; - 请求头:
Content-Type: application/x-www-form-urlencoded,说明表单格式是普通的URL编码;如果是application/json,那你爆破时要注意payload的写法; - 请求体:
username=admin&password=123456,这是你的爆破变量所在地; - 响应体:找一下你提交错误口令后服务器返回的内容,比如"用户名或密码错误"这类的提示,注意它的状态码是200还是302。
拿到请求之后,先把请求发送到Repeater(右键Send to Repeater),手动改几个密码再点Send,观察响应变化。这一步的目的是确认爆破的可行性:如果连续发10次请求,服务器每次都照样返回错误信息,没有验证码校验,没有锁定提示,那就可以放心开爆了。如果第3次请求后突然返回"try again later"之类的内容,说明服务器有频率限制,你需要在爆破策略里加延迟。
3.3 Intruder配置:标记两个坑位,选对字典
确认请求没问题后,右键Send to Intruder。Intruder界面有四个标签页,重点是前三个:Target、Positions、Payloads。
Target页保持默认,攻击目标已经自动带出来了。Position页里,你需要手动把要爆破的参数值选中,点Add §标记变量。比如请求体是username=admin&password=123456,我把123456选中加§,变成username=admin&password=§123456§,表示这里是要遍历的变量。攻击类型保持在Sniper,因为我们只爆破一个密码字段(用户名已知是admin)。
如果用户名也要爆,那就把admin也选中标记,攻击类型切换成Cluster bomb。
Payloads页是关键。在Payload Options的Simple list里,你可以手动往列表里输入几个常用密码,也可以点Load从一个字典文件里导入。ctfshow爆破专题有些题目会直接给你一个候选密码集合,比如题目描述里放了一个链接,里面是几百个弱口令。这种情况直接用题目给的字典就行;如果没有提供,我一般用网上公开的常用弱口令字典,几百条到几万条不等。
选好字典后,看右下角的Resource pool设置。社区版默认有一个线程池,你可以把Maximum concurrent requests调成10到30。新手不要一上来就调500,很多题目服务器根本扛不住,而且会把你的行为变成明显的攻击特征。一个不严谨但实用的经验是:先用20个线程跑一圈小字典,看看响应情况,再决定是否加大规模。
设置完毕后,点右上角Start Attack,等待结果。弹窗里每一行代表一次请求,对应各个payload。你要关注的列是Status和Length:状态码出现异常值(比如200变成302跳转)、响应长度突然和大多数请求不同,这两者都意味着可能爆破成功了。
3.4 用Python脚本爆破:比GUI更灵活的第二方案
在ctfshow爆破专题里,纯Intruder能解决的题目大概占一半左右;剩下的一半,要么是token需要动态同步更新,要么是Basic认证需要编码,要么是登录请求里有需要先获取的隐藏字段。这些场景下,我建议你直接写Python脚本。
一个最基础的POST登录爆破脚本,结构大概是这样的:
import requests url = "http://target/login.php" data = { "username": "admin", "password": "123456" } with open("passwords.txt", "r", encoding="utf-8") as f: passwords = f.read().splitlines() for pwd in passwords: data["password"] = pwd resp = requests.post(url, data=data, timeout=5) if resp.status_code == 302 or "flag" in resp.text or len(resp.text) != 1000: print(f"[+] 命中: {pwd}, 状态码: {resp.status_code}, 响应长度: {len(resp.text)}") print(resp.text[:500]) break这个脚本的思路是:把密码字典逐行读进来,每次替换data里的password字段发送请求,然后用resp.status_code、resp.text的长度、响应中是否出现flag关键字来做命中判定。只要服务器做出了不一样的响应,就直接打印并停止循环。
实战中你往往需要根据题目调整判断条件。比如有的题目登录成功后会跳转到index.php,那么状态码302就是命中信号;有的题目登录失败和登录成功返回的页面长度差几十个字节,那就把长度阈值设进去。
另外,如果你的Linux环境没有requests库,先执行pip install requests装一下。如果你要在Windows上跑中文路径的字典文件,记得encoding那里用"gbk",否则读文件会乱码——我自己就在Windows上踩过这个坑,读出来的密码全是乱码,爆了一整轮才发现。
3.5 命中判定:别把flag漏在脚下
爆破成功之后,怎么确认?这个环节我单独拿出来讲,因为有一半的新手不是爆不出来,而是爆出来了没发现。
判定命中的三个主要信号分别是:
- 状态码变化:最常见的形式是登录成功后302跳转,失败时404或200原地刷新;
- 响应长度变化:这个在Intruder结果列表里最直观。正常失败请求的响应长度通常是固定的(比如1200字节),一旦某个密码触发了不同的逻辑分支,响应内容多了或少了,长度就变了。你在Intruder结果页面按Length列排序,看谁的长度和别人不一样;
- 响应内容特征:比如成功响应里包含
flag{、welcome、index.php、用户名或密码正确等字样。这个需要在Intruder的Settings里加一个Grep-Match,输入flag等关键词,burpsuite会在结果里自动标记命中。
经验之谈:跑完之后不要只看前几行结果,直接把Length列点一下排序,把长度异常的行单独拎出来看响应体。很多情况下,正确密码产生的响应只比错误密码长几十个字节,肉眼不容易看出来,但排序一到,差异立刻显现。
4. 常见问题与排查技巧实录
4.1 跑了半天一个都没中,怎么办
这种情况我遇到太多了,先说结论:90%的情况不是你字典不好,而是你配置出了问题。
逐一排查:
第一,确认变量位置。回到Intruder的Positions页,仔细看标记是否只圈住了你要爆破的值。如果§标的位置偏了一个字符,比如把password=§123456§&标成了password=§123456&,那等于把参数名后半部分也当成变量了,永远不可能命中。
第二,确认请求头是否正确。有些登录接口要先带一个Cookie头或者Authorization头才能访问,如果你抓的请求里带了这些头,但Intruder跑的时候莫名其妙丢了(一般是内置的Header处理设置问题),会导致所有请求都被拒绝。对比一下原始请求和Intruder里的请求头,逐一核对。
第三,确认是否有动态字段需要处理。服务器可能在登录页面里埋了一个csrf_token隐藏字段,每次刷新页面都会变。你直接拿旧的csrf_token去爆破,第一次请求就失败了,后面全无效。这种情况你需要先写脚本在每次请求前GET一次页面,把token提取出来再POST。本质上这已经属于用脚本做"会话保持"的爆破。
第四,确认响应判定条件。状态码200未必是失败,302也未必是成功,得看具体逻辑。有的题目登录失败时状态码就是200且返回登录页面,登录成功时会重定向,但302不一定出现在每一个题里。把其中一条成功响应的完整内容抓出来,看看到底有什么特征是失败响应里没有的。
4.2 线程开太高,被封了或者被强制下线
ctfshow这类靶场为了保护服务器,有时会对高频请求做了限制。你如果一口气跑到几个小时的进程里没有限制地发请求,可能触发服务器的防爆破策略,之后所有请求都会返回同一个提示。
处理方式很简单:把线程降到5以下,或者让脚本在每次请求之间sleep 0.1秒到0.5秒。Python脚本里加一行time.sleep(0.2)不会让整体速度慢太多,但能大大降低触发防护的可能性。
另外一个常见问题是:爆破的过程中如果服务器返回了302,requests默认会跟随跳转,跳到登录成功后的页面,这个过程可能会额外消耗时间甚至触发一些异常。建议在requests里设置allow_redirects=False,只关心第一次响应结果,需要跳转的话再手动GET目标页面。
4.3 爆破结果全是一样的响应,怎么快速定位问题
这种情况通常是请求包本身有问题,比如提交的数据格式错了。我整理了一个排查顺序表,你可以照着检查:
| 现象 | 可能原因 | 下一步操作 |
|---|---|---|
| 所有请求响应完全一致 | 变量位置没标对、payload没实际替换 | 检查Positions标记 |
| 所有请求都是401/403 | 缺少必要的认证头或Cookie | 补全请求头 |
| 响应里有验证码错误提示 | 验证码参数固定、但服务端要求动态值 | 处理验证码逻辑或用脚本同步 |
| 状态码全302但内容相同 | 302可能是统一跳转到某错误页 | 追踪Location头,看跳转后内容 |
| 少量请求长度异常 | 字典里存在类似格式的干扰项 | 查异常响应文本,确认是否为目标内容 |
排错的一个核心技巧是:把Intruder的请求抓到Repeater里,手动改payload发送一次。如果手动发送能得到不同结果,那说明Intruder里跑出来的"全一样"一定是你配置层面的问题;如果手动发送也得不到不同结果,那就要考虑题目的正常入口是不是变了,比如服务端已经改用了别的校验方式。
4.4 一个必须反复强调的底线:授权与靶场边界
写到这里,我要专门花一段篇幅说一件非常重要的事。爆破这个技术本身没有错,但它的杀伤力取决于用在什么地方。ctfshow是一个合法的在线靶场平台,它的爆破专题就是专门留给安全爱好者练习的——有明确的练习目的、有平台授权、有隔离环境,在这里怎么折腾都行。
但同样的爆破手法,如果用在未经授权的真实系统上,性质就完全不同了。私自在别人的网站上进行口令爆破,属于违法攻击行为,这一点没有任何灰色地带。所以我建议所有读者在做题时养成一个习惯:每一次爆破操作前,问自己一句"我对这个目标是否有明确的权限?"答案如果是"靶场""CTF比赛""自己的测试环境",那可以放手去练;答案如果是否定的,就到此为止。
这也是为什么我一直推荐通过ctfshow这类平台来学习爆破的原因:它给你提供了足够真实的Web环境,让你能把"技术动作"练扎实,同时又把"法律边界"画得清清楚楚。真正的安全能力,是既懂技术,又懂边界。
5. 我的个人体会与后续扩展方向
爆破专题做完之后,我的一个很明显的感觉是:做题时对"请求包"的敏感度会大幅提升。以前看到一长串HTTP头部就直接跳过,现在会习惯性地看一眼Cookie、Authorization、X-Forwarded-For这些字段,遇到登录页面也会下意识想一下"这里有没有限速"。
这种敏感度,恰恰是Web安全的入场券。后面你再接触SQL注入、XSS、文件上传时,会发现所有攻击手法的第一步都是同样的动作——抓包、看参数、理解服务端逻辑。爆破专题像是一个微缩模型,把Web攻击最通用的操作流程浓缩在里面了,跑完一遍,你至少不会再对burpsuite感到陌生。
如果你做完ctfshow爆破专题还想继续深入,我有两个建议。第一,把爆破脚本的灵活性再拔高一层,试着用requests写一个支持多线程的爆破框架雏形,比如用concurrent.futures做并发请求,遇到命中就自动终止所有线程。这个练习能让你把并发编程和HTTP请求结合起来,后续写复杂工具时很有用。第二,往Web漏洞链路的方向延伸,多关注登录接口之外的漏洞——验证码识别方案可以往OCR方向走,token生成规则可以往伪随机数审计方向走,cookie越权可以往会话安全问题走。
最后,我在实际做题过程中最深的体会是:爆破题花的时间常常不在"跑"上,而在"分析"上。分析清楚题目想让你利用哪个逻辑缺陷、正确的payload长什么样、成功响应里有什么特征,这三件事做扎实了,爆破跑起来往往几秒钟就出结果。反而是一上来就挂字典狂跑的人,大概率跑个大半个小时颗粒无收。希望这篇文章能帮你把"先分析、后动手"的习惯培养起来,这对你接下来走Web安全这条路,会是一笔持续复利的投资。