文章总结: 本文探讨了前端防重放机制对传统渗透测试工具的挑战,提出PassRS工具通过桥接Burp与真实浏览器执行环境来解决该问题。关键发现包括:现代前端防护依赖浏览器上下文而非单纯请求参数,传统重放方式在动态Cookie、挑战页等场景下失效。可操作建议为使用PassRS实现请求在浏览器中执行并将结果回传Burp,支持页面/接口请求分流及挑战页链路处理。 综合评分: 82 文章分类: 渗透测试,WEB安全,安全工具,实战经验
攻防渐进–前端防重放的挑战
原创
在稻香村养猪 在稻香村养猪
鉴帷安全
2026年3月27日 15:49 湖北
在小说阅读器读本章
去阅读
前沿:浏览器能过,Burp 却过不去
如果最近两年你做过偏实战的 Web 渗透测试,大概率都遇到过这样一种场景:
目标站点在浏览器中访问完全正常;
可一旦把同样的请求丢进 Burp Repeater,返回的却是 412、403、挑战页,甚至连真正的业务响应都拿不到。
从表面上看,这像是“Burp 重放失败”; 但从本质上看,问题并不在于请求参数本身,而在于请求所处的执行环境已经发生了变化。
越来越多的前端防护产品,已经不再只依赖服务端的静态校验,而是将校验逻辑前置到浏览器环境中。它们会通过动态 Cookie、前端脚本执行、上下文状态绑定、自动跳转、二次请求等方式,对“这个请求究竟是不是由真实浏览器发起”进行判断。
于是,一个非常现实的问题出现了:
浏览器能通过,不代表 Burp 也能通过;而 Burp 之所以过不去,往往并不是因为它不会发包,而是因为它缺少浏览器执行这一层。
在爬虫场景里,这类问题通常可以通过逆向前端逻辑逐步解决; 但在渗透测试场景下,时间预算、测试范围和项目节奏往往决定了我们不可能对每一套前端防护都投入高成本去逆向。
测试人员真正需要的,不是再写一套新的绕过脚本,而是一种更具工程效率的方案:
既然问题出在“执行环境不对”,那么,能不能让 Burp 不再单独发包,而是借助真实浏览器来完成请求执行,再把结果带回 Burp?
PassRS,就是在这个问题意识下做出来的一次尝试。
传统重放为什么越来越吃力
在过去很长一段时间里,Web 安全测试的主要对抗对象是服务端。 测试人员只要能抓到原始请求、修改参数并重放,就足以覆盖大量验证工作。
但今天的应用环境已经明显不同。前端不再只是展示层,而越来越多地承担了状态建立、令牌分发、挑战验证、参数签名、行为判定等职责。许多防护产品真正识别的,也不再只是“请求长什么样”,而是“请求是不是在真实浏览器上下文里发出的”。
这类场景常见的表现包括:
- 首次请求返回挑战页,页面脚本执行后自动写入新的 Cookie 或令牌
- 页面虽然能打开,但真实业务请求其实是后续由
fetch/XHR再次发起 - 同一个 URL 在浏览器中可访问,在 Burp 中却持续返回
412/403 - 请求是否成功依赖 DOM、历史记录、存储状态、同源上下文或自动跳转链路
- 部分目标对 TLS、HTTP/2、浏览器会话特征有明显依赖
在这种情况下,传统的“协议层抓包 + 协议层重放”并没有失效,但它的有效边界已经明显缩小。 测试人员真正缺失的,不再只是“一个会发请求的工具”,而是“一个能在真实浏览器环境中执行请求的测试能力”。
我想解决的其实不是“发包”,而是“执行环境”
PassRS 的定位并不是替代 Burp,也不是另起炉灶做一套浏览器自动化框架。 它想补上的,是 Burp 现有工作流里长期缺失的一层能力:真实浏览器执行层。
它的核心逻辑可以概括成一句话:
在 Burp 中发起重放,在真实浏览器中执行请求,再将浏览器拿到的最终结果同步返回 Burp。
这意味着:
- Burp 继续负责抓包、查看、修改、筛选与重放
- 浏览器负责执行前端脚本、建立上下文、处理挑战链路
- 插件负责在 Burp 与浏览器之间完成请求桥接、流程协调和结果回传
从用户视角看,工作流仍然留在 Burp; 但从执行路径看,请求已经不再完全由 Burp 自己发出,而是由真实浏览器代表 Burp 完成执行。
一张图看懂 PassRS 的工作方式
flowchart LR
A[Burp 模块<br/>Repeater / Proxy / Intruder 等] --> B[PassRS 接管层]
B --> C[本地 Relay]
C --> D[浏览器桥接层]
D --> E[真实浏览器上下文]
E --> F[前端脚本执行]
F --> G[动态 Cookie / Token / 二次请求 / 跳转]
G --> H[最终业务响应]
H --> D
D --> C
C --> B
B --> I[Burp 中回显最终响应]
技术原理:为什么这条路线是成立的
PassRS 的技术原理,建立在一个非常直接的判断上:
当前很多前端防护拦截的,并不是“请求包本身”,而是“请求发起环境”。
如果问题的核心在执行环境,那么解决方案就不能只停留在协议层,而必须把浏览器上下文一并纳入重放过程。
围绕这一点,PassRS 的设计可以拆成四个核心原则。
1. 请求先被接管,再进入浏览器执行链路
请求不再由 Burp 直接发往目标,而是先进入本地桥接链路。 这样做的目的,是把“Burp 发起请求”和“浏览器执行请求”这两件事解耦。
Burp 负责控制请求,插件负责桥接流程,浏览器负责完成执行。
2. 重点不是模仿浏览器,而是借助浏览器
浏览器的价值从来不只是一个 User-Agent。
它真正提供的是完整的执行现场,包括:
- DOM
- Cookie 与本地存储
- 页面脚本执行能力
- 表单提交与页面跳转机制
- 同源上下文与状态链路
很多前端防护依赖的,正是这些执行现场本身。 与其不断模拟浏览器,不如直接让浏览器完成它原本就擅长的事情。
3. 页面型请求与接口型请求必须区分处理
浏览器里的请求并不是单一模型。 页面导航、表单提交、脚本请求,本质上是三条不同的执行路径。
如果对所有请求都用同一种方式处理,就很容易出现“看起来发出去了,实际上上下文不对”的问题。
因此,PassRS 并不是简单地“把所有请求交给浏览器”,而是根据请求特征选择更接近原生行为的执行路径,例如:
- 页面型请求尽量走真实导航
- 表单型请求尽量走真实提交
- 接口型请求尽量在浏览器上下文中走
fetch/XHR
4. 真正有价值的是“最终结果回传”,而不是“第一跳响应回显”
很多前端防护的第一跳响应,本来就只是一个中间状态。 如果插件只是把第一跳挑战页回传给 Burp,那么从测试角度看,与传统 Repeater 并没有本质区别。
PassRS 真正要做的是:
- 先让浏览器把挑战页后续链路跑完
- 再把浏览器执行完成后的最终结果带回 Burp
- 只有这样,Burp 中看到的响应才真正具备分析价值。
实现方法:PassRS 是如何落地的
在实现层面,PassRS 并不依赖某一种厂商专属规则,而是围绕“请求接管、浏览器执行、结果回传”三个核心阶段展开。
第一阶段:在 Burp 中选择性接管请求
并不是所有请求都值得走浏览器桥接。 PassRS 会根据作用范围、Burp 模块和目标规则,对请求进行筛选,仅接管真正需要浏览器执行的那一部分流量。
这样可以避免对全部请求一刀切,也便于测试人员只在复杂站点上启用插件。
第二阶段:通过本地 Relay 承接原始请求
被接管的请求不会再由 Burp 直接发往目标,而是先进入本地中继层。 这一层的任务不是执行业务逻辑,而是作为 Burp 与浏览器之间的桥接节点,承接原始请求信息,并转交给浏览器执行层。
这样做的好处是:
- 将测试入口与执行现场隔离
- 便于统一管理错误、状态与回传流程
- 为后续浏览器侧执行提供稳定桥梁
第三阶段:在真实浏览器中重建执行上下文
浏览器执行层的重点并不是“打开网页”这么简单,而是尽量让请求回到合适的上下文中执行。 例如:
- 复用已有浏览器实例,避免无意义的重复启动
- 进入合适的页面上下文,减少状态错位
- 同步必要 Cookie,保证会话连续性
- 根据请求类型选择导航、表单提交或脚本请求路径
从工程角度看,这一步做的其实是“上下文恢复”,而不是“动作模仿”。
第四阶段:继续处理挑战页、中间页和自动二次请求
很多前端防护不会在第一跳就给出业务结果,而是通过页面脚本、中间表单或自动跳转继续推进流程。 因此,浏览器执行层除了发起请求,还必须继续观察页面后续行为,例如:
- 是否进入挑战状态
- 是否自动写入新的 Cookie
- 是否由页面脚本再次发起请求
- 是否存在自动表单提交
- 是否在跳转后落到最终业务页面
这一阶段决定了插件能否真正拿到“浏览器视角下的最终结果”。
第五阶段:将最终结果结构化回传给 Burp
浏览器拿到最终结果之后,PassRS 还需要把它转换为 Burp 可识别、可查看、可分析的响应形式。 这一步回传的不是单纯的页面内容,而是一个完整的最终结果,包括:
- 最终状态码
- 最终地址
- 页面上下文信息
- 最终响应内容
只有完成这一层结构化回传,Burp 侧的分析和后续手工测试才具备连续性。
为什么不优先做“规则绕过”
从结果上看,测试人员当然更关心“能不能拿到最终响应”; 但从方法上看,PassRS 选择的路线与传统绕过思路是明显不同的。
传统方法通常强调:
- 补齐缺失请求头
- 伪造浏览器字段
- 逆向前端算法
- 复制挑战页中的参数生成逻辑
这些方法并非没有价值,但在渗透测试场景中,它们通常存在几个现实问题:
- 站点差异大,难以通用
- 维护成本高
- 新版本防护上线后容易失效
- 对有限测试周期不够友好
相比之下,PassRS 所采用的路线是:
不优先伪造浏览器,而是优先借助真实浏览器。
这条路径的优势在于:
- 更接近真实用户访问链路
- 对新型前端校验机制具有更强适应性
- 减少对单站点逆向逻辑的依赖
- 更适合复杂页面和动态交互场景
当前版本的几个关键特性
1. 支持页面型请求与接口型请求分流
不同请求类型采用不同执行策略,以贴近浏览器真实行为。当前覆盖的典型类型包括:
GET页面请求GET接口请求- 无请求体的
POST application/x-www-form-urlencodedapplication/jsonmultipart/form-data- 其它文本类请求体
2. 支持挑战页后续链路处理
对于首次返回 412、403 或挑战页的场景,插件不会简单停留在第一跳,而是继续观察并处理:
- 脚本触发的二次请求
- 自动表单提交
- 中间页跳转
- 最终业务页面回传
3. 支持作用范围与 Burp 模块选择
PassRS 不是全局粗放式接管,而是支持根据作用范围和模块进行精确控制。 这样既能提高针对性,也有助于控制整体性能开销。
4. 支持目标域名或 IP 正则匹配
对于多目标、多环境测试场景,可以只对指定域名或 IP 范围启用浏览器桥接,降低误接管概率。
5. 支持静态资源加载控制
在部分场景下,加载全部静态资源有助于还原页面真实状态; 而在另一些场景下,适度屏蔽图片、媒体和字体资源,则有利于提升执行效率。 PassRS 将这一能力设计为可选配置,以兼顾兼容性与性能。
6. 针对并发场景做稳定性保护
真实浏览器上下文本身是强状态化环境。 如果多个重放请求同时争用同一浏览器现场,极易出现页面抢占、状态污染和响应错位。
因此,在当前阶段,PassRS 对浏览器桥接执行采用了更偏稳定性的控制策略,以尽量避免多请求并发争用同一执行现场。
它适合谁使用
PassRS 更适合以下类型的测试场景:
- 浏览器访问正常,但 Burp Repeater 长期返回
412/403 - 目标系统存在明显的前端挑战、动态 Cookie 或二次请求机制
- 业务接口依赖浏览器真实上下文
- 需要在 Burp 中持续完成手工验证,而不是跳转到纯浏览器自动化框架
- 需要在有限测试周期内提升复杂站点的验证效率
它不适合什么场景
PassRS 并不是一个“任何前端防护都能无成本解决”的通用终极方案。 它能够显著提升对某类目标的兼容能力,但仍然存在边界,例如:
- 极端依赖浏览器指纹或环境特征的站点
- 带文件上传的复杂
multipart场景 - 少量非标准
GET + body请求 - 对环境依赖极强的特殊客户端链路
- 不同系统与 Python 运行环境下的依赖差异
也就是说,PassRS 更适合解决“测试执行链路缺失浏览器能力”这一类问题,而不是试图替代所有针对特定防护产品的深度逆向分析。
结语
过去,Web 安全测试更关注服务端如何理解一个请求; 而今天,越来越多的场景开始要求测试人员回答另一个问题:
这个请求,究竟是不是由一个真实浏览器,在真实上下文中发出的?
PassRS 的价值,就在于它试图将这一问题重新纳入 Burp 的主战场。
它未必是终点,但它代表了一条值得持续投入的方向: 让安全测试工具不仅能够抓包和改包,也能够借助真实浏览器完成请求执行。
对于那些长期遭遇“浏览器能够访问、Burp 却难以有效重放”困境的测试人员而言,这种思路并不是锦上添花,而是正在变得越来越必要。
项目地址:https://github.com/Zmz-c/PassRS/
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:鉴帷安全 在稻香村养猪 在稻香村养猪《攻防渐进–前端防重放的挑战》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论