JS 逆向与接口发现(js-reverse)
TL;DR
- 目的:从前端 javascript 产物与运行时流量还原真实 api 面——签名/signature 机制、加密参数、webpack 隐藏路由全部进资产清单,产出可直接喂给 hunt-* 主线的接口与参数字典
- 适用:接口带签名/时间戳/token 参数、常规爬取拿不到数据接口、需要复现请求做越权测试时
- 输入:目标站点 URL、可运行的浏览器(Playwright MCP)或静态 JS 产物
- 输出:
资产/js-reverse.md(接口清单 + 签名机制说明 + 可重放的请求样例 + 参数字典) - 红线:仅限授权范围;逆向产物是资产不是漏洞,禁止把"能签名"当发现上报
- 关联:发现结果交给
hunt-idor(ID 字典)、hunt-ssrf(隐藏内部接口)、api-authentication(签名绕过);工具路由见playwright-browser-mcp
纲领:逆向产出不只是 /api/ path
签名盐、密文 ID 的公钥、hidden/admin 路由、写死的演示账号——全部进资产清单。演示号是钥匙,不是登录框字典:遇到测试账号/演示凭据硬编码,优先怀疑它在新接口仍有效。
工作流(九步,可独立执行任意一步)
| # | 步骤 | 做法 | 算成 | 假点 |
|---|---|---|---|---|
| 1 | 运行时抓 XHR/fetch | Playwright MCP list_network_requests 筛 XHR/fetch,按业务操作分组 |
得到"操作 → 接口"映射表 | 只列到静态资源请求=没筛干净 |
| 2 | 全量 JS 提取 path | 下载全部 js 产物,grep -oP '"(/api/[^"]+)"' 类正则批量挖未触发过的 path |
path 清单显著大于运行时所见 | 把 CDN/第三方库的 path 混入=需按域过滤 |
| 3 | 关键词检索定位鉴权代码 | search_in_sources:userId、Authorization、sign、signature、salt、appkey |
定位签名生成与鉴权头注入点 | 仅命中压缩变量名无上下文=换关键词 |
| 4 | XHR 断点回溯 | 对目标请求下 XHR 断点,从 setRequestHeader 调用帧向上回溯到签名生成函数 |
拿到签名函数名与输入参数列表 | 断不到=setRequestHeader 被包装,改 hook XMLHttpRequest |
| 5 | 签名形态识别 | 三种常见形态:参数字典序拼接+MD5(secret);timestamp+nonce+HMAC;固定盐拼接 | 写出签名算法说明(进资产) | 猜测形态未验证=不算,必须过第 7 步比对 |
| 6 | 借页面 JS 现场签名 | evaluate_script 直接调用页面自己的签名函数给任意参数签名——不必复现算法 |
任意参数的合法签名请求 | 页面函数依赖闭包内密钥无法直接调用=回退第 5 步复现 |
| 7 | Python 复现双端比对 | 离线复现签名,与第 6 步结果逐字节比对 | 完全一致=可离线重放;不一致=还有隐藏参数,回第 4 步 | 只对一组参数一致=样本不足,至少 3 组 |
| 8 | webpack chunk 挖隐藏路由 | grep chunk.*js、path:、baseURL;还原路由表与多环境 API 根 |
hidden/admin 路由清单进资产 | 仅找到路由名未找到 API 根=标记待验证 |
| 9 | 接口参数字典化 | 提取各接口响应中的 ID 字段、枚举值,整理成参数字典 | 字典交付给 hunt-idor 做换 id 测试 | 字典里混入自产数据=标注来源 |
与三环的衔接
- 产出物落点:
资产/js-reverse.md是发现环的正式产出,进状态层 discovery 节点;权重 ≥0.6 的签名缺陷(如弱盐、时间戳缺失)升级为深度攻击环输入。 - 何时停:接口清单覆盖了主要业务操作、签名机制可离线重放、隐藏路由已核活——三硬件齐即收口,禁止无限逆向框架运行时。
- 操作安全:现场签名请求频率与正常用户一致;
evaluate_script只调用页面自身函数,不注入可见行为。