如何确保通过CDN交付的JavaScript文件不被更改?

如何确保通过CDN交付的JavaScript文件不被更改?,javascript,code-signing,Javascript,Code Signing,我正在研究一个场景,其中一些JavaScript文件将托管在CDN上。我希望有一些机制,以便在用户端下载这些文件时,我可以确保这些文件没有被篡改,并且确实来自指定的CDN 我知道如果我使用SSL,这项任务非常简单,但我仍然希望确保即使在没有SSL的HTTP上也能提供正确的文件 就我所能搜索的范围而言,目前还没有跨平台支持的JavaScript文件数字签名这样的机制。也许不需要它 浏览器是否内置了某种方法来验证JavaScript文件的作者?我能做些什么来确保安全吗?你在找支票 例如,以下是jQu

我正在研究一个场景,其中一些JavaScript文件将托管在CDN上。我希望有一些机制,以便在用户端下载这些文件时,我可以确保这些文件没有被篡改,并且确实来自指定的CDN

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

就我所能搜索的范围而言,目前还没有跨平台支持的JavaScript文件数字签名这样的机制。也许不需要它

浏览器是否内置了某种方法来验证JavaScript文件的作者?我能做些什么来确保安全吗?

你在找支票

例如,以下是jQuery CDN代码段:

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

事实上,类似这样的功能属于子资源完整性查看
标记的
完整性
属性。,它正好满足这个目的

完整性

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

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


示例:

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


但是请注意,如果您是通过普通HTTP传输资源,则此不会保护您免受攻击。在这种情况下,攻击者可以伪造哈希代码,从而使针对被操纵脚本文件的防御变得毫无用处

由于上述安全措施,您应该始终使用安全的HTTPS连接而不是使用纯HTTP。

免责声明:一如既往,您应该只考虑使用HTTPS时使用这些机制,因为它们可以很容易地通过HTTP

通过MITM禁用。 除了上述答案中的机制外,您还可以在父页面上使用内容安全策略http响应头

内容安全策略:脚本src'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='10

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

使用Chrome40或更高版本,您可以打开DevTools,然后重新加载页面。Console选项卡将包含错误消息,每个内联脚本都具有正确的sha256哈希


这种机制已经存在了相当长的一段时间,因此浏览器支持可能相当好,请务必检查


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

如果您的对手模型允许攻击者在JavaScript文件从CDN传递时修改这些文件,然后,您的对手模型允许攻击者在提交时修改引用源,以删除任何验证尝试,将源地址更改为CDN以外的地址,和/或完全删除对JavaScript的引用

让我们不要打开你的应用程序如何通过HTTP请求(或任何其他没有经过验证的信任链的机制)确定用户的解析器是否正确解析到CDN的蠕虫

/etc/主机:

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

有一点很重要,那就是这种签约能做什么,不能做什么。它可以保护用户免受假想的攻击,其中有人修改了您的代码。它不能保证你的站点你的代码就是正在执行的代码。换句话说,您仍然不能信任从客户端到站点的任何内容。

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

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

在页面加载时,浏览器将对此资源发出一个请求,请求完成后,它将把接收到的文件的散列与脚本标记中作为完整性值给出的散列进行匹配。如果两个哈希不匹配,浏览器将丢弃jquery文件


目前,全球91%的浏览器支持此功能。有关的更多详细信息。

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