首页  >  文章  >  web前端  >  防止对 JavaScript 生态系统的供应链攻击

防止对 JavaScript 生态系统的供应链攻击

Patricia Arquette
Patricia Arquette原创
2024-10-25 13:19:30627浏览

Preventing supply-chain attacks to the JavaScript ecosystem

供应链攻击是 JavaScript 生态系统的大问题。在这篇短文中,我将概述一个简单的安全措施,可以由所有 JavaScript 运行时(浏览器内和浏览器外)实现。这将防止当今困扰 JavaScript 生态系统的大多数供应链攻击。

问题:权限继承

这是最近发生的网站被黑客攻击的事件:

  • 研究人员将 Polyfill 供应链攻击与庞大的模仿赌博网站网络联系起来

问题的核心是JavaScript 模块继承了调用它们的应用程序或模块的权限。这对于浏览器内运行时和浏览器外运行时都是一个问题。

应用程序所依赖的模块版本可能会在应用程序作者不知情的情况下发生更改,这一事实使问题变得更加复杂。因此,即使所有依赖的代码都已经被彻底审查(这本身就是一个巨大的努力),如果依赖版本没有被锁定,这个努力就会被浪费。

为什么不锁定版本并使用基于 semver 的依赖项?嗯,这主要是因为如果模块发布者发布了错误修复,那么最好使用修复的代码。这也是 esm.sh 等 JavaScript CDN 支持 semvers 的重要原因之一。

?网站如何受到影响

网络浏览器是沙盒执行环境,因此网站导入的第三方 JavaScript 模块 (3JM) 不会对最终用户的设备造成任何损害。

尽管如此,3JM 可以在未经网站同意的情况下使用设备的计算资源并发出网络请求进行比特币挖矿等。

?脱离浏览器的 JavaScript 应用程序会受到怎样的影响

一些浏览器外运行时(例如 Deno)确实实施了限制 JavaScript/TypeScript 应用程序权限的措施。但由于以下原因,这些措施还不够:

  • 即使强制执行诸如 Deno 之类的权限系统,它们仍然允许 JS 模块不受限制地继承调用者的权限。这意味着,如果应用程序具有完全写入权限,则不应访问除计算资源之外的任何资源的电子邮件地址验证器可以在操作系统用户不知情的情况下删除用户文件。
  • 应用程序通常以操作系统用户的完全权限运行。例如,对于在 MDRB 等工具下执行的代码,目前无法限制正在运行的代码的权限。

目前的解决方案

目前,安全团队已经建立了自动化流程,用于查找在 NPM 等知名注册表上发布的模块中的漏洞。这种安全措施有几个缺点:

  • 扫描已发布的所有已知模块的所有版本非常耗费资源。
  • 无法保证所有可用的模块都已被扫描。

?解决方案:每个模块的权限

为了解决这些问题,我提出了一个新的每模块权限系统,该系统向后兼容 JS/TS 应用程序当前的工作方式。

这涉及一个新的可选权限配置,每个应用程序和模块都可以在其 deno.json / deno.jsonc / package.json 文件中声明。权限有 2 部分:

  • requests.self — 这是应用程序或模块声明它及其依赖项所需的权限的地方。
  • requests.imports — 这是应用程序或模块声明其同意分配给其依赖项的权限的地方。这是每个依赖项允许需要的权限的超集。

以下是 JS/TS 运行时如何使用权限:

  • 当应用程序或模块导入模块M时,运行时会检查M的permissions.self是否在导入器对M。如果不是这种情况,导入会抛出错误(例如 PermissionError)。
  • 当模块或应用程序尝试执行不允许执行的操作时,也会引发运行时错误(例如 PermissionError)。可以捕获并处理此运行时错误,而无需中止应用程序。
权限的值将是这样的:


{
  "self": {
    "read":  {"allow": [], "deny": []},
    "write": {"allow": [], "deny": []},
    "net":   {"allow": [], "deny": []},
    "env":   {"allow": [], "deny": []},
    "run":   {"allow": [], "deny": []}
  },

  "imports": {
    "jsr:@org/module@1.0.0": {
      "read":  {"allow": [], "deny": []},
      "write": {"allow": [], "deny": []},
      "net":   {"allow": [], "deny": []},
      "env":   {"allow": [], "deny": []},
      "run":   {"allow": [], "deny": []}
    },
    "https://cdn.example/org/module@1.0.0": {
      "read":  {"allow": [], "deny": []},
      "write": {"allow": [], "deny": []},
      "net":   {"allow": [], "deny": []},
      "env":   {"allow": [], "deny": []},
      "run":   {"allow": [], "deny": []}
    },
    "[default]": {
      "read":  {"allow": [], "deny": []},
      "write": {"allow": [], "deny": []},
      "net":   {"allow": [], "deny": []},
      "env":   {"allow": [], "deny": []},
      "run":   {"allow": [], "deny": []}
    }
  }
}
与目前的解决方案相比,我提出的解决方案有几个优点:

  • 轻量级 — 发布的模块不需要扫描。
  • 彻底 — 权限是在运行时强制执行的,因此如果使用正确的 JS/TS 引擎,那么即使是未知的模块也不会被漏掉。

这看起来非常简单。 JS/TS 语言无需修改。如果没有权限配置,那么我们会回到当前的情况,即应用程序及其依赖关系图都具有命令行参数提供的权限 ∎

以上是防止对 JavaScript 生态系统的供应链攻击的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn