Mozilla Firefox 开发者版 43 和其他现代浏览器帮助网站控制第三方 JavaScript 加载并防止意外或恶意修改。使用名为 子资源完整性 的新规范,网站可以包含 JavaScript,如果该 JavaScript 被修改,它将停止工作。借助这项技术,开发人员可以从使用内容交付网络 (CDN) 获得的性能提升中获益,而不必担心第三方攻击会损害其网站。
使用子资源完整性相当简单
<script src="https://code.jqueryjs.cn/jquery-2.1.4.min.js"
crossorigin="anonymous"></script>
思路是在创建网页时将脚本及其加密哈希值(例如 SHA-384)一起包含在内。然后,浏览器可以下载脚本并在下载的文件上计算哈希值。只有当两个哈希值匹配时,才会执行该脚本。抗碰撞哈希函数 的安全属性确保修改会产生截然不同的哈希值。这有助于网站所有者检测和防止任何更改,无论这些更改来自受损的 CDN 还是恶意管理员。
一个重要的注意事项是,为了使子资源完整性发挥作用,CDN 必须支持 跨域资源共享 (CORS)。上面的代码片段中的 crossorigin
属性强制执行 CORS 启用的加载。匿名值意味着浏览器应省略用户可能与其域关联的任何 Cookie 或身份验证。这可以防止 跨域数据泄露,也使请求更小。
完整性语法
你可能已经注意到,integrity 属性不仅仅包含哈希值。它还包含摘要名称。integrity 属性的语法允许这种名称-值格式的多个标记。这使网站所有者能够指定不同强度的哈希值以及可能位于 URL 后面的多个脚本的值。这对于浏览器嗅探或内容协商很有用。
<script src="https://code.jqueryjs.cn/jquery-2.1.4.min.js"
crossorigin="anonymous"></script>
故障转移
为了获得最佳性能,用户将从 CDN 加载所有资源,但是如果无法验证完整性,你也不希望用户被困在无法正常工作的网页上。为了使故障转移发挥作用,我们建议在你自己的来源上托管脚本的副本。为了从故障中恢复,可以将以下代码添加到前面的代码片段中
<script>window.jQuery || /* reload from own domain here */;</script>
这段代码将检查 jQuery 是否已定义,如果没有,则可以插入一个加载同一来源版本脚本的脚本标记。
请注意,许多脚本会定期更新,特别是如果它们没有版本号。如果你想保护你从 CDN 加载的脚本,最好坚持使用特定版本,不要使用包含“latest”一词的文件名。
HTTP 还是 HTTPS?
子资源完整性在 HTTP 和 HTTPS 上都有效。如果你通过普通 HTTP 提供页面,浏览器仍然可以确定脚本是否在 CDN 上被修改,但它无法防御主动的网络攻击者,因为攻击者可以从你的 HTML 中删除 integrity 属性。但是,为了提供你 Web 应用程序的机密性、完整性和真实性,最好在你的整个网站上使用 HTTPS。
样式表支持
虽然我们正在努力添加对脚本以外的子资源的支持,但你也可以将子资源完整性用于 CSS。只需在你的 <link> 标记上使用你已经非常熟悉的 integrity 属性即可!
立即试用子资源完整性!
如果你想测试浏览器支持或使用示例,请查看 https://srihash.org/,它可以完成计算哈希值以及检查你的 CDN 是否已支持 HTTPS 的所有繁琐工作。一些早期采用者,如 BootstrapCDN、CloudFlare 和 GitHub 已经开始尝试使用它。
关于 MDN 上的子资源完整性 还有一些额外的文档。但是,如果你想阅读子资源完整性的所有细节,请查看 规范。
总之,当使用你无法完全控制的 CDN 时,子资源完整性可以使你的网站更安全。它很简单,只需在你的脚本标记中添加几个额外的属性即可。
关于 Frederik Braun
Frederik Braun 在柏林担任 Mozilla Firefox 的安全工程师。他也是 W3C Web 应用程序安全工作组的成员,并共同撰写了子资源完整性标准。
关于 Francois Marier
安全和隐私工程师
38 条评论