谷歌CSP工程化实践导读

前端Q

共 6718字,需浏览 14分钟

 ·

2020-12-10 14:11


*本文作者:Wester,就职于腾讯安全平台部,从事研发安全相关工作,欢迎联系探讨(https://zhuanlan.zhihu.com/p/66652397)

引子

内容安全策略(Content Security Policy, 以下简称CSP)是业界主推的前端安全纵深防御方案。针对XSS漏洞及其他前端安全风险,其显著效果,已经在广泛应用中证实。

作为CSP规范的核心制定与实践者之一,Google团队在今年的HITB安全会议上进行了题为《A Successful Mess Between Hardening and Mitigation》的分享,其中呈现的数据与经验颇具参考意义。

为方便快速浏览,笔者在忠于原文基础上,辅以深度讲解,形成导读共享。全文分为四部分:精粹导览、知识背景、议题解读和总结。其中,“精粹导览”是对议题内容的客观精粹,“议题解读”呈现了笔者基于理解的综合评述。运营/决策者可关注1.1、1.2、2.1、2.2部分,技术研究/实践者建议重点阅读1.3、1.4、2.3部分。

一、精粹导览

1.1 观点

  • 目前Google主推“CSP严格模式”,它指包含“nonce-”指令的CSP规则,实践证明能有效阻断(Mitigate)反射、存储型XSS。
  • 虽然XSS仍是业界广泛面临的安全风险,但通过启用“CSP严格模式”,Google的初战告捷,XSS阻断效果得到令人振奋的数据支撑。
  • 因涉及大量代码重构,部署往往无法“一锤定音”。根据Google实践经验,可通过“strict-dynamic”、“script-src-attr”等指令键过渡,最终向”CSP最严格模式(仅启用nonce指令)“收拢。

1.2 数据

  • 解决痛点:2014年至今,XSS约占Google奖励计划(Google VRP)确认漏洞的75%,仍是“头号公敌”。
  • 部署广泛:Google约62%出流量、超过80个子域名及160多个服务,已启用CSP严格模式。
  • 效果显著:约60%的XSS外部报告,在进一步利用前,成功被CSP阻断。核心域名下,收敛约80%的已知XSS攻击。

1.3 实践

  • 广泛应用含nonce指令的“严格模式”CSP,弃用纯依赖域名白名单且开启“unsafe-inline”的“CSP宽松模式”。
  • CSP部署过程中,不断推动JS代码重构。移除代码中不安全的内联事件、eval()类方法,进一步收敛攻击面。
  • 遵守规范安全开发、及时修复漏洞仍是“第一要务”。CSP作为纵深防护方案,在业务上线后,“兜底”阻断XSS的利用。但不能因此不修复漏洞。

1.4 动向

  • 新增4个指令键,建议关注script-src-attr。根据CSP最新W3C规范,新加入了script-src-elem、script-src-attr、style-src-elem及style-src-attr四条指令键。其中,script-src-attr允许不移除on事件属性或javascript伪协议的情况下,通过sha256-指令阻断不可信脚本执行,降低部署CSP严格模式的改造成本。目前,Chrome 75及以上版本已率先支持。

二、知识背景

CSP的原理是,浏览器客户端以指令键形式(如:script-src),向Web开发者开放页面资源管控能力。通过编写CSP规则,可以构建“前端沙箱”,保证页面渲染结束时都是预期的内容。最终实现“敏感信息带不出去,恶意资源跑不起来”的防护效果。

近年来,围绕“增强阻断效果”、“降低部署成本”两个目标,CSP规范不断优化演进。最早制订的一代标准(CSP1)和最新的三代标准(CSP3)有很大不同,提供的防护能力也有天壤之别。两者差别,可类比为移动通讯中的“2G”与“5G“。

为便于理解,下文涉及的基础概念阐释如下:

[1] CSP规则。是由一系列键和值对组成的HTTP响应头。“键”指定要管控的资源类型,例如,script-src可控制页面所有JS脚本的行为。“值”包含“CSP指令”,用来指定白名单逻辑。例如,'unsafe-inline'表示允许执行内联脚本。

图2-0-1:CSP规则的组成说明

[2] CSP严格模式。自CSP二代标准(CSP2)引入的概念,可根据是否包含'nonce-'指令辨识,是Google等厂商主推的最佳实践方案。除非有特殊说明,下文所提CSP默认均指“CSP严格模式”。下图是一个“CSP严格模式”的典型案例:

图2-0-2:“CSP严格模式”典型案例(bugly.qq.com)

受篇幅限制,更多CSP技术细节可参考最新W3C规范及MDN:

Content Security Policy Level 3www.w3.orgContent Security Policy (CSP)developer.mozilla.org

3.1 背景:为什么要广泛部署CSP?

一开始,Google团队就”用数据说话“。一方面,公开自家VRP Program(漏洞奖励计划)数据,现身说法,XSS类风险占所有历史确认漏洞的75%。另一方面,引用Hackerone、Mozilla的数据,揭示XSS数量占“压倒性”比重,进一步佐证了风险的广泛性。

图 3-1-1:Google漏洞奖励计划确认漏洞类型分布

这部分指出,XSS形式多样、利用灵活,仍是Google乃至整个行业面临的首要安全风险,需要重点关注。对于核心业务,例如涉及账密、用户活动记录等隐私的敏感服务,类似CSP的“纵深防护(Defense-in-Depth)”措施,应作为首要兜底方案部署,以减轻安全函数库过滤缺失/失效时,产品面临的风险。

同时还阐明了一个认知误区,漏洞缓解措施(Mitigation)应以“彻底收敛攻击面,根本地解决漏洞”为导向,而不单是为了提高利用难度,由此带来的益处,不言而喻。比如,严格模式CSP可以使所有通过eval()或javascript:执行的XSS失效。但纯基于白名单的CSP,通过查找jsonp接口等方式,攻击者成功利用XSS,只是时间问题。

最后,这部分还提到部署CSP的过程,也是代码加固、重构的过程,会有一定成本。具体来说,涉及重构移除内联事件,eval()类方法,以及使用能依据场景自动添加nonce属性的模版系统。

3.2 绝非“纸上谈兵”:部署CSP获得显著收益

本节主要介绍了Google业务的CSP覆盖度现状,通过对2018年Google XSS漏洞报告的复盘,直观地呈现真实收益。给因顾虑有成本、收益不明朗,而对部署CSP犹豫不决的人们,打了一剂“强心针”。

在Google,CSP整体已取得较高覆盖度。“严格模式CSP”,正为62%的业务出流量提供保障。其中包括,80多个Google子域名,及超过160项业务

img

**图3-2-0:**典型业务案例

实战效果方面, 团队围绕2018全年漏洞报告数据,对CSP的收益进行了复盘。涉及核心域名的XSS漏洞报告共11例。其中9例业务已部署CSP,7例被成功阻断。报告者仅能论证代码存在缺陷,但无法在真实场景下产生危害,有效率约为78%。涉及敏感业务的XSS共69例,20例已部署严格模式CSP,成功阻断12例产生实际风险,有效率约为60%。

图3-2-1:“CSP严格模式”对已知XSS的阻断效果显著

团队分析了报告的XSS利用手法,包括注入恶意HTML标签(占29%)、javascript:伪协议(占23.2%)、 innerHTML写入(占8.7%)等。但绝大部分利用方法在正确配置CSP规则后,能被成功阻断。

图3-2-2:针对不同XSS利用方式,CSP阻断的生效条件

以Google核心域名为例,2018年外部发现且未被阻断的4例XSS,50%由于未部署CSP、完全无防护,剩余50%可通过优化CSP规则解决。换句话说,调整后,CSP可100%覆盖上述11例已知的XSS攻击。

图3-2-3:Google核心域名CSP未成功阻断案例复盘

3.3 CSP实践经验

当前,Google广泛部署的是包含nonce指令的”CSP严格模式“。nonce类似一个“接头暗号”,不可预测且页面刷新时会变化,只有当HTTP头和HTML属性值相等时,特定脚本才能执行。由于攻击者无法预知有效nonce值,插入的恶意代码因而不能执行。

而仅启用CSP1特性、类似如下的实践,有很多绕过方式。比如,仅使用了'unsafe-inline',而未引入'nonce-xxx',