3.8 KiB
3.8 KiB
浏览器扩展分析方法论坑与边界
MV2 / MV3 差异组(最容易踩)
- 权限字段语义不同:MV3 站点权限独立在
host_permissions,MV2 混在permissions内(URL 匹配模式)——只读一个字段会漏判一半权限边界 - 远程代码合法性相反:MV2 允许远程 JS(动态加载/
eval),MV3 一律禁止(所有代码必须打包随扩展分发)——"远程拉取代码"在 MV2 是常见能力、在 MV3 是审查绕过信号,证据强度随版本不同 - 后台形态不同:MV2 是常驻 background page;MV3 是 service worker——MV3 worker 空闲约 30 秒被终止、事件唤醒,全局变量状态丢失;持久状态必然落在
chrome.storage/IndexedDB,静态分析别在全局变量里找持久数据 - 流量修改 API 换血:MV2
webRequestblocking 可拦截修改;MV3 商店扩展一般只剩declarativeNetRequest(声明式规则),webRequest 阻断仅企业策略部署的例外——MV3 里找不到 webRequest 拦截代码是正常的 - executeScript 挪窝:动态注入 MV2 是
tabs.executeScript,MV3 是scripting.executeScript(需scripting权限)——按版本搜对应 API 名 - action 统一:MV2 的
browser_action/page_action在 MV3 统一为action——页面弹窗代码位置按版本不同
跨浏览器差异组(Chromium vs Firefox)
- Firefox MV3 不支持
background.service_worker:声明了也不执行(warning 后忽略),实际用background.scripts事件页——同一扩展在 Firefox 里后台可能根本不跑,动态验证要按浏览器分别做 - 更新渠道不同:Chrome 系支持
update_url自托管更新清单(投毒入口);Firefox 更新只经 AMO 渠道,update_url不生效——"自托管更新投毒"仅 Chromium 系成立 - 签名要求不同:Firefox AMO 要求扩展签名(临时加载例外);Chromium 系开发者模式可加载未打包目录——动态分析入口不同
- 扩展 ID 派生:Chrome 扩展 ID 由 manifest
key字段公钥/打包签名派生;Firefox ID 在 manifest 的browser_specific_settings.gecko.id显式声明——找 ID 的位置不同
解包与格式组
- crx 解包警告别当错误:
unzip/7z对 crx 报extra bytes at beginning or within zipfile是正常(Cr24 头在前),结果可用;想无警告用python3 -m zipfile -e - crx2/crx3 头差异:crx2 头含公钥与签名(可变长),crx3 是 protobuf 头 + proof——头长度字段是 LE 4 字节,先读版本号再读头长度,别按固定偏移跳
- xpi 与 zip 无头:Firefox xpi 就是 zip,解包无警告——"解包报错"本身可作格式判定线索
审查绕过与反例组
- 无远程代码也有投毒面:扩展更新机制(自托管/商店)本身就是远程代码通道——单版本静态干净 ≠ 安全,必须看更新链(反例:首版干净、更新后恶意是常见形态)
- 混淆不是恶意证据:商店政策允许合理打包混淆,但高混淆 + 高危权限 + 少功能组合才是可疑信号——别单凭混淆下结论
<all_urls>权限不是必然恶意:部分合法功能(翻译/词典/脚本管理器)确实需要全站点权限——按"权限 vs 声明功能"对照判断,越权信号要结合行为- content script 的隔离上下文:content script 与页面共享 DOM 但不共享 JS 环境——页面里找不到扩展注入的变量,扩展里也读不到页面全局;跨上下文证据链要按消息传递(runtime.sendMessage)还原
使用注意
- 动态加载与行为触发在沙箱内(re-sandbox,re-analyze/platform-tips 最高原则);扩展以浏览器进程权限运行,未隔离环境不加载
- 分析结论按 decision-tree 证据分级标注,并注明浏览器族与版本范围