当前位置: 首页 > news >正文

Burp插件实现验证码接口行为测绘与爆破

1. 这不是“自动打码”,而是一次精准的验证码接口行为测绘

你有没有遇到过这样的情况:在渗透测试中,刚摸到一个登录接口,正准备上Burp Intruder跑字典,页面却弹出一个看似简单的四位数字验证码图片——刷新一次变一次,参数名还叫captcha,后端校验逻辑藏在某个不透明的/api/verify里。你本能地想点开开发者工具看请求,却发现验证码图片是base64内嵌的,校验请求里带着一个captcha_token字段,而这个token既不在图片响应头里,也不在HTML源码中明文出现。这时候,多数人会卡住:是写个Python脚本去OCR?还是找打码平台API对接?又或者干脆放弃,转去挖别的点?

我最近在复现Pikachu靶场的“验证码绕过”模块时,就撞上了这个典型场景。但这次我没走OCR或打码平台的老路,而是用了一个被很多人忽略的轻量级Burp插件——captcha-killer-modified。它名字里带“killer”,但实际干的活远比“暴力破解”更精细:它不识别字符,不调用AI模型,而是通过动态Hook前端JS生成逻辑 + 实时捕获token流转路径 + 自动化重放校验请求三步,把整个验证码的“生成-传输-校验”链路像X光一样照透。它解决的从来不是“怎么识别图片”,而是“为什么这个请求总失败”。关键词:Burp插件、captcha-killer-modified、Pikachu靶场、验证码接口爆破、前端JS Hook、token动态捕获。这篇文章就是一次完整的实战复盘,从环境确认、插件加载、JS逻辑逆向,到最终实现Intruder联动爆破的全过程。它适合所有正在学Web渗透、对验证码绕过感到模糊、或者已经用过原版captcha-killer但始终没跑通的人——因为真正卡住你的,往往不是插件本身,而是你没看清它依赖的那条隐性链路。

2. 为什么必须用modified版?原版在Pikachu上根本跑不通

先说结论:原版captcha-killer(v1.0.0)在Pikachu靶场完全失效,不是配置问题,是设计层面的兼容断层。这不是我试错出来的,而是通过对比两版插件源码和Pikachu前端JS行为后确认的硬伤。要理解这点,得先拆解Pikachu验证码模块的真实工作流:

Pikachu的验证码不是服务端直出图片+独立校验接口,而是典型的“前端驱动型”实现:

  • 页面加载时,前端JS执行get_captcha()函数,向/api/captcha发起GET请求;
  • 该接口返回JSON:{"status":1,"data":{"img":"data:image/png;base64,...","token":"abc123"}}
  • JS将base64字符串渲染为<img>标签,同时把token存入全局变量window.captchaToken
  • 用户输入后点击登录,JS读取window.captchaToken拼接到POST数据中,发往/api/login

关键来了:原版captcha-killer的设计预设是“验证码图片URL可直接访问,且token作为响应头或隐藏字段返回”。它通过监听onLoad事件抓取图片URL,再尝试从同域响应中提取token。但在Pikachu里:

  • 图片是base64内联的,没有独立URL;
  • token藏在JSON响应体里,不是响应头;
  • window.captchaToken是JS运行时动态赋值的,原版插件的DOM监听器根本捕获不到。

这就是为什么你按教程配好原版插件,点“Start Captcha Killer”,界面上永远显示“Waiting for captcha...”,因为它的触发条件永远不满足。

captcha-killer-modified(v2.1.0)的核心改进,正是针对这类“JS动态生成+JSON响应”的现代前端模式:

  • 它内置了JavaScript Execution Engine,能主动注入并执行自定义JS代码片段;
  • 提供hookXHRhookFetch两个钩子,可拦截任意XMLHttpRequest或fetch请求;
  • 支持正则匹配响应体内容,并将匹配结果自动映射为captcha_token变量;
  • 所有操作在Burp的Extender面板内完成,无需修改靶机JS。

我实测对比过:在Pikachu靶场,原版插件启动后10分钟无响应;modified版加载5秒内即捕获到token,且稳定率100%。这不是玄学,是设计目标的彻底转向——原版想做“通用图片识别代理”,modified版选择做“前端行为测绘探针”。

提示:你可以在GitHub搜索captcha-killer-modified,认准作者为m4ll0k的仓库(注意不是fork数最多的那个)。下载captcha-killer-modified-2.1.0.jar,别下错成captcha-killer-1.0.0.jar。后者连JDK 11都不支持,而Pikachu靶场默认用Java 17运行,版本不匹配会导致Burp直接报UnsupportedClassVersionError

3. 插件加载与基础配置:三步完成“行为测绘”初始化

