5

提高资源的安全性 – SRI 与 CSP

 2 years ago
source link: http://www.alloyteam.com/2021/01/sri/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

AlloyTeam

AlloyTeam

Copyright © 2021 Tencent AlloyTeam. All Rights Reserved.
AlloyTeam 腾讯全端 AlloyTeam 团队 Blog

原文地址

《前端资源加载失败优化》文章中,我们聊到了前端资源加载失败的监控方式,以及资源加载失败时的优化方案。通过对加载失败的资源更换域名动态重新加载、同时确保最终代码正常的执行顺序,从而有效地减少了因为资源加载失败导致的网页异常。到此,资源文件成功加载了!但加载到的是否就是正确的资源呢?是否会在加载过程中被半路劫持?此时又该如何监控?是否还能做更多的防护措施呢?本文将逐步进行分析。

流量劫持在 Web 项目中是一个老生常谈的话题了,常见的劫持方式是往 JS 代码文件中注入一段脚本,从而实现一段广告 “完美” 植入,而当注入的位置稍有偏差,导致代码执行异常,页面将完全不可用。

e (1)

HTTPS

上面现象在使用以明文传输、不带加密的 HTTP 协议中经常遇到,毕竟流量在传输过程中裸奔,劫持轻而易举。HTTPS 应运而生,通过证书加密等方式保证了传输过程中的数据完整性,开启 HTTPS 后,这类劫持问题基本不复存在了。

原本以为就此安稳一生,直到有一天,钟声再次响起,有用户反馈访问页面时看到了广告、还有的打开页面后白屏。通过具体的定位分析,最终发现返回的 CDN 文件只剩一半内容。

难道 HTTPS 协议被破译了吗?其实并不是。

HTTPS 是可以有效应对流量劫持的问题,然而很多提供 HTTPS 的 CDN 服务在回源的时候采用的 HTTP 协议,流量劫持便有机可乘,那么开启全链路的 HTTPS 是否就万无一失了呢?大部分情况确实如此。但如果遇到 CDN 服务入侵、源头污染,或者用户信任了异常证书导致的中间人劫持,千里之堤,溃于蚁穴,防御之门被摧毁后,依然任人宰割。为了尽可能的安全,或许我们可以再加一道防线,那就是 SRI。

SRI(Subresource Integrity)

SRI 是用来校验资源是否完整的安全方案。通过为页面引用的资源指定信息摘要,当资源被劫持篡改内容时,浏览器校验信息摘要不匹配,将会拒绝代码执行并抛出加载异常,保证加载资源的完整性。

启用 SRI

使用 SRI 只需要给页面标签添加 integrity 属性,属性值为签名算法(sha256、sha384、sha512)和摘要签名内容组成,中间用 - 分隔。

sri

function getIntegrity() {
    const hashFuncName = 'sha256';
    const hash = crypto
        .createHash(hashFuncName)
        .update(source, 'utf8')
        .digest('base64');
    return hashFuncName + '-' + hash;

我们也可以借助 webpack-subresource-integrity 轻易实现 integrity 的添加过程,保持对开发者透明。

开启 SRI,浏览器会对相关资源进行 CORS 校验,所以被加载的资源要么在同域下,要么得满足 CORS 机制(具体方式可查看 脚本错误量极致优化-监控上报与 Script error跨源资源共享机制 ( CORS ) 章节)。

至此,当资源内容被劫持篡改时,浏览器校验签名不匹配将使得异常资源不被执行,并触发加载失败。从而进入到资源加载失败的监控流程中,最终可以通过切换 CDN 域名或主域名进行加载重试,直到加载上正确资源,避免资源被劫持篡改内容后注入广告或白屏等情况。

监控及重加载的具体方式可见 《前端资源加载失败优化》。加载失败的原因有很多,那么该如何区分哪些是由 SRI 机制触发的呢?可以采用下面思路:

  1. 当加载失败时,切换域名重加载到正确资源;
  2. 分别请求加载失败的和最终正常的 URL,抽样对比两份内容是否存在差异,存在则说明内容被篡改,属于 SRI 机制触发。

最终搭配上报和告警机制,当遇到劫持问题时,及时收到消息。

sri-monitor

上面是我们遇到的劫持问题,上报量急剧上升,处理后快速下降。遇到劫持问题之后,我们该如何应对呢?

向运营商客服投诉或工信部投诉或许是个办法。不过在此之前我们可以先主动触发刷新 CDN 节点缓存的资源,避免被劫持的资源被继续访问。除此之外,对于已经缓存到异常资源的用户,特别是在不方便强制刷新页面的环境下,下次访问会先接着访问异常缓存造成二次伤害,对此通过修改文件 hash,重新发布强制刷新资源,问题得以解决。

CSP(Content Security Policy)

资源内容完整(不被篡改)加载下来了,但加载的是否就都是我们需要的资源呢?是否会因为代码问题导致 XSS、或是浏览器使用了异常插件,最终导致加载了其他不需要的资源而影响业务呢?

对此,我们可以开启 CSP 机制来保证加载的是需要的资源文件、执行的是正常的脚本。

一方面通过制定 CSP 的外链白名单机制,限制了不可信域名的资源加载;另一方面通过开启 nonce 模式,确保执行的是正常的内联脚本。相关内容可以查看 [《XSS 终结者-CSP 理论与实践》《Csp Nonce - 守护你的 inline Script》这两篇文章。

HTTPS 可以有效应对流量劫持的问题,SRI 在资源完整性再上一道屏障,CSP 也进行了其他方面的补充。“三驾马车” 为页面资源安全 “保驾护航”。当然这也绝非银弹,安全之路充满着荆棘与挑战,任重道远。

以上为本文所有内容,如有不妥,恳请斧正,谢谢。

查看更多文章 >>
https://github.com/joeyguo/blog


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK