拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

浏览器端(Client-Side)安全审计实战指南:DOM XSS、跨源消息与 Service Worker 攻击面的猎杀与验证规范

浏览器端(Client-Side)安全审计实战指南:DOM XSS、跨源消息与 Service Worker 攻击面的猎杀与验证规范
  • AI 技能
  • 应用安全

【免费下载链接】security-audit-skill

A coding-agent skill for multi-phase security audits with independently verified, machine-readable findings

项目地址:https://gitcode.com/GitHub_Trending/se/security-audit-skill
点击查看免费下载

浏览器端是源码审计中最容易被低估的攻击面:大量安全决策发生在服务端永远看不到的数据上——URL 片段、window.name、postMessage、浏览器缓存,以及由扩展与离线应用维护的客户端状态。本文以 security-audit skill 的 CLIENT-SIDE.md 为骨架,完整讲解浏览器端攻击类别的猎杀方法、核心纪律与验证规则。读完本文,你将掌握从 DOM 注入、DOM clobbering、原型链污染,到跨源消息、Service Worker 缓存、XS-Leaks、点击劫持的完整证据链构建方法,并理解这些结论如何在多智能体审计流水线中输出为可独立验证的confirmed或needs_validation记录。

何时使用这份指南:浏览器端适用场景界定

当安全信任决策或不可信渲染发生在浏览器环境中时,就应该启用本指南。具体包括以下目标形态:

  • 单页应用(SPA);
  • 浏览器扩展(browser extensions);
  • 嵌入式 WebView;
  • Service Worker;
  • 离线应用(offline applications);
  • 将攻击者可影响的内容渲染进 DOM 的代码;
  • 接收跨窗口消息(cross-window messages)的代码;
  • 使用浏览器存储(browser storage)的代码。

这些路径包含服务端完全看不到的来源,例如 URL 片段(URL fragments)、window.name、postMessage载荷,以及先前缓存过的内容。审计者必须把它们当作独立的、位于服务端视野之外的输入面来对待。

在技能体系中,本文件需要与其他配套文档协同使用:

  • 与 ATTACK-CLASSES.md 配合:该文件是核心攻击类别清单,其中明确说明"Client-side (browser/JS): DOM XSS, prototype pollution, postMessage/origin trust, and other browser-side classes — covered by the CLIENT-SIDE.md companion blocks when selected"(ATTACK-CLASSES.md 的 Injection 小节),即当选定客户端配套块后,浏览器侧注入类问题统一由本文件接管;
  • WebView 桥接的原生侧(native side)由 DESKTOP-MOBILE-AND-LOCAL-IPC.md 覆盖;
  • 服务端 CSRF、会话(session)与认证回调(auth callbacks)由 WEB-PROTOCOL-AND-AUTH.md 覆盖。

从源码结构可以推断:ATTACK-CLASSES.md是"普通攻击类别块"的来源,而CLIENT-SIDE.md属于"companion(配套)块",二者在 RECONNAISSANCE.md 的伴生选择环节中按边界匹配被选入特定的覆盖单元。

核心纪律:每条浏览器端审计提示词都必须包含的内容

本文件开篇就给出 5 条核心纪律,要求在浏览器域内下发的每个 agent 提示词中完整包含。它们构成了整个浏览器端审计的证据门槛:

- A client-side candidate needs a controllable source and an executing or disclosing sink. Name both and show attacker-influenced data reaching the sink. - The impact must reach a victim's session, another origin, or shared persistence. Self-injection and disclosure of the attacker's own data are not findings. - Framework escaping, browser same-origin policy, CSP, COOP/CORP, service-worker scope, and modern noopener defaults are real controls. Verify them before assigning impact. - Browser storage and caches are shared by origin and may outlive login state. Identify who writes, who reads, and which account, tenant, or worker lifecycle clears each record. - Use `confirmed` only for complete source evidence plus bounded local browser tests. Use `needs_validation` when renderer, extension permission, deployed header, or browser-policy behavior is required but unavailable.

