【问题标题】:How can I make sure that my JavaScript files delivered over a CDN are not altered?如何确保通过 CDN 交付的 JavaScript 文件不会被更改?
【发布时间】:2016-08-01 14:04:08
【问题描述】:

我正在处理一些 JavaScript 文件将托管在 CDN 上的场景。我想有一些机制,这样当这些文件在用户端下载时,我可以确保这些文件没有被篡改,并且确实来自指定的 CDN。

我知道如果我使用 SSL,任务会非常简单,但我仍然想确保即使在没有 SSL 的 HTTP 上也能提供正确的文件。

据我所知,目前没有跨平台支持的 JavaScript 文件数字签名等机制。也许不需要?

浏览器是否有内置方法来验证 JavaScript 文件的作者?有什么办法可以安全地做到这一点吗?

【问题讨论】:

  • 虽然我觉得这个问题很有趣,但它不是题外话吗?
  • 为什么要在 http 上提供文件?
  • "但是为什么没有这样的机制呢?"因为它真的很难。一旦您的数据离开您的服务器,它就完成了。 HTTPS 有帮助,但如果它是一个普通的 HTTP 连接,任何验证都可能失败(或者更确切地说 - 通过)。 MITM 攻击可以在浏览器获得预期之前修改您的预期签名和/或您提供的签名。因此,当用户收到一些有效载荷时,它会被认为是完全安全的……但不一定如此。
  • "但是为什么没有这样的机制呢?"因为在 HTTPS 中已经有一个便宜、有效且广泛适用的解决方案。
  • 这可能应该在 ServerFault 或 Security 上,因为它实际上是关于以安全的方式提供文件,并且与编程的任何关系都只是相切的,因为所述文件恰好代表源代码。

标签: javascript code-signing


【解决方案1】:

事实上,像这样的功能是currently being drafted,名称为Subresource Integrity查看<script> 标记的integrity 属性。 While not yet fully adopted across the board,它正好实现了这个目的。

integrity

包含内联元数据,用户代理可以使用这些元数据来验证获取的资源是否已在没有意外操作的情况下交付。请参阅子资源完整性。

Source

子资源完整性 (SRI) 是一项安全功能,它使浏览器能够验证他们获取的文件(例如,从 CDN 获取的文件)是否在没有意外操作的情况下交付。它的工作原理是允许您提供获取的文件必须匹配的加密哈希。

Source


示例:

<script src="https://example.com/example-framework.js"
    integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
    crossorigin="anonymous"></script>

但是请注意,如果您通过纯 HTTP 传输资源,则此不会保护您免受 Man in the Middle attacks 的影响。在这种情况下,哈希码可以被攻击者欺骗,使得对被操纵的脚本文件的防御变得毫无用处。

因此,除了上述安全措施之外,您应该始终使用安全的 HTTPS 连接而不是纯 HTTP。

【讨论】:

  • 我认为值得一提的是,假设 OP 计划用 HTTP 发送他们的 HTML 以及他们的资产文件,完整性检查很容易被欺骗。如果他们的网站是 HTTPS 并且他们想通过 HTTP 提供资产,那么大多数浏览器都不会喜欢这样并默默地忽略 HTTP 资产。
  • @MonkeyZeus 这只有在 MITM 攻击或我们自己的服务器被入侵的情况下才会成立,对吗?我的理解是,这个问题明确询问如何防御受损的 CDN。
  • @TimoSta 没错!如果没有这些检查,如果您包含来自例如https://code.jquery.com/ 的脚本,那么任何破坏code.jquery.com 的人都可以对您的站点进行XSS,无论code.jquery.com 是否通过HTTPS 访问。通过这些检查,攻击者只能阻止脚本加载,而不是用恶意脚本替换它们。
  • @MonkeyZeus 我在回答中添加了一条注释,说明了您的担忧。你同意这个措辞吗?
  • @TimoSta 非常好,我喜欢!顺便说一句,我甚至在我发表第一条评论之前就 +1 了 :-)
【解决方案2】:

您正在寻找subresource integrity 支票。

例如,这里是 jQuery CDN sn-p:

<script src="https://code.jquery.com/jquery-3.1.0.js"
        integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
        crossorigin="anonymous"></script>

