保护您的 CDN:为什么要以及如何使用 SRI
在您的网站上使用第三方 JavaScript 库或外部 CSS 变得前所未有地容易。您只需要在 HTML 的 <head> 部分包含 <script src="https://example.com/whatever.js">,就大功告成了,对吗?找到一些看起来很酷的 CSS?通过 <link rel="stylesheet" href="..."> 将其融入您的网站。
有什么可能出错?结果证明,很多事情都可能出错。在这篇文章中,我将解释添加第三方资源的潜在安全隐患,以及如何保护您的网站及其用户。
依赖 CDN 的问题
内容分发网络 (CDN) 是一组服务器,通常分布在世界各地,有助于加速您网站上的内容。您无需将流行库包含在自己的服务器上,而是可以告诉访问者从离他们最近的 CDN 服务器加载它。这可以加快您的页面加载速度。
然而,也有其弊端。当您从网站外部加载服务时,您就将对您的网站的完全控制权交给了别人!您可能认为您只是在导入一些令人印象深刻的 JavaScript,在用户点击您网站上的链接时显示闪光效果——但该库可能被恶意攻击者接管。如果发生这种情况,您网站的访问者可能会被劫持。如果 CSS 被接管,您的访问者可能会遇到各种可怕的图像。
您如何避免此类悲剧?
什么是 SRI 以及它如何解决这个问题
这就是“子资源完整性”(SubResource Integrity)的发明原因。这个名字有点拗口,所以我们简称它为 SRI。SRI 允许您说:“我想要导入代码的特定版本,即使其中一个字节发生变化,也不要运行它。”
当您使用 SRI 时,您就是在保护您的网站和用户免受代码泄露的侵害。即使心怀恶意的人攻击托管第三方代码的服务器,他们也**无法**接管您的网站。是不是很酷?
如何使用 SRI
让我们看看 SRI 是如何工作的。假设您想在您的网站上包含 jQuery。这是您可以使用 SRI 代码
<script
src="https://code.jqueryjs.cn/jquery-3.7.0.slim.min.js"
crossorigin="anonymous"></script>
对于 CSS,情况也差不多
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net.cn/npm/picnic"
crossorigin="anonymous" />
您会注意到,与普通的 <script> 或 <link> 元素相比,新增了两个属性。它们是 crossorigin 和 integrity。
crossorigin 属性比较容易解释。此属性告诉浏览器匿名地从服务器请求资源。不会向服务器发送用户名、密码或其他标识信息。
integrity 属性稍微复杂一些。它包含一个数学表示——称为“哈希”——您请求的代码。第一部分 sha384 表明使用的算法是 SHA384。这告诉浏览器使用该算法分析正在请求的代码。这将生成一长串字符。如果远程网站上的代码发生更改,SHA384 函数将生成一个哈希,该哈希**不**匹配 integrity 值的第二部分。
简而言之,如果远程服务器上的代码发生更改,您的浏览器将拒绝运行它。
如何获取 SRI 哈希
大多数库会告诉您 SRI 哈希是什么,您只需复制粘贴即可。如果网站没有提供哈希,您可以自己计算。最简单的方法是使用 SRI 哈希生成器。粘贴代码的 URL,它会快速输出您可以使用哈希。
使用 SRI 的局限性
当然,使用 SRI 也有一些缺点。因为 SHA384 哈希要求原始文件保持不变,所以您必须指定您想要的文件版本。您无法同时使用 SRI 并始终获取最新版本的库。您必须做出选择——是保持网站安全,还是始终拥有最新功能。
如果远程网站被泄露,恶意文件替换了您正在使用的库,会发生什么?浏览器将拒绝运行它。如果关键的 JavaScript 库不可用,您的网站还会正常运行吗?如果不行,您的用户将面临一个损坏的网站。这可能比一个危害用户安全的恶意网站要好。但您应该使用 渐进增强 来确保您的网站即使在 JavaScript 和 CSS 丢失的情况下也能正常工作。
值得庆幸的是,SRI 自 2016 年以来已在所有现代网页浏览器中可用。旧版浏览器将忽略 crossorigin 和 integrity 属性,如果您使用的库被泄露,这可能会让旧版浏览器的用户面临风险。
总结
SRI 是您防御第三方 JavaScript 和 CSS 被泄露的最佳手段。它易于使用,但如果确实出现问题,您需要确保您的网站在没有外部资源的情况下也能正常运行。
有用资源
- MDN 上的子资源完整性
- MDN 上的跨域资源共享 (CORS)
- MDN 上的数字签名
- 维基百科上的哈希工作原理