逐条解读其实质含义:

  1. 候选漏洞必须同时具备"可控来源"与"执行/泄露汇聚点":审计者要同时命名两者,并展示攻击者影响的数据确实抵达了汇聚点。只找到来源或只找到汇聚点都不构成候选。
  2. 影响必须跨越信任边界:必须触及受害者会话、另一个源(origin)或共享持久化。自注入(攻击者注入并影响自己的数据)与攻击者自身数据的泄露不是发现项——这是浏览器端审计中最重要的排除法则。
  3. 浏览器内建控制是真实存在的防护:框架转义(framework escaping)、浏览器同源策略、CSP、COOP/CORP、Service Worker 作用域、现代浏览器noopener默认行为,都必须先验证再赋予影响等级。不能假设它们不存在。
  4. 浏览器存储按源共享且可能比登录态更长寿:必须识别谁写入、谁读取、由哪个账号/租户/worker 生命周期负责清理每条记录。跨账号切换后仍然残留的令牌就是典型的高危信号。
  5. 证据等级纪律:confirmed只用于完整来源证据加上受限的本地浏览器测试;当需要渲染器(renderer)、扩展权限、已部署响应头或浏览器策略行为而现场不可得时,一律用needs_validation。

这些纪律并非孤立文本——HUNTING.md 的"Required hunter prompt"第 4 点明确规定,hunter 提示词必须逐字复制每个选中配套块的Core discipline、攻击类别小节、Universal moves与Validation rules,而不是只发送块名或小节名。这意味着本文件的纪律、类别与规则就是实际下发给猎手 agent 的执行规范。

攻击类别一:DOM 与对象状态(subagent_type: general)

DOM 型 XSS(DOM-based XSS)

追踪以下浏览器源进入危险汇聚点的路径:

  • location字段(location.href、location.search、location.hash等);
  • document.referrer;
  • window.name;
  • 消息数据(message data,即postMessage载荷);
  • 浏览器存储(storage);
  • 浏览器控制的文档状态。

这些数据一旦流入以下汇聚点即构成候选:

  • innerHTML、outerHTML;
  • document.write;
  • 字符串求值类 API(eval、Function、setTimeout/setInterval的字符串形式等);
  • 可执行 URL(javascript:、data:等协议);
  • jQuery 的 HTML API;
  • 框架的逃生舱口(escape hatches,如dangerouslySetInnerHTML之类的显式原样渲染接口)。

关键排除规则:被框架自动转义后的插值(interpolation escaped by the framework)不是发现项。审计者必须确认攻击者数据确实以未转义形式到达了执行型/渲染型汇聚点。

DOM clobbering(DOM 覆写)

攻击者注入的id或name属性会遮蔽(shadow)一个全局变量、表单属性、配置对象或初始化标志,而这些对象随后被代码当作可信值使用。

构成发现项必须同时满足两个条件:

  1. 存在保留属性的标记路径——即攻击者注入的 HTML 属性能够存活下来(未被净化器剥离);
  2. 存在对覆写值的安全相关使用——被覆写的值随后参与了授权、配置、路由或渲染决策。

仅仅能覆写某个 DOM 属性、但该值从未被安全相关逻辑读取,不构成发现项。

原型链污染与 gadget 链(Prototype pollution and gadget chain)

攻击者控制的键(key)到达一个递归写入操作(如深度合并 deep merge、路径赋值 path assignment),从而修改原型状态;随后存在一个可达的 gadget消费被污染的原型属性,改变授权、执行、导航或渲染结果。

必须同时证明两段链条才能报告:

  • 污染段:攻击者键确实驱动了递归写入并污染了原型;
  • 利用段:污染后的属性被某个安全相关的 gadget 消费。

明确的反例排除:仅仅JSON.parse、浅拷贝(shallow copy)、或"污染了原型但没有 gadget 消费"的情况,不足以构成发现项。

攻击类别二:跨源消息与网络(subagent_type: general)

postMessage 的 origin 与 source 信任(postMessage origin and source trust)

处理方(handler)在未使用精确 origin 白名单的情况下,用event.data执行敏感操作;当多个 frame 共享同一 origin 时,还必须校验期望的event.source。发送侧同样存在风险:敏感数据以*为目标发送,会到达非预期的嵌入方(embedder)。

关键排除规则:弱子串(substring)、前缀(prefix)、后缀(suffix)或未锚定正则(unanchored-regex)的 origin 匹配不算origin 校验。origin 校验必须是精确的、规范的、锚定的。

跨站 WebSocket 请求利用(Cross-site WebSocket request use)

WebSocket 升级(upgrade)在没有Origin校验或信道专属令牌(channel-specific token)的情况下,接受来自不可信源的 ambient cookie,使得受害者的会话能够读取或篡改数据。

报告此类发现需要同时确认两件事:

  • 升级行为:确认服务端确实接受了携带 ambient cookie 的跨源升级请求;
  • 安全相关的消息处理函数:确认升级后的通道中存在读取/变更敏感数据的处理逻辑。

携带凭据的 CORS 信任(Credentialed CORS trust)

服务端反射(reflects)或弱匹配(weakly matches)Origin,同时允许凭据(credentials)并返回敏感响应。

关键排除规则:带凭据的裸通配符(bare wildcard,即Access-Control-Allow-Origin: *配合credentials)会被浏览器直接拒绝——这不是可利用路径。只报告实际被反射/被允许的具体 origin 路径以及随之发生的跨源数据读取或变更。

攻击类别三:Service Worker 与浏览器存储(subagent_type: general)

Service Worker 注册与作用域接管(Service-worker registration and scope takeover)

攻击者可影响的内容存在以下情况之一即构成候选:

  • 成为被注册的 worker 脚本本身;
  • 控制一个接收过度宽泛Service-Worker-Allowed作用域(scope)的路径;
  • 在缺少完整性控制(integrity control)的情况下篡改更新导入(update imports)。

报告前必须验证以下事实:

  • 最终脚本 URL;
  • 响应 MIME 类型;
  • 来源(origin);
  • 作用域(scope);
  • 每个被导入脚本的实际控制者。

关键排除规则:具有预期作用域的正常同源 worker不是缺陷。

Service Worker 缓存与身份混淆(Service-worker cache and identity confusion)

worker 缓存了个性化响应,但缓存策略没有包含账号、租户、授权状态或请求模式,随后在账号切换或登出后把这些响应提供给新身份。

审计时需要检查:

  • fetch 事件路由(fetch-event routing);
  • 缓存名称与键(cache names and keys);
  • 导航回退(navigation fallbacks);
  • 缓存清理逻辑;
  • 错误/离线路径是否会返回另一个用户的先前响应。

浏览器存储泄露与过期授权(Browser-storage disclosure and stale authorization)

令牌、私有响应、草稿数据或授权决策残留在以下客户端存储中,并被另一个账号或低信任的同源组件读取:

  • localStorage;
  • sessionStorage;
  • IndexedDB;
  • Cache Storage;
  • 扩展存储(extension storage);
  • 其他客户端状态。

关键排除规则:仅仅"存储了一个令牌"不是发现项。必须存在一个更低权限的现实读取者,或存在撤销/登出后的持续使用路径。

跨上下文存储与广播混淆(Cross-context storage and broadcast confusion)

storage事件、BroadcastChannel、共享 worker(shared workers)或源级缓存(origin-wide caches)在标签页之间传递身份或指令,却没有绑定当前会话。

审计要点:

  • 账号切换(account switching);
  • 私有/公开窗口(private/public windows);
  • 租户变更(tenant changes);
  • 可能覆盖更新授权状态的过期标签页(stale tabs)。

攻击类别四:跨站信息泄露(subagent_type: general)

XS-Leaks 与跨源状态预言机(XS-Leaks and cross-origin state oracles)

攻击者页面能够通过以下侧信道区分受保护的跨源状态,同时浏览器自动附加受害者凭据:

  • 资源加载/错误事件(resource load/error events);
  • frame 或 window 状态;
  • 重定向行为(redirect behavior);
  • 时序(timing);
  • 缓存状态(cache state);
  • 响应大小(response size)。

报告必须要求一个具体的、携带秘密的谓词(predicate),例如"某个私有对象是否存在""某个角色是否存在""某个账号是否存在"。

关键排除规则:泛泛的时序波动或公共资源可用性差异不是发现项。必须能证明这个可区分的比特泄露了具体受保护状态的布尔结果。

Window 与 opener 状态泄露(Window and opener state disclosure)

