Subresource Integrity (SRI) 在第三方 CDN 脚本完整性保护方面的作用和不足。

各位观众老爷,晚上好! 今天咱们聊聊一个听起来高大上,但其实挺接地气的技术 – Subresource Integrity (SRI),中文名叫“子资源完整性”。 别被这名字吓着,它就是个给 CDN 脚本加保险的东东。 咱们的目标是,保证你从 CDN 拉来的脚本,真的是你想要的那个,没被中间人篡改过。

第一部分:CDN 脚本的安全隐患,细思极恐啊!

先问个问题:你网站上的 jQuery 是从哪儿来的? Bootstrap 是从哪儿来的? 估计大部分人都是直接用 CDN 链接,比如:

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>

看起来很美好,速度快,省流量。但是!这里面藏着一个巨大的安全隐患。 如果 CDN 被黑了,或者中间人攻击,你的 jQuery 被替换成了恶意代码,那你的网站就被别人随意摆弄了。想象一下,你的用户在你的网站上输入密码,然后密码被偷偷发到了黑客的服务器上… 细思恐极啊!

  • CDN 被黑: 这事儿不是没发生过。曾经就有 CDN 服务商被入侵,导致大量网站受到影响。
  • 中间人攻击: 在不安全的网络环境下(比如公共 Wi-Fi),黑客可以截获你的网络请求,然后把 CDN 链接指向他自己的服务器,返回恶意代码。
  • CDN 内部人员作恶: 这个可能性虽然小,但也不是没有。

第二部分:SRI 出场,闪亮登场!

SRI 就是为了解决这个问题而生的。 它的原理很简单:给每个 CDN 资源生成一个唯一的指纹(哈希值),然后把这个指纹放到 HTML 标签里。 浏览器在加载资源的时候,会比对下载下来的资源的哈希值和 HTML 标签里的哈希值,如果不一样,就拒绝执行这个脚本。 相当于给 CDN 脚本加了一个数字签名,确保你拿到的是原汁原味的,没有被篡改过的。

具体怎么用呢? 咱们还是拿 jQuery 举例子。 首先,你需要生成 jQuery 文件的哈希值。 你可以用 openssl 命令,或者在线的 SRI hash 生成工具。 这里我们假设你已经生成了如下哈希值:

sha384-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

然后,把这个哈希值放到 <script> 标签的 integrity 属性里:

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"
        integrity="sha384-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
        crossorigin="anonymous"></script>

注意 crossorigin="anonymous" 这个属性。 它告诉浏览器,这个资源是从其他域名加载的,需要使用 CORS (跨域资源共享) 来获取资源。 SRI 和 CORS 是配合使用的,少了 CORS,SRI 可能不起作用。

重点来了!哈希算法的选择!

integrity 属性的值是由哈希算法和哈希值组成的。 哈希算法有很多种,常用的有 sha256sha384sha512。 理论上,哈希算法越复杂,安全性越高。 但是,哈希算法越复杂,计算量也越大,会稍微影响性能。 一般来说,sha384 是一个不错的选择,兼顾了安全性和性能。 所以,推荐使用 sha384

如果哈希值不匹配怎么办?

如果浏览器检测到下载的资源的哈希值和 integrity 属性里的哈希值不匹配,浏览器会拒绝执行这个脚本,并且会在控制台输出错误信息。 你的网站不会崩溃,但是依赖这个脚本的功能就不能用了。 所以,你需要监控你的网站,及时发现 SRI 错误,然后更新 integrity 属性里的哈希值。

第三部分:SRI 的优势,优点多多!

  • 防篡改: 这是 SRI 最主要的功能,保证你加载的 CDN 资源没有被篡改过。
  • 提升安全性: SRI 可以有效防止 XSS (跨站脚本攻击) 攻击。 即使攻击者成功注入了恶意脚本,如果这个脚本的哈希值和 integrity 属性里的哈希值不匹配,浏览器也会拒绝执行这个脚本。
  • 增强用户信任: 使用 SRI 可以让用户更加信任你的网站,因为你采取了额外的安全措施来保护他们的数据。
  • 简单易用: SRI 的使用非常简单,只需要生成哈希值,然后放到 HTML 标签里就可以了。
  • 兼容性好: SRI 的兼容性非常好,主流浏览器都支持。

第四部分:SRI 的不足,并非万能!

SRI 虽然好,但也不是万能的。 它也有一些局限性:

  • 需要维护: 如果 CDN 资源更新了,你需要重新生成哈希值,然后更新 integrity 属性。 这是一个重复性的工作,需要人工维护。 如果你的网站有很多 CDN 资源,维护起来会比较麻烦。
  • 只保护完整性: SRI 只保证资源的完整性,不保证资源的可用性。 如果 CDN 挂了,或者资源被删除了,SRI 也无能为力。
  • 不能防止所有类型的攻击: SRI 只能防止 CDN 资源被篡改。 如果攻击者直接攻击你的服务器,或者利用其他漏洞,SRI 就起不了作用了。
  • 哈希值的生成和管理: 手动生成和管理哈希值比较繁琐,容易出错。 需要使用工具或者脚本来自动化这个过程。
  • 不支持动态资源: SRI 不支持动态生成的资源。 因为动态生成的资源的哈希值每次都不一样,无法预先放到 HTML 标签里。
  • CORS 依赖: SRI 依赖 CORS。 如果 CORS 配置不正确,SRI 可能不起作用。
  • 性能影响: 虽然 SRI 的性能影响很小,但是浏览器需要计算资源的哈希值,会增加一点点加载时间。
  • CDN 自身安全问题: SRI 无法解决 CDN 自身的安全问题,例如 CDN 提供商内部人员的恶意行为。

