ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

captcha-killer-modified实战:验证码识别与登录爆破自动化

captcha-killer-modified实战:验证码识别与登录爆破自动化 最近在评估一个内部系统的登录接口安全性时遇到了一个绕不过去的坎验证码。虽然口令爆破本身不复杂但每次请求都要手工识别图片验证码手里的扫描工具直接变成半自动模式。后来我把验证码识别这条链路拆开接入了captcha-killer-modified才真正把登录口令爆破这条链路跑通。这篇文章就是围绕这个工具把验证码对抗的完整思路、部署细节和实战坑点都捋一遍适合正在做授权渗透测试、登录接口安全评估或者对验证码识别链路感兴趣的朋友参考。captcha-killer-modified 是安全圈里常用的验证码识别辅助工具本质上是一个 Burp Suite 插件解决的核心问题是让自动化爆破工具能够自动拿到验证码识别结果并回填到请求中。它本身不做识别而是把验证码图片提取出来交给云端打码平台或本地 OCR 引擎识别再把识别结果返回给爆破流程。这样一来登录接口的自动化测试就不再需要人工盯着图片一张张看了。1. 项目概述验证码为什么成了爆破流程里的“拦路虎”1.1 一个典型场景引发的需求先还原一下我最初遇到的状况。目标系统是一个后台登录页面用户名和口令都走 POST 请求请求体里除了账号密码之外还有一个captcha字段和关联的captchaId。当时我用 Burp Suite 的 Intruder 跑弱口令字典前两轮还正常到第三轮服务器就开始返回“验证码错误”。原因很直白验证码是和服务端会话绑定的而且是一次性的。你第一次拿到验证码图片如果不带上识别结果一起提交这个验证码就失效了下次请求必须再取一张新图、再识别一次。问题就出在这里。人工操作时识别一张验证码可能要花 1 到 3 秒而爆破一个口令字典可能要跑几千上万次请求。人工根本跟不上节奏自动化工具又拿不到验证码的识别结果整个爆破流程就卡死在“验证码识别”这一步。抛开攻击视角不谈哪怕是做安全巡检想验证弱口令问题是否存在这种验证码机制也会把测试效率拖到极低。1.2 工具定位与适用边界captcha-killer-modified 要解决的正是“验证码图片获取”和“识别结果回填”之间断掉的那一环。它不替代验证码识别服务本身而是做了三件事拦截并提取响应报文里的验证码图片、把图片转发给打码平台或本地识别服务、拿到结果后交给 Intruder 的 payload 机制回填到下一个请求。整体上是一个衔接层和调度层的角色。需要注意这个工具主要针对传统图片验证码比如四位数字、四位字母、算术式、滑块缺口识别等。如果你面对的是极验、腾讯验证码这类带有复杂行为轨迹校验的验证码单靠这个工具是不够的通常还需要配合对应的打码平台专用接口才能处理行为数据。但即便如此captcha-killer-modified 在整个流程里仍然可以作为统一入口来调度这些能力只是需要在插件里多配置几套请求模板。2. 工具原理与核心设计captcha-killer-modified 是怎么工作的2.1 整体工作流程图解画一个简单的流程来描述整个链路浏览器或测试请求访问登录页面服务端返回 HTML 页面里面包含img src/captcha?idxxx这样的验证码图片地址以及一个隐藏的captchaId字段。Burp Suite 拦截到这个响应后captcha-killer-modified 根据预设的配置从响应中提取验证码图片的 URL 或 Base64 数据。插件请求验证码图片地址拿到图片二进制数据然后按照打码平台的接口要求封装成请求发送给云端的 OCR 识别服务。打码平台返回识别文本比如8f3a插件把结果暂存在内存中。Intruder 在发送下一次登录请求时通过 payload 处理器从插件中获取这个识别结果替换到captcha字段里完成请求。整个过程中关键点在于“获取验证码”和“提交登录请求”必须保持同一个会话否则验证码与登录请求的 Cookie/Session 不匹配服务端依然会判定失败。这个在后续的实操中非常容易踩坑。2.2 为什么选择“云端识别”而不是本地 OCR很多人一听到验证码识别第一反应是训练一个本地模型来做 OCR。这种做法在对付简单数字验证码时可行比如用 ddddocr 跑本地推理速度也很快。但在实际对抗中验证码图片往往会加入干扰线、噪点、扭曲、背景杂色甚至字体不规则本地 OCR 的准确率会明显下降。一旦识别率低于 60%爆破流程里有一大半请求都会因为验证码错误被服务端拒绝整体效率反而不如人工。captcha-killer-modified 的设计思路更务实把识别这个活外包给专门的打码平台。这类平台常年处理各种验证码积累了大量样本和模型对常见干扰的鲁棒性远高于通用 OCR。单张验证码的识别价格也很低比如按次计费的平台1000 次识别可能只要几块钱。对于授权测试场景这种成本完全可接受。当然如果你明确知道自己目标站点的验证码类型比较固定、干扰很少也可以把 ddddocr 这类本地引擎接进来。captcha-killer-modified 提供了自定义请求模板的能力你可以把识别接口改成http://127.0.0.1:9898/ocr这种本地服务地址一样能跑通。两条路线各有优劣后面在配置部分我会具体展开。2.3 与“前端校验”思路的差异早期有一些“跳过验证码”的思路是尝试在前端逻辑里找到验证码校验的漏洞比如修改返回包、删除验证码参数、或者找到某个调试后门。这种思路在很多老系统里确实有效但现在的系统普遍会把验证码校验放到服务端做前端只是展示校验结果你改了前端没有任何意义。captcha-killer-modified 走的是另一条路不尝试绕过而是老老实实地把验证码识别出来作为合法参数提交。这种方法更接近真实用户的交互逻辑也更能反映系统在自动化攻击下的真实表现对安全评估来说反而更有价值。3. 部署配置与登录爆破实操从加载插件到跑通第一个请求3.1 环境准备与前置条件在开始之前先确认你的环境满足以下条件避免在配置阶段浪费无谓的时间Burp Suite建议使用 2021 年之后的版本社区版和专业版都能加载扩展。captcha-killer-modified 官方推荐的版本是 2020.12 及以上其实新版兼容性更好。Jython 或 Java 环境captcha-killer-modified 本身是 Java 写的不需要额外装 Python 环境。但 Burp 插件加载时需要确保 Java 环境变量正常。如果启动 Burp 时报错说找不到 Java先检查java -version是否能正常输出。打码平台账号注册一个支持 HTTP API 调用的打码平台获取对应的 API Key / Token。部分平台还支持本地 OCR 引擎可以留作备用。目标授权这是老生常谈但必须强调。所有验证码爆破操作必须在获得目标系统所有者明确授权的前提下进行。授权渗透测试、漏洞验证、CTF 比赛、本地靶场都属于合理场景。3.2 插件加载与打码平台配置先明确一点captcha-killer-modified 的发行方式是一个.jar文件官方仓库里可以直接下载。加载步骤很简单打开 Burp Suite进入Extender或Extensions标签页。点击Add按钮Extension Type选择Java。在Extension File里选中下载好的 captcha-killer-modified jar 包。点击Next等待下方输出窗口出现加载成功日志。加载完成后你会在 Burp 的标签栏里看到一个新的captcha-killer标签页。界面主要分几个区域请求模板配置、验证码请求定义、识别结果展示、以及和 Intruder 联动的操作按钮。我第一次用的时候最不习惯的就是这个界面信息密度比较高但其实核心只需要关注两个请求模板获取验证码的请求和识别验证码的请求。接下来配置打码平台。不同的平台 API 格式略有差异但大致的思路是一样的告诉插件“验证码图片应该通过什么 HTTP 请求发出去”以及“识别结果在响应里如何提取”。以某打码平台为例它要求你提交一个 multipart/form-data 请求字段包括api_key、file图片二进制、type验证码类型编号。captcha-killer-modified 的请求模板里支持自定义Content-Type、请求头和请求体你可以把图片二进制数据通过占位符%DATA%的方式放到请求体里。3.3 验证码接口请求模板配置这是整个使用过程中最核心的一步也是新手最容易卡住的地方。captcha-killer-modified 的流程是先模拟发送一个“获取验证码的请求”到目标站点拿到验证码图片的响应然后从这段响应中提取图片数据再发送给打码平台。所以你需要配置两个请求模板。第一个模板是“获取验证码图片”的请求。目标站点的验证码接口通常长这样GET /captcha?t123456789 HTTP/1.1 Host: target.example.com User-Agent: Mozilla/5.0 Cookie: sessionidxxxx其中t参数是时间戳或随机数通常用来防止浏览器缓存图片。这个请求的响应可能是一张 PNG 图片也可能是一个 JSON 数据包里面包含 Base64 图片。我遇到过一个比较特殊的系统验证码图片不是通过 URL 返回的而是在登录页 HTML 里直接内联了一段 Base64。这种情况你还需要先去获取登录页面从 HTML 中提取 Base64然后再把 Base64 还原成图片。captcha-killer-modified 支持这种情况只是在提取规则里要写一个正则表达式把base64,([A-Za-z0-9/])这一段抓出来。配置时你需要关注的东西MethodGET 还是 POSTURL验证码接口地址HeadersCookie、Referer 等通常需要与登录请求保持一致Extract这里填写提取图片数据的规则。如果是二进制图片可以直接标记整个响应体如果是 Base64则用正则提取。我踩过的一个坑是有些系统的验证码接口会校验 Cookie 是否与当前会话绑定如果获取验证码时用的 Cookie 和后面登录时用的 Cookie 不一致服务端就会认为验证码无效。所以我在配置第一个请求模板时会先在 Burp 的 HTTP 历史里找到一条访问验证码接口的完整请求把原始请求头完整复制过来再精简成模板。3.4 对接 Intruder 实现登录口令爆破当验证码请求模板和识别模板都配置好之后下一步就是把识别结果接入 Intruder。在 Intruder 的Payload Positions里正常标记好用户名、口令和验证码参数的位置。比如 POST 请求体长这样usernameadminpassword§PASS§captcha§CAPTCHA§captchaIdxxx这里§CAPTCHA§是占位符运行爆破时会被替换成实际的验证码识别结果。接下来关键操作在Payload Processing里添加一条规则选择use captcha-killer或类似名称的处理器。这个处理器的功能就是在每次请求发送之前从 captcha-killer 插件内部取最新的验证码识别结果替换掉§CAPTCHA§位置的内容。这样 Intruder 每发一个请求都会自动携带一个刚识别出来的验证码值。在资源池Resource Pool设置里建议把线程数调低一些比如 1 到 3。原因很现实打码平台的识别速度一般只有每秒 1 到 3 个请求如果你把线程飙到 20请求会大量堆积在等待识别结果的环节超时和错误请求会变得非常多。我实测下来单线程跑 1000 条字典加上打码平台延迟大约需要 20 到 40 分钟。如果需要更快可以找识别速度更快的平台或者适当提高并发但前提是目标系统和服务端不会触发频率限制。3.5 参数与字典调优思路验证码识别的用途是让爆破请求“看起来像正常用户”所以爆破参数的节奏也要配合验证码获取频率来调整。延迟设置在 Intruder 的Resource Pool里可以设置请求之间的延迟时间。建议设置为 1 到 2 秒太低容易被风控系统判定为自动化行为导致 IP 被临时封禁。字典选择不用一上来就跑几十 GB 的大字典。推荐先从高频弱口令开始比如内置的top10000字典。授权测试讲究效率先跑小字典命中常见的弱口令再针对特定用户名做定向扩展。错误处理如果服务端返回“验证码错误”通常说明识别结果不对。这时需要回到插件里检查识别准确率。如果连续 5 次识别失败建议暂停爆破排查是图片提取问题还是打码平台接口问题。4. 实战问题排查与独门避坑技巧4.1 验证码识别率低先看图再调参验证码识别率是所有流程中最不稳定的环节。同样是四位数字验证码有的站点识别率可以做到 95% 以上有的连 50% 都不到。关键差别在于图片质量。我在配置过程中发现有些系统返回的验证码图片尺寸很小只有 60x20 像素。这种小图就算人眼看着清晰打码平台识别也会因为分辨率不足而失误。解决办法是在发送给打码平台的请求模板里把图片做一次预处理。常见的做法是先用脚本把图片放大两倍并做灰度化、二值化处理再提交给打码平台。captcha-killer-modified 本身不内置图像处理功能但你可以通过把验证码图片先发送到本地写好的图像处理服务由它处理完再转发给打码平台。相当于在链路里加了一个前置处理节点。如果识别率长期低于 70%还有一招换打码平台。不同平台的模型擅长方向不同有的对扭曲字符处理得好有的对干扰线多的图片识别率高。多注册几个平台实测对比后再决定主用哪个。这个环节没有银弹测过才知道。4.2 Cookie 和 Token 不同步导致验证码无效这个问题的表现是打码平台识别结果明明是对的但提交登录请求后服务端依然返回“验证码错误”。排查步骤通常是这样在 Burp 里对比“获取验证码图片的请求”和“登录请求”的 Cookie 是否一致。确认验证码接口的响应里是否包含Set-Cookie头如果包含说明服务端在获取验证码时创建了一个新会话而你登录请求里用的还是旧会话。在 Intruder 的请求模板里把获取验证码请求响应的Set-Cookie提取出来动态设置到登录请求的 Cookie 头里。captcha-killer-modified 对这种情况的支持方式是在请求模板配置里写提取规则把响应中的Set-Cookie值提取到一个变量然后在另一个请求模板中引用这个变量。我在实操中遇到过几次搞定之后整个流程就很顺了。4.3 验证码接口带时间戳或签名参数有些系统的验证码接口地址每次刷新都会带一个新的签名比如GET /captcha?signabc123ts1710000000这个签名可能是服务端根据当前时间、会话 ID 计算出来的。如果你在插件里写死了这个 URL过一段时间就会失效。解决办法有两类先请求登录页面从 HTML 或脚本里提取最新的 sign 和 ts 值再构造验证码请求。如果验证码接口是在前端 JS 里动态生成的可以考虑直接从浏览器调用链路上复制最新的请求模板并配合 Burp 的宏Session Handling 规则来做动态处理。captcha-killer-modified 对这类动态参数的处理能力相对有限更多时候需要你在 Burp 的 Session Handling 规则里配合宏一并使用。你可以把宏的内容定义为“先请求登录页面并提取验证码 URL再请求验证码接口”然后再把结果交给插件处理。4.4 并发过高触发风控反而更慢我早期犯过一个错误为了追求速度把 Intruder 线程调到了 20 个。结果跑了几百条请求后目标系统直接把 IP 拉黑或者弹出一个行为验证码导致整个爆破流程全部停摆。后来我学乖了把线程降到 2同时在每次爆破前主动请求一次验证码接口确保插件内存里的识别结果是最新的。虽然总耗时变长了但完成率反而更高。还有一点值得提醒打码平台也会有并发限制。部分平台对同一账号的并发识别数有硬性限制超过之后会返回错误码。配置时留意一下平台的 API 文档把并发控制在一个安全的区间。4.5 插件加载失败或无响应如果加载 jar 包时 Burp 报错优先检查 Java 版本。有些旧版本插件使用了一些过时的库和新的 Java 17 不兼容。解决办法是升级插件到最新 release或者在系统环境变量中指定使用 Java 8 启动 Burp。另外如果你同时安装了多个 Burp 扩展某些扩展之间可能存在命名空间冲突表现为点击 captcha-killer 标签页没有反应。这种情况尽量只保留一个验证码处理插件避免互相干扰。5. 合规边界与防守方视角一个测试工具的两面性5.1 使用前提与合规提醒captcha-killer-modified 这类工具的能力摆在这里它能极大提升登录接口自动化测试的效率但也能被用来做坏事。我的建议是只在授权范围内使用。做渗透测试先签订授权书做 CTF只在靶场环境里用做学习研究最好搭一个本地靶场来练手。验证码机制在很多系统里是安全防护的一部分当你决定要“突破”它的时候就要想清楚自己的操作是不是有正当理由。合规永远是第一位的技术能力越强越要守住边界。5.2 从防守方看怎么加固验证码机制站在防守方角度如果希望提高攻击者的测试成本可以做的加固手段其实很多增加复杂度把纯数字验证码换成数字字母混合、加入扭曲、旋转、干扰线提升 OCR 识别难度。控制有效期验证码有效时间缩短到 60 秒以内超过即失效减少自动化工具的操作窗口。做会话绑定强制验证码与 Cookie、Session ID 绑定服务端校验时确认三次握手的信息一致。频率限制同一 IP、同一账号在一定时间内限制登录失败次数超过后锁定或进入人工审核。升级验证码类型从图片验证码换成滑块验证或行为验证。这类验证码需要处理轨迹数据自动化难度成倍增加。监控与告警记录验证码错误率、请求频率、请求来源出现异常时自动触发告警或封禁。我一直觉得验证码对抗本质上是成本对抗。攻击者花成本去识别防守者花成本去增加识别难度双方在各自能接受的成本范围里博弈。理解了这一点你就能明白为什么没有一种验证码是绝对安全的也没有一种爆破工具是万能的。真正决定成败的是操作者对原理的理解程度和对细节的把控能力。最后再分享一个实用的心得在使用这个工具跑通一次完整流程之后建议把请求模板、提取规则、打码平台配置都整理成一份笔记因为你下一次遇到的目标系统可能只是换了验证码接口路径和参数名整体流程是完全一模一样的。把这套模板当做一个固定套路来积累效率和稳定性都会提升不少。
返回列表