跨源 window 的允许元数据或导航结果泄露了受保护状态;或者,保留的 opener / 命名窗口(named-window)关系让攻击者控制的页面能够影响特权导航。

审计检查项:

  • COOP;
  • frame 保护;
  • noopener;
  • 精确 origin 校验;
  • 可观察状态是否确属机密。

攻击类别五:UI-redress 与导航(subagent_type: general)

点击劫持(Clickjacking)

被框架化(framed)的状态变更动作缺少有效的防护机制:

  • frame-ancestors;
  • X-Frame-Options;
  • 或等效的 UI 隔离措施。

报告要求:

  • 必须是敏感动作(状态变更);
  • 必须确认该动作能够在被框架化状态下完成。

关键排除规则:只读内容缺少响应头只是加固建议(hardening notes),不是发现项。

客户端导航混淆(Client-side navigation confusion)

客户端来源控制了重定向或导航,却没有方案(scheme)与目的地(destination)策略,包括可执行的javascript:或data:目的地。

反向标签钓鱼(reverse tabnabbing)的适用前提:仅当代码显式保留window.opener、使用window.open且未做隔离、或支持没有隐式noopener的浏览器时,反向标签钓鱼才适用。现代浏览器默认noopener行为是真实防护,必须先验证再报。

通用动作(Universal moves):适用于以上所有类别的猎杀策略

无论具体攻击类别是什么,以下三条通用策略都适用:

  • 从汇聚点反推来源:先从 DOM、导航、worker、消息和存储汇聚点出发,再反向追踪到仅浏览器可见的来源与服务端可控来源。同时记录应该阻止这条路径的浏览器策略(browser policy)。
  • 用本地测试源与虚拟账号验证生命周期:测试账号切换、登出、worker 更新、离线回退和过期标签页状态,必须使用本地测试源(local test origin)与虚拟账号(dummy accounts)。禁止使用生产用户、生产源或共享服务。
  • XS-Leaks 只列可证谓词:只列出由源码与本地浏览器行为证明的谓词,然后识别能够移除该预言机的响应头或渲染选择。

验证规则:报告任何浏览器端发现项之前必须完成的前置检查

本文件的最终验证规则是报告阶段的强制门槛,共 5 条:

  1. 引用完整五要素:来源(source)、汇聚点(sink)、浏览器策略(browser policy)、受影响源/会话(affected origin/session)、可观察的变更或泄露(observable mutation or disclosure)。
  2. 证明机制完整性:原型链污染必须证明递归写入与安全相关 gadget;DOM clobbering 必须证明标记存活且被遮蔽的值确实被使用。
  3. 证明生命周期可达性:Service Worker 与存储类发现项,必须证明攻击者控制的写入或缓存条目能到达不同账号、不同租户或更晚的授权状态。
  4. 证明精确校验与受保护状态:消息、CORS、WebSocket 与 XS-Leaks 类发现项,必须展示精确的 origin/source 校验以及暴露的受保护状态或动作;同时确认 CSP、COOP/CORP、cookie 与 SameSite 策略没有已经阻断该路径。
  5. 证据等级分流:confirmed只用于完整客户端路径加受限本地证据;needs_validation必须精确列出所有者需要验证的已部署响应头、扩展权限、浏览器版本或渲染器行为。

与多智能体审计工作流的衔接:这些类别如何在流水线中被执行与验证

CLIENT-SIDE.md并非孤立的安全清单,它在 security-audit skill 的六阶段工作流中扮演着"选中的配套攻击类别块"角色。理解以下衔接关系,可以让你真正把它用起来:

阶段定位:整个 skill 在 SKILL.md 中定义了六阶段流程——侦察(Reconnaissance)、覆盖驱动的猎杀波次(Coverage-led hunting waves)、候选验证(Candidate validation)、结构化输出(Structured output)、独立记录验证(Independent record verification)与目标无关报告(Target-neutral reporting)。其中浏览器端攻击类别在第二阶段被猎手执行。

提示词组装:按 HUNTING.md 的"Required hunter prompt"要求,每个猎手提示词必须包含:角色前言、architecture.md全文、分配的覆盖单元、逐字复制的选中攻击类别块(含本文件的Core discipline、各攻击类别小节、Universal moves和Validation rules)、被排除的块及理由、核心猎杀方法、验证规则、结构化结果契约。这解释了为什么本文件要把"核心纪律—类别—通用动作—验证规则"组织成四个层次——它们就是为被原样嵌入 agent 提示词而设计的。