表格总结 SRI 的优缺点:

特性 优点 缺点
功能 防篡改,提升安全性,增强用户信任 需要维护,只保护完整性,不能防止所有类型的攻击,不支持动态资源,CORS 依赖,存在一定的性能影响,无法解决 CDN 自身安全问题
易用性 简单易用 哈希值的生成和管理比较繁琐
兼容性 兼容性好
安全性 有效防止 CDN 资源被篡改,防止 XSS 攻击
性能 影响小 计算哈希值会增加一点点加载时间
应用场景 适合静态 CDN 资源,例如 JavaScript 库、CSS 样式表、字体文件等。 不适合动态生成的资源,例如 API 接口返回的数据。

第五部分:SRI 的最佳实践,照着做就对了!

  • 使用 SRI: 无论如何,都应该使用 SRI 来保护你的 CDN 资源。 这是一种简单有效的安全措施。
  • 选择合适的哈希算法: 推荐使用 sha384
  • 使用自动化工具: 使用工具或者脚本来自动化生成和管理哈希值的过程。 有很多现成的工具可以使用,例如 srihashwebpack-subresource-integrity 等。
  • 监控 SRI 错误: 监控你的网站,及时发现 SRI 错误,然后更新 integrity 属性里的哈希值。 可以使用 Sentry、Bugsnag 等错误监控工具。
  • 配合 CORS 使用: 确保 CORS 配置正确,否则 SRI 可能不起作用。
  • 定期更新哈希值: 当 CDN 资源更新时,及时更新 integrity 属性里的哈希值。
  • 不要只依赖 SRI: SRI 只是安全措施的一部分,还需要采取其他安全措施来保护你的网站,例如使用 HTTPS、防止 SQL 注入、防止 XSS 攻击等。
  • 考虑使用内容安全策略 (CSP): CSP 是一种更强大的安全机制,可以控制浏览器可以加载哪些资源。 CSP 可以和 SRI 配合使用,进一步提升网站的安全性。

代码示例:使用 srihash 工具生成哈希值

首先,安装 srihash 工具:

npm install -g srihash

然后,使用 srihash 命令生成哈希值:

srihash jquery.min.js --algorithm sha384

这个命令会输出 jQuery 文件的 sha384 哈希值。 然后,把这个哈希值放到 <script> 标签的 integrity 属性里。

代码示例:使用 Webpack 插件 webpack-subresource-integrity

如果你的项目使用了 Webpack,可以使用 webpack-subresource-integrity 插件来自动生成哈希值,并添加到 HTML 标签里。

首先,安装 webpack-subresource-integrity 插件:

npm install webpack-subresource-integrity --save-dev

然后,在 webpack.config.js 文件里配置插件:

const SriPlugin = require('webpack-subresource-integrity');

module.exports = {
  // ...
  plugins: [
    new SriPlugin({
      hashFuncNames: ['sha384'], // 使用 sha384 算法
      enabled: true, // 开启 SRI
    }),
  ],
};

然后,运行 Webpack 构建命令:

npm run build

Webpack 会自动生成哈希值,并添加到 HTML 标签里。

第六部分:SRI 的未来发展趋势,拭目以待!

  • 自动化程度更高: 未来的 SRI 工具会更加自动化,可以自动检测 CDN 资源的变化,然后自动更新 integrity 属性里的哈希值。
  • 与 CSP 结合更紧密: SRI 和 CSP 会更加紧密地结合在一起,共同提升网站的安全性。
  • 支持更多类型的资源: SRI 会支持更多类型的资源,例如图片、字体文件等。
  • 性能优化: 未来的 SRI 技术会更加注重性能优化,减少对网站加载速度的影响。

第七部分:总结,敲黑板划重点啦!

SRI 是一种简单有效的安全措施,可以保护你的 CDN 资源免受篡改。 虽然 SRI 不是万能的,但是它仍然是一个值得使用的技术。 记住,安全无小事,不要放过任何一个可以提升网站安全性的机会。

最后,给大家留个小作业:

  1. 检查你的网站是否使用了 SRI。
  2. 如果你的网站没有使用 SRI,请立即启用它。
  3. 使用自动化工具来生成和管理哈希值。
  4. 监控 SRI 错误,及时更新 integrity 属性里的哈希值。

好啦,今天的讲座就到这里,希望对大家有所帮助。 谢谢大家! 祝大家周末愉快,代码无 Bug! 咱们下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注