【讨论】:

  • 完全没用,因为攻击者可以在修改您正在下载的脚本的同时修改完整性字段。
  • @LightnessRacesinOrbit:如果您控制自己的通过 HTTPS 访问的域但不控制 code.jquery.com,则不会。这可以保护您免受 code.jquery.com 的入侵。
  • @SilverlightFox:好吧,对 MITM 攻击完全没用*
  • @LightnessRacesinOrbit 是的。仍然非常有用,并且可以防止这种攻击,例如:bleepingcomputer.com/news/security/…
【解决方案3】:

免责声明:与往常一样,您应该只考虑这些机制在使用 https 时有用,因为它们可以通过 http 的 MitM 轻松禁用

除了上述答案中的机制外,还可以在父页面上使用content-security policyhttp响应头。

http://www.html5rocks.com/en/tutorials/security/content-security-policy/

内容安全策略:script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='

这里有几点需要注意。 sha*- 前缀指定用于生成散列的算法。在上面的示例中,使用了 sha256-。 CSP 还支持 sha384- 和 sha512-。生成哈希时不要包含标签。大写和空格也很重要,包括前导或尾随空格。

使用 Chrome 40 或更高版本,您可以打开 DevTools 然后重新加载您的页面。控制台选项卡将包含错误消息,其中包含每个内联脚本的正确 sha256 哈希值。

这个机制已经存在了很长一段时间,所以浏览器的支持可能还不错,一定要检查一下。

此外,如果您想确保旧的不兼容浏览器不安全,您可以在页面顶部包含策略不允许的同步重定向脚本。

【讨论】:

  • 已经存在了很长一段时间,但浏览器支持不是很好。 caniuse.com/subresource-integrity
  • @Sp0t - 子资源完整性(您的链接是关于什么)是其他答案中的机制。我的回答是关于内容安全策略,它有更好的支持
【解决方案4】:

关于这种签名能做什么和不能做什么,有一点很重要。它可以保护用户免受有人修改您的代码的假设性攻击。它不能向您的网站保证您的代码就是正在执行的代码。换句话说,您仍然不能相信来自客户端的任何内容。

【讨论】:

    【解决方案5】:

    如果您的对手模型允许攻击者在 JavaScript 文件从 CDN 交付时对其进行修改,那么您的对手模型允许攻击者在其交付时修改引用源,以消除任何验证尝试,更改源地址到 CDN 以外,和/或完全删除对 JavaScript 的引用。

    请不要公开您的应用程序如何确定用户的解析器是否通过 HTTP 请求(或任何其他没有经过验证的信任链的机制)正确解析到 CDN 的问题。

    /etc/hosts:

    #  ...
    1.2.3.4    vile-pirates.org    trustworthy.cdn
    #  ...
    

    【讨论】:

    • 第一句话显然是不真实的。如果引用页面是通过 HTTPS 加载的,而 JavaScript 文件是通过 HTTP-not-S 加载的呢?
    • 或者如果 CDN 本身被入侵,而不是你自己的服务器被入侵怎么办?
    • @immibis :我选择假设 OP 并没有那么不合理地提出这样的方案。
    • @immibis 这难道不是浏览器通常不允许 HTTPS 页面通过 HTTP 加载 JS 的原因吗?
    • @immibis 我是说它改善了一种甚至不可能的情况,因为浏览器不允许这样做。
    【解决方案6】:

    您可以通过子资源完整性来确保这一点。许多公共 CDN 在 CDN 网站上提供的可嵌入代码中包含 SRI 哈希。例如,在 PageCDN 上,当您单击 jQuery CDN 页面上的 jquery 文件时,您可以选择复制 URL 或使用包含 SRI 哈希的脚本标记,如下所示:

    <script src="https://pagecdn.io/lib/jquery/3.4.1/jquery.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
    

    在页面加载时,浏览器将发出对该资源的请求,并在请求完成后将接收到的文件的哈希值与脚本标签中给出的完整性值相匹配。如果两个哈希不匹配,浏览器将丢弃 jquery 文件。

    目前,全球 91% 的浏览器都支持此功能。更多详情请关注caniuse

    【讨论】:

      猜你喜欢
      • 2020-09-23
      • 2013-12-03
      • 1970-01-01
      • 1970-01-01
      • 2016-02-12
      • 1970-01-01
      • 2021-09-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多