结构化返回契约:猎手必须返回恰好一个 JSON 对象(结构化猎手结果),其中每个候选条目都要携带proposed_verdict(confirmed或needs_validation)。浏览器端结论的confirmed需要完整字段(fingerprint、title、description、root_cause、intended_behavior、ordered trace、evidence、conditions、execution、remediation、severity、confidence),且整体严重等级不得超过已证实的影响;needs_validation则需要claimed_root_cause、trace、evidence、非空的 blockers 和至少一条validation_plan(local或deployment),且不允许附带严重等级——这与本文件"核心纪律"第 5 条的等级纪律完全一致。

记录契约:report-schema.json 定义了三种 verdict 的严格字段约束(additionalProperties: false):confirmed必须携带execution(目标无关、使用目标原生接口的受限复现)与observed_result(非空且事实性);needs_validation携带blockers与validation_plan,不得使用 severity;rejected携带reason。浏览器端测试的"受限本地浏览器测试"对应 schema 中execution的浏览器动作(browser action)描述,而部署响应头无法确认的项则流入needs_validation的deployment计划。

沙箱边界:浏览器端行为验证必须在 SKILL.md 规定的 OS 强制沙箱内进行:无外部网络、空环境白名单、目标与工具只读、仅scratch/可写、显式资源限制。这正是本文件"通用动作"要求"使用本地测试源与虚拟账号、不使用生产用户"的落点。

验证接力:VALIDATION-AND-REPORTING.md 规定每个唯一候选都要交给没有猎杀过它的新鲜generalverifier,由它尝试从源码与受限本地证据中反驳候选;verifier 可以确认、降级为needs_validation或rejected。浏览器策略、扩展权限、已部署响应头这类"源码外事实"正是needs_validation的典型触发点——这与你看到的本文件多处"确认 CSP/COOP/COEP 是否已经阻断"的要求一一对应。

多轮覆盖:RECONNAISSANCE.md 明确"不要因为语言或依赖名出现就选择配套文件,而是因为侦察发现了该文件When to use this file所描述的信任敏感边界"——这提示审计者:只有当你确认目标确实存在 SPA、扩展、WebView、Service Worker 或浏览器存储边界时,才应把CLIENT-SIDE.md选入猎手提示词。

实战要诀:把本指南用于你自己的浏览器端审计

将本指南落到实际审计中,可以遵循以下操作顺序:

  1. 判定边界:确认目标形态落在"何时使用这份指南"清单内,并检查是否存在 SPA/扩展/WebView/Worker 等浏览器边界(对照 ATTACK-CLASSES.md 的类目入口)。
  2. 反向追踪:从innerHTML、postMessagehandler、worker fetch 事件、导航与存储读写点出发,反向找可控来源,并记录应阻止该路径的浏览器策略。
  3. 排除内建防护:对每条路径先验证框架转义、同源策略、CSP、COOP/CORP、SW scope、noopener默认行为是否已经阻断;被阻断的路径要么放弃、要么记为加固建议。
  4. 构建本地证据:用本地测试源与虚拟账号做账号切换、登出、worker 更新、离线回退与过期标签页测试,观察最小边界结果。
  5. 按等级分流:完整源码路径加受限本地证据 →confirmed;需要渲染器、扩展权限或部署响应头 →needs_validation并写明精确 blocker 与验证计划。

这套纪律的核心始终是那句总纲:一个候选漏洞如果没有具体的受影响主体、资源或安全后果,就不是已确认的发现项。浏览器端审计尤其如此——自注入不是发现项,框架转义是真实防护,存储残留必须找到更低压力的读者,而每一次confirmed都应当经得起一位从未参与猎杀的独立验证者的反驳。

  • AI 技能
  • 应用安全

【免费下载链接】security-audit-skill

A coding-agent skill for multi-phase security audits with independently verified, machine-readable findings

项目地址:https://gitcode.com/GitHub_Trending/se/security-audit-skill
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

返回列表