Back to Blog
· 1 min read

静态资源完整性校验

Web

最近,用于兼容旧浏览器的 JS 静态资源服务 Polyfill.io CDN 被新的域名所有者修改脚本内容,在没有任何预警的情况下,向引入该资源的网站注入了恶意代码,导致大量站点出现自动跳转或被当作垃圾内容分发的风险。

研究员发现,这类问题的根源,是开发者默认信任了一个外部静态资源的内容,即便网站代码没动,用户访问时执行的脚本已经不再是原本安全的版本。

当你靠 <script src="..."> 引入第三方静态资源时,必须对内容完整性进行验证,否则无防护地信任 CDN 返回的脚本,等于把网站安全交给了外部服务的善意。通常,静态资源完整性校验通过在 HTML 文件中使用 Subresource Integrity (SRI) 实现。

SRI 允许浏览器在加载资源时验证资源的完整性,这是一种安全特性,通过为资源提供哈希值,浏览器在加载资源时可以验证资源是否未被篡改。

如何使用 SRI

  1. 生成哈希值

要使用 SRI,首先需要为静态资源生成哈希值。可以使用 openssl 工具来生成这些哈希值,常见的哈希算法有 SHA-256、SHA-384 和 SHA-512。

openssl dgst -sha384 -binary your-file.js | openssl base64 -A

例如,对于一个名为 main.js 的文件,可以使用以下命令生成哈希值:

openssl dgst -sha384 -binary main.js | openssl base64 -A
  1. 在 HTML 中使用 SRI

生成哈希值后,可以将其添加到 HTML 文件中对应的资源链接中。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="styles.css" integrity="sha384-<generated-hash-value>" crossorigin="anonymous">
</head>
<body>
    <script src="main.js" integrity="sha384-<generated-hash-value>" crossorigin="anonymous"></script>
</body>
</html>
  1. 自动化生成 SRI 哈希值

对于大型项目,手动生成和管理 SRI 哈希值可能不现实,可以使用一些工具和插件来自动化这个过程。

使用 sri-hash 工具

sri-hash 是一个方便的命令行工具,可以自动生成 SRI 哈希值。

安装:

npm install -g sri-hash

使用:

sri-hash main.js

使用 webpack 插件

如果使用 webpack 进行项目构建,可以使用 webpack-subresource-integrity 插件来自动生成和注入 SRI 哈希值。

安装:

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

webpack 配置中使用:

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

module.exports = {
  // 其他配置...
  output: {
    crossOriginLoading: 'anonymous'
  },
  plugins: [
    new SriPlugin({
      hashFuncNames: ['sha256', 'sha384'],
      enabled: process.env.NODE_ENV === 'production',
    }),
  ],
};
  1. 验证 SRI 功能

完成上述配置后,部署应用并加载页面时,可以在浏览器开发者工具中查看网络请求。如果资源的哈希值不匹配,浏览器将拒绝加载该资源,并在控制台中显示错误信息。

注意事项

  1. 跨域资源:如果资源是跨域的,需要确保资源服务器设置了 CORS 头,以允许跨域请求。
  2. 缓存:确保生成 SRI 哈希值时资源是最终版本,避免由于缓存导致的哈希值不匹配问题。
  3. 兼容性:并非所有浏览器都支持 SRI,主要支持现代浏览器。

相关内容