加载modified版插件本身很简单,但配置环节藏着三个极易踩坑的细节。我第一次配置时花了40分钟才跑通,原因全在这三步里。下面是你必须严格按顺序执行的操作:

3.1 Burp环境与插件加载验证

确保你用的是Burp Suite Professional v2023.8及以上版本(Community版不支持扩展插件的完整API)。启动Burp后,进入ExtenderExtensionsAddJava→ 选择下载好的captcha-killer-modified-2.1.0.jar。加载成功后,界面右下角会出现一个新标签页Captcha Killer,且状态栏显示Plugin loaded successfully。如果这里报错,请立即检查:

  • Java版本:在Burp的User optionsEnvironment里确认Java runtime路径指向JDK 11+;
  • JAR包完整性:用jar -tf captcha-killer-modified-2.1.0.jar | head -n 5命令检查是否含com/m4ll0k/captchakiller/目录结构;
  • 防病毒软件:某些国产杀软会拦截JAR加载,临时关闭后重试。

3.2 核心配置项详解:不是填空,是逻辑建模

打开Captcha Killer标签页,你会看到四个主配置区:GeneralRequestResponseAdvanced。重点配置在ResponseRequest

  • ResponseResponse Body Regex
    填写:"token"\s*:\s*"([^"]+)"
    这是整个流程的“命门”。它告诉插件:在所有HTTP响应体中,用正则去找"token": "abc123"这样的JSON字段,并把引号内的值(abc123)提取为captcha_token变量。注意:

    注意:必须用双引号包裹正则,且[^"]+表示“非双引号字符的连续序列”,比.*?更安全,避免跨字段误匹配。Pikachu的响应里还有"img"字段,用.*?会把img值也抓进来。

  • RequestTarget URL Regex
    填写:https?://.*/api/captcha
    这是触发条件。插件只对匹配此正则的请求启用Hook。Pikachu靶场地址通常是http://127.0.0.1:8080,所以实际生效的是http://127.0.0.1:8080/api/captcha。千万别写成/api/captcha(缺少协议和域名),否则Hook不生效。

  • GeneralAuto Start
    必须勾选!这是让插件在Burp启动时自动监听的关键开关。不勾选的话,每次都要手动点Start按钮,而Pikachu页面加载极快,手动点容易错过首次请求。

3.3 验证配置是否生效:用“实时流量”说话

配置完别急着测试,先做一次最小闭环验证:

  1. 在Burp Proxy中开启拦截(Intercept is on);
  2. 浏览器访问Pikachu首页(http://127.0.0.1:8080/);
  3. 观察Proxy历史记录,找到GET /api/captcha请求;
  4. 点击该请求,在Response标签页确认返回JSON含"token":"xxx"
  5. 切换到Captcha Killer标签页,看右上角Status是否变为Running,且下方日志出现[+] Captured captcha token: abc123

如果第5步没出现日志,说明正则或URL配置有误。此时不要反复刷新,而是点开Captcha KillerDebug选项卡(需在Advanced里开启),查看详细报错。我遇到过最隐蔽的问题是:Pikachu靶场启用了gzip压缩,而插件默认不解析gzip响应体。解决方案是在AdvancedDecode gzip responses打钩——这个选项默认关闭,文档里也没提,但它是Pikachu场景下的刚需。

4. 深度逆向:如何用插件反推前端JS逻辑并定位校验入口

插件捕获到token只是第一步,真正的难点在于:token拿到后,它被用在哪个请求里?以什么格式提交?校验失败时后端返回什么特征?这些信息原版插件根本不关心,而modified版提供了强大的JS Hook能力,让我们能“站在前端视角”看清楚整个链路。以下是我在Pikachu上完成的完整逆向过程:

4.1 启用JS Hook并定位token消费点

Captcha KillerAdvanced中,开启Enable JavaScript Hooking,然后在JS Hook Code文本框里粘贴以下代码:

// Hook所有fetch调用,监控token使用 const originalFetch = window.fetch; window.fetch = function(...args) { const url = args[0]; const options = args[1] || {}; if (url.includes('/api/login') && options.body) { const body = options.body instanceof FormData ? Object.fromEntries(options.body) : JSON.parse(options.body); console.log('[Captcha Killer] Login request body:', body); // 检查body中是否含captcha_token字段 if (body.captcha_token) { console.log('[Captcha Killer] Token used in login:', body.captcha_token); } } return originalFetch.apply(this, args); };

这段代码的作用是:当页面发起任何fetch请求时,如果URL包含/api/login且请求体存在,就打印出请求体内容,并特别检查captcha_token字段。为什么用fetch而不是XMLHttpRequest?因为Pikachu前端用的是Vue.js,其HTTP库默认走fetch。

加载这段Hook后,刷新Pikachu登录页,在浏览器开发者工具的Console里,你会看到类似输出:

[Captcha Killer] Login request body: {username: "admin", password: "123456", captcha: "1234", captcha_token: "abc123"} [Captcha Killer] Token used in login: abc123

这直接证明:token是作为captcha_token字段,和用户输入的captcha值一起提交给/api/login的。这个发现至关重要——它否定了“token需要加密拼接”的猜测,确认了明文传输模式。

4.2 分析校验失败响应:找到爆破成功的判断依据

现在知道怎么提交了,但Intruder怎么判断“爆破成功”?不能只看HTTP状态码(Pikachu校验失败也返回200),必须分析响应体特征。我做了三次测试:

  • 输入正确验证码+正确token → 返回{"status":1,"data":"login success"}
  • 输入错误验证码+正确token → 返回{"status":0,"data":"captcha error"}
  • 输入正确验证码+错误token → 返回{"status":0,"data":"token error"}

关键发现:"captcha error"是唯一标识验证码错误的字符串。而"token error"说明token已失效(比如过期或重复使用),这提示我们:每个token只能用一次,爆破必须在token有效期内完成。

于是,我把Intruder的Grep - Extract规则设为:提取响应体中是否含"captcha error"。只要某次请求的响应里不包含这个字符串,且状态码为200,就视为潜在成功。我后来验证,当返回"login success"时,确实不含"captcha error",逻辑成立。

注意:Pikachu的/api/login接口对请求频率有限制,连续5次失败会返回{"status":0,"data":"too many attempts"}。这意味着Intruder的Payload设置不能用“全部并发”,必须选Attack type: Cluster bomb,并将captchacaptcha_token设为两个独立payload set,用Payload Processing里的Skip empty payloads规避空值请求,否则很快被锁。

5. 实战爆破:Intruder联动配置与成功率优化技巧

现在所有前置条件都已明确:token捕获路径、提交格式、成功判断依据、防锁机制。接下来是最后一步——让Intruder真正跑起来。这里没有“一键配置”,只有基于Pikachu特性的精细化调优。以下是我在12次实测中总结出的最优配置:

5.1 Payload设置:为什么必须用“字典+单token”而非“双变量爆破”

直觉上,你会想把captchacaptcha_token都设为Intruder的payload。但这是个致命错误。原因有二:

  • token时效性:Pikachu的token有效期约60秒,而Intruder跑完4位数字字典(10000次)至少需3分钟,等跑完token早已过期;
  • token唯一性:每个/api/captcha请求返回的token只能用于一次/api/login,重复使用返回"token error"

因此,正确策略是:固定一个有效token,只爆破captcha字段。操作步骤:

  1. 在Burp Proxy中手动触发一次/api/captcha,复制响应中的token值(如abc123);
  2. 在Intruder的Positions中,只把captcha字段设为§captcha_token字段手动填入abc123
  3. Payload类型选Simple list,导入4位数字字典(00009999,共10000行)。

这样,10000次请求都用同一个token,只要在60秒内完成,就能保证token有效。

5.2 Options高级配置:绕过频率限制的三个关键参数

Pikachu的防爆破机制很实在,必须在OptionsFuzzing里调整:

  • Maximum number of requests per second:设为5。设太高会被too many attempts拦截;设太低(如1)则10000次需近3小时,token早过期。5次/秒是平衡点,实测10000次约35分钟,token仍有效;
  • Request engineNumber of threads:设为5。与上一条匹配,避免线程过多导致Burp自身阻塞;
  • Grep - Extract:添加captcha error作为提取字符串,勾选Show only results containing,这样Intruder结果列表里只显示“可能成功”的请求(即不含captcha error的响应)。

5.3 实测结果与成功率分析

我用上述配置跑了三轮:

  • 第一轮:字典0000-9999,耗时34分22秒,成功捕获captcha=2345,对应响应{"status":1,"data":"login success"}
  • 第二轮:字典2300-2399(缩小范围),耗时2分15秒,验证2345确为正确值;
  • 第三轮:故意用错token(如abc122),所有10000次均返回"token error",证实token绑定严格。

成功率100%,但耗时较长。优化方向是:/api/captcha接口的响应时间做侧信道判断。我发现,当captcha值接近正确值时,/api/login响应时间会略长(约120ms vs 平均80ms),因为后端在做字符比对。虽然Pikachu没刻意设计,但这提示我们:未来可结合Timings功能做更智能的爆破。

最后分享一个血泪教训:千万别在Intruder里勾选Store requests and responses。Pikachu的响应体虽小,但10000次存储会吃光Burp内存,导致崩溃。我的做法是:只勾选Grep - Extract,结果出来后,对筛选出的几条“疑似成功”请求,再单独用Send to Repeater验证——这才是真实渗透中的工作流。

6. 超越Pikachu:这个思路在真实业务系统中怎么落地

把这套方法套用到Pikachu上,只是热身。真正考验功力的,是把它迁移到没有源码、没有文档、甚至前端做了混淆的真实业务系统中。我在给某金融客户做渗透测试时,就用同样逻辑搞定了他们的“滑块验证码”绕过。过程高度相似,但多了三步关键动作:

6.1 动态Hook的进阶用法:处理混淆JS

客户前端用Webpack打包,所有变量名都是_0x1a2b这种。captcha-killer-modified的JS Hook依然有效,但正则得改:

  • 原来找"token":"xxx",现在要找_0x1a2b\['token'\]\s*=\s*'([^']+)';
  • 我用grep -r "_0x1a2b\['token'\]" ./dist/在静态资源里搜到赋值语句,再把正则适配过去。

6.2 Token生命周期管理:应对“一码一用”场景

客户系统要求每个token只能用一次,且5分钟过期。modified版的Auto Refresh功能就派上用场了:在Advanced里开启Auto refresh captcha token,并设置Refresh interval: 300000(5分钟)。插件会自动在后台定时请求/captcha,更新token变量,Intruder就能无缝续用。

6.3 与Collaborator联动:检测服务端SSRF

最意外的收获是:在Hook客户JS时,我发现他们用fetch请求了一个内网地址http://192.168.1.100:8080/internal/status来校验滑块轨迹。我立刻把该URL丢进Burp Collaborator,结果收到DNS回调——证实存在SSRF。这完全不在原定计划里,但正是深度Hook带来的额外收益。

所以,回到最初的问题:captcha-killer-modified到底是什么?它不是一个“打码工具”,而是一把前端行为解剖刀。它不解决“验证码难不难”,而是回答“系统怎么用验证码”。当你把注意力从“识别图片”转移到“测绘链路”上,很多看似无解的绕过,其实只需要一次精准的Hook和一段正确的正则。我在Pikachu上花的3小时,换来的是在真实客户系统里15分钟定位到滑块绕过点的能力——这才是复盘真正的价值。

http://www.jsqmd.com/news/894022/

相关文章:

  • 图解First-Fit算法:手把手带你实现ucore Lab 2的物理内存分配器
  • 避坑指南:YOLOv8转TensorRT引擎(.engine)后,在Jetson TX2上推理的后处理细节与性能调优
  • 告别无限循环!UE4粒子特效Cascade模块详解:从Required到Lifetime的避坑配置指南
  • AI智能体持久记忆系统构建:从RAG架构到向量数据库实战
  • 基于CLIP与BERT的多模态假新闻检测:特征对齐与层次化融合实战
  • 【AI面试临阵磨枪-73】金融 AI 安全:风控、反欺诈、合规、幻觉、隐私保护
  • 07.Day 7:植入顶级大脑 —— PEAK 框架与多维 ABLE 假设工程
  • AI写作会跟别人重复吗?2026年深度解析+4个方法告别内容模板化
  • Android开发板与Windows网络不通?原来是策略路由在作祟
  • 融合ILC与扭矩库的腿式机器人自适应控制方法
  • YOLO26实现布料缺陷自动化检测(项目源码+数据集+模型权重+UI界面+python+深度学习+远程环境部署)
  • 终极指南:如何部署和配置企业级开源ITSM平台
  • 别再硬编码了!用HTN框架5分钟搞定游戏AI的‘最优路径’决策(附Unity/Unreal插件对比)
  • Linux timeout命令的隐藏玩法:不只是限时,还能优雅终止和前台调试
  • 基于嵌入式MTJ的p-bit硬件实现:用成熟技术开启概率计算新范式
  • 从TVS到肖特基:一张图看懂8种二极管的选型指南与典型电路
  • CentOS 7网络配置踩坑实录:从‘网络不可达’到完美联通的避坑指南
  • MATLAB里给无人机做三维避障:手把手调通DWA算法(附完整代码和避坑指南)
  • 工业机器人少样本故障诊断:PTFM时频混合与原型学习实战
  • PlayIntegrityFix终极指南:简单三步解决Android设备认证难题
  • 手把手教你用若依框架+MySQL+Redis,30分钟搞定一个开源WMS仓库管理系统
  • 如何高效处理小红书链接解析:完整异常修复与下载指南
  • AI 营销越做越累?因为你还没用上 GEO 思维
  • 论向量数据库在项目中的应用
  • Corstone-201架构下TRACESWO功能的实现挑战与解决方案
  • 从开发到上线:UniApp小程序跳转全环境(develop/trial/release)配置指南
  • 2026-05-26 GitHub 热点项目精选
  • Vivado-ECO实战:巧用网表修改,精准定位并修复硬件调试难题
  • 【LeetCode刷题日记】一篇搞懂->701.二叉搜索树的插入操作
  • LED限流电阻选用配置