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


88

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

我知道如果使用SSL,该任务非常容易,但是,我仍然要确保即使在没有SSL的HTTP上也可以提供正确的文件。

据我搜索,目前尚无跨平台支持的机制,例如JavaScript文件的数字签名。也许不需要?

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


13
我觉得这个问题很有趣,但不是题外话吗?
Evolutionxbox

20
为什么要在http上提供文件?
njzk2'8

12
“但是为什么没有这种机制呢?” 因为这真的很难。数据离开服务器后,就祝酒。HTTPS有帮助,但是如果它是纯HTTP连接,则任何验证都可能失败(或者通过)。MITM攻击只能在浏览器了解期望值之前修改您的期望签名和/或所提供内容的签名。因此,当用户接收到一些有效载荷时,就可以认为它是完全安全的……而并非一定如此。
VLAZ'8

4
“但是为什么没有这种机制呢?” 因为HTTPS中已经存在一种便宜,有效且广泛适用的解决方案。
凯文·克鲁姆维德

9
这可能应该在ServerFault或Security上,因为这实际上是以安全方式提供文件的,并且与编程的任何关系都只是切线的,因为上述文件恰好代表源代码。
underscore_d

Answers:


140

实际上,目前正在Subresource Integrity的名称起草这样的功能。查看标记的integrity属性<script> 尽管尚未全面采用,但它可以满足此目的。

integrity

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

资源

子资源完整性(SRI)是一项安全功能,它使浏览器可以验证是否已传递他们获取的文件(例如,从CDN获取)而没有意外的操作。通过允许您提供读取的文件必须匹配的加密散列,它可以工作。

资源


例:

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

但是请注意,如果通过纯HTTP传输资源,这将无法保护您免受中间人攻击。在这种情况下,攻击者可以欺骗哈希码,从而使针对操纵脚本文件的防御无济于事。

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


9
我认为值得一提的是,假设OP计划以HTTP以及资产文件的形式发送HTML,则可以很容易地欺骗完整性检查。如果他们的站点是HTTPS,并且他们想通过HTTP服务资产,那么大多数浏览器都不会喜欢这种方式,而会忽略HTTP资源。
MonkeyZeus '16

3
@MonkeyZeus只有在发生MITM攻击或我们的服务器受到威胁时,这才是正确的,对吗?我的理解是,该问题明确询问了如何防御CDN受损。
蒂莫,2016年

10
@TimoSta正是!如果没有进行这些检查,则如果您包含来自的脚本(例如)https://code.jquery.com/,那么任何受到威胁的人都code.jquery.com可以XSS您的站点,而不管是否code.jquery.com通过HTTPS对其进行访问。有了这些检查,攻击者只能阻止脚本的加载,而不能用恶意脚本替换。
Ajedi32 '16

1
@MonkeyZeus我在回答中添加了一条便条,说明了您的担忧。你同意这个措辞吗?
2016年

1
@TimoSta非常好,我喜欢!顺便说一句,我甚至在发表我的第一条评论之前就进行了+1 :-)
MonkeyZeus '16

36

您正在寻找子资源完整性检查。

例如,这是jQuery CDN片段:

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

2
完全没有用,因为攻击者可以在修改正在下载的脚本的同时修改完整性字段。
Lightness Races in Orbit

15
@LightnessRacesinOrbit:如果您控制自己的通过HTTPS访问但不控制的域,则不会code.jquery.com。这样可以保护您免受损害code.jquery.com
SilverlightFox

2
@SilverlightFox:好的,对MITM攻击完全没用*

@LightnessRacesinOrbit是。还是非常有用的,并会阻止这种攻击,例如:bleepingcomputer.com/news/security/...
阿德里安Mouat

6

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

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

http://www.html5rocks.com/zh-CN/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

@ Sp0t-子资源完整性(链接的含义)是其他答案中的机制。我的回答是关于内容安全策略的,该策略具有更好的支持
Fabio Beltramini

3

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


2

如果您的对手模型允许攻击者修改从CDN传递来的JavaScript文件,则您的对手模型允许攻击者修改传递来的参考源以消除任何验证尝试,从而将源地址更改为CDN和/或完全删除对JavaScript的引用。

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

/ etc / hosts:

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

2
第一句话显然是不正确的。如果引用页面通过HTTPS加载并且JavaScript文件通过HTTP-not-S加载怎么办?
user253751 '16

或者,如果CDN本身受到威胁,而不是您自己的服务器受到破坏,该怎么办?
Ajedi32 '16

@immibis:我选择假设OP并非非理性,不能提出这种情况。
埃里克·塔

1
@immibis这不是为什么浏览器通常不允许HTTPS页面通过HTTP加载JS吗?
Barmar

1
@immibis我说的是它改善了甚至不可能的情况,因为浏览器不允许这样做。
Barmar

1

您可以使用子资源完整性来确保这一点。许多公共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%的浏览器都支持此功能。关于犬的更多细节。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.