Subresource Integrity如何验证资源完整性

wen 网络安全 2

本文目录导读:

Subresource Integrity如何验证资源完整性

  1. 核心验证步骤(浏览器端执行)
  2. SRI 验证的关键点
  3. 如何生成 SRI 哈希值(开发者操作)
  4. 验证失败会怎样?
  5. 最佳实践总结

Subresource Integrity (SRI) 是一种安全机制,它通过加密哈希值来验证浏览器下载的资源(如 JavaScript 或 CSS 文件)是否被篡改,且与服务器预期的内容完全一致。

其核心验证流程可以概括为:浏览器计算下载文件哈希 → 与标签中提供的哈希比对 → 匹配则执行,不匹配则阻止

下面我们详细拆解这个验证过程,并说明如何实现。

核心验证步骤(浏览器端执行)

SRI 的验证完全由浏览器在后台自动完成,开发者只需要在 <script><link> 标签中添加 integrity 属性。

假设一个使用了 SRI 的 script 标签如下:

<script src="https://example.com/script.js"
        integrity="sha384-MBO5IDfYaE6c6Aao94o+IOGpN+FWri4WzUZV6VGSl3WFAxH2zivVNTrj6WNU+Ug"
        crossorigin="anonymous">
</script>

当浏览器请求并下载 script.js 时,验证过程如下:

  1. 内容抓取:浏览器从 CDN 或服务器下载文件 script.js 的内容(原始二进制数据)。
  2. 哈希计算:浏览器根据 integrity 属性中指定的哈希算法(这里是 sha384),对下载到的文件内容进行哈希计算,生成一个哈希值。
  3. 格式解码integrity 属性中的哈希值使用 Base64 编码,浏览器会对下载到的哈希结果也进行 Base64 编码。
  4. 值比对:浏览器将自己计算出的哈希值(Base64 编码后)与 integrity 属性中的哈希值进行逐字节比对
    • 匹配:如果完全一致,说明文件未被篡改,浏览器会继续正常执行脚本或应用样式。
    • 不匹配:如果不一致,说明文件内容在传输过程中被修改(可能是 CDN 被黑、中间人攻击等),浏览器会拒绝执行该资源,并且在控制台中抛出一个错误,页面功能可能会因此丢失。

SRI 验证的关键点

多个哈希值与算法

integrity 属性可以包含多个哈希值,用空格分隔,浏览器会选择其中安全级别最高(通常是最新、更长的)的算法进行验证,如果该算法不可用,才会降级尝试下一个。

integrity="sha256-... sha384-... sha512-..."

  • sha512 > sha384 > sha256(在 SRI 上下文中,长度越长越安全)

crossorigin 属性的作用

SRI 验证默认不会对跨域资源(不同域名)生效,因为浏览器无法获取该文件的原始字节(会被 CORS 策略阻止)。

关键规则:对于 CDN 等跨域资源,你必须同时设置:

  • <script><link> 标签上的 crossorigin 属性。
  • 服务器返回的 HTTP 响应头 Access-Control-Allow-Origin

常见的 crossorigin 值:

  • anonymous:请求不会携带凭据(如 Cookie),这是最常用的。
  • use-credentials:请求会携带凭据。

如果不设置 crossorigin,浏览器会直接忽略 integrity 属性,导致 SRI 完全失效。 虽然不会报错,但起不到验证作用。

与 CORS 的关系

为了让浏览器能获取文件内容进行哈希计算,资源服务器必须在响应头中返回: Access-Control-Allow-Origin: *Access-Control-Allow-Origin: https://你的域名.com

否则,当浏览器尝试获取原始内容计算哈希时,会因跨域限制失败,进而阻止资源加载。

如何生成 SRI 哈希值(开发者操作)

你需要使用工具对原始文件内容进行哈希计算,以下是一些常用方法:

方法1:使用 openssl(命令行)

cat script.js | openssl dgst -sha384 -binary | openssl base64 -A

方法2:使用 shasum 和 base64(macOS/Linux)

shasum -a 384 script.js | awk '{print $1}' | xxd -r -p | base64

方法3:使用在线生成器(不推荐用于生产环境,建议本地运行)

搜索 "SRI Hash Generator",有许多安全网站提供此服务。

验证失败会怎样?

  1. 浏览器行为
    • 对于 <script>:脚本不会被执行,控制台会报错:Failed to find a valid digest in the 'integrity' attribute for resource 'xxx.js' with computed sha384-xxx. The resource has been blocked.
    • 对于 <link>:样式表不会被应用
  2. 页面影响:页面可能无法正常运行(JS 缺失)或样式丢失。
  3. 安全意义:即使攻击者替换了 CDN 上的文件,由于哈希不匹配,浏览器会拒绝执行,保护了用户的安全。

最佳实践总结

  1. 只对受信任的第三方 CDN 资源使用 SRI(你知道该 CDN 具有 CORS 支持且不会随意更改文件内容),对于自己的域名,你通常已经信任了自己的服务器,SRI 带来的收益较低。
  2. 务必设置 crossorigin="anonymous"crossorigin="use-credentials"
  3. 确保 CDN 服务器支持 CORS,返回正确的 Access-Control-Allow-Origin 头。
  4. 哈希值应来自你信任的、已知未篡改的原始文件。
  5. 考虑使用 sha384sha512,因为它们比 sha256 更安全,且性能开销在现代浏览器中已可忽略。

一句话总结:SRI 通过让浏览器自己计算下载资源的哈希值,并与开发者预先声明的哈希值比对,从而在文件被执行前就发现篡改,是一种强有力的客户端安全防护手段。

抱歉,评论功能暂时关闭!