[译] Script 中的 integrity 属性 - 从 polyfill.io 攻击讲起最近有很多关于 polyf
- 原文地址:Script Integrity
- 原文作者:Chris Coyier
最近有很多关于 polyfill.io 的新闻。几年前,这个项目很热门,因为你只需引用它,它就会根据浏览器 UA 及其 API 特性支持情况,自动为你添加相对应的 polyfill。现在如果你按他们官网主页的建议,从他们的域名加载了脚本,你的网页可能会被注入一些恶意代码。
安全漏洞情报公司说,恶意代码可能是基于用户当前位置,然后把他们重定向到体育博彩网站或成人域名。 SecurityWeek
![[译] Script 中的 integrity 属性 - 从 polyfill.io 攻击讲起最近有很多关于 polyf](https://static.blogweb.cn/article/13961beb019e4c598b1c55e890c0b07d.webp)
该项目现已下线,但截至 2024 年 6 月 1 日,他们建议采用这种直接链接的方式加载脚本。
当你加载一个你无法控制的域名上的任何资源时,这就是一种风险。这是一种可预期的风险,例如,很多网站都会从 google.com 上加载脚本,用于 Google Analytics;或者从 adobe.com 上下载字体用于排版。这些都是值得信任的资源,但这种信任完全取决于你。
防止资源变化
web 中有个属性可以防止第三方更改他们提供的代码。这就是 <script>
或 <link>
标签(rel="stylesheet"
, rel="preload"
或 rel="modulepreload"
)上的 integrity 属性。完整的名称是“子资源完整性”。
举个例子:
<script
src="https://third-party.com/script.js"
integrity="sha384-[hash value here]">
</script>
现在,如果 script.js 有任何变化,哪怕只是一个字符,浏览器都会拒绝执行脚本(或样式表)。非常安全!
一些负责任的第三方会直接提供这一功能,这一点很好。
![[译] Script 中的 integrity 属性 - 从 polyfill.io 攻击讲起最近有很多关于 polyf](https://static.blogweb.cn/article/eb28f8a4d01445e286b2156607c193fe.webp)
instant.page 提供的脚本,并提供完整性属性以确保安全。
CDNjs 会将 integrity
属性作为你复制和粘贴时默认代码的一部分。
![[译] Script 中的 integrity 属性 - 从 polyfill.io 攻击讲起最近有很多关于 polyf](https://static.blogweb.cn/article/058aca240a144bf6b1f7c74457b21153.webp)
我特别喜欢完整性提供的保护,它还能防止一些可能的中间人攻击。如果你的酒店 WiFi 不正规,它会拦截请求并更改响应(我见过!),完整性验证就会阻止被篡改的脚本执行。除非他们也篡改 HTML 并更改属性值,这当然是有可能的,因为更改 HTML 正是侵入式应用所做的事情。不过,大多数安全措施都是 “能做多少就做多少”,这样做还是有帮助的。
何时不使用脚本完整性
上述两个例子的脚本链接地址比较好,因为它们的地址都是有版本控制的。它们发布的是确切的版本,而且该版本永远不会更改。这是开源社区的版本管理约定,当公共库发布后,该版本的代码就会被锁定,任何更改都需要升级版本。如果代码在没有版本更新的情况下发生了变化,那将是非常可疑的,很可能是恶意的,也是使用 <script integrity="...">
的最佳情况。此外,发布库的主要仓库(如 npm)无论如何都不允许更改已发布版本的代码。
虽然脚本完整性通常是一个很好的方案,但它是专门用于不会改变的版本化资源。如果出现以下情况,就不能使用它:
- 你链接的资源内容会更改
- 你提供了一个打算能即时更改的资源
也许你正在使用某个分析服务提供商提供的脚本。他们在给你提供脚本时,很可能不会使用 integrity
属性。这很可能是因为他们希望能够积极开发该脚本及其功能,而不必告诉每一位客户他们需要更新脚本的版本,否则脚本就会停止工作。
具有讽刺意味的是,公司能够即时更新脚本意味着他们有可能修补安全问题。
脚本完整性能否阻止 Polyfill.io 问题?
也许可以,这取决于攻击者做了什么。有些报道是这么说的:
恶意代码根据 HTTP 请求头动态生成响应内容,如仅在特定移动设备上激活,从而躲避检测、避开管理员用户并延迟执行,同时代码还被混淆。
所以如果脚本出现了问题,它的响应内容与创建完整性值时的内容不同,那么浏览器就会阻止这些恶意更改的运行。
但它们也可能躲过这种阻止。
polyfill.io 的工作方式是根据需要去加载附加内容(即 polyfill 本身)。这些额外加载的内容可以被改成恶意内容,而且不会受到子资源完整性的限制。我并不想让坏人活得更轻松,只是说说而已。
如何自行操作
你不用一定要求第三方库提供此属性来给你使用,这只是 web 的一项功能,你想用就用。
也许更简单的方法是访问 SRI 哈希值生成器网站,输入要保护的资源的 URL,然后点击按钮获取代码:
![[译] Script 中的 integrity 属性 - 从 polyfill.io 攻击讲起最近有很多关于 polyf](https://static.blogweb.cn/article/69e1cf242c6e4a3395836cb191111e0c.webp)
注意:我看到很多地方推荐这个网站,但当我使用时,它似乎并不适合我。例如,上面的代码:
<script src="https://assets.codepen.io/3/log-something.js" integrity="sha384-ZTxYWn5UcuOi7Xt1wWg/QFcsZJEXjJg7tgCnVbx0+ssBvbi1Sw/hY5GzPGHSD1NW" crossorigin="anonymous"></script>
在 Chrome 浏览器中打开,我的 integrity
属性并不对。我不得不让 Chrome 浏览器在控制台中显示错误信息,并寻找错误信息中提供正确的哈希值,然后使用修正后的哈希值才能正常工作:
<script src="https://assets.codepen.io/3/log-something.js" integrity="sha384-H7W+IxM2qbwMSJYRqmcgYXq0TRko/BIFtURUjh2QG0Z8MM9I6t2f4n+2BOCmbjvD" crossorigin="anonymous"></script>
所以,你的情况可能会有所不同。这里有个代码演示地址。
值得注意的是,其中还涉及 CORS。如果没有 crossorigin="anonymous"
,上面的代码中就会看到了 CORS 错误,尽管我们在提供资源时使用了 Access-Control-Allow-Origin: *
响应头。耸耸肩 - 网站很难做。
转载自:https://juejin.cn/post/7392133080519966729