CSP使用指南

作者:JAY 2020-07-22

简介

上一篇博客介绍了XSS攻击(Cross Site Scripting)的原理。常规过滤脚本等防范方式,不仅麻烦,而且消耗性能,易攻难守,容易出纰漏。那干嘛不制定一个白名单,只有在白名单的内容才能正常执行呢?这个白名单就是Content Security Policy(内容安全策略),简称CSP。网站通过CSP声明了哪些来源的资源是可信的,就算黑客成功注入了XSS脚本,只要不在CSP声明的范围内,浏览器就不会加载执行,而是抛出错误。


通常情况下,网站通过http响应header来配置CSP。只需要增加像这样一行:

content-security-policy: default-src 'self';

也可以通过HTML的<meta>来配置,比如:

<meta http-equiv="Content-Security-Policy" content="default-src 'self';">

两者选一种即可。如果两者都设置了,浏览器会校验两次,重复抛出错误。 


指令规则

CSP由一系列的策略指令组成:JS脚本是一个策略指令,CSS样式又是一个策略指令,图片也是一个策略指令,等等。每个指令都描述了这类型资源的白名单策略,这一系列的策略指令,共同构成了网站的CSP策略。每个策略指令需要大概长这样:

script-src 'self' blog.oonne.com;

如上所示,红色部分表示这个策略对应的资源类型,比如“script-src”表示这个策略是针对脚本代码;蓝色部分表示白名单列表,列表的每一项空格隔开。合起来,上面这个策略就表示“本网站仅允许加载执行:来自本域名、blog.oonne.com的脚本代码”。


策略类型

常用策略类型有以下几种:


策略值

对应上述类型,策略值有以下几种:

说明
*通配符,允许任何来源
'none'禁止任何来源
'self'允许符合同源策略的资源

域名

(如blog.oonne.com,或通配域名 *.oonne.com)

允许来自此域名的资源
data:允许dataUrl,通常是经过Base64编码的资源
https:允许https协议的资源
'unsafe-inline'允许内联资源,如<script>标签
'unsafe-eval'允许eval()执行内容
'unsafe-hashes'允许事件里的内容,如onclick等
'strict-dynamic'允许动态创建的标签,如document.createElement('script')
'nonce-'允许带有指定nonce值的标签
'sha256-'允许指定Hash值的内容

以上一些特殊值必须在单引号中才能生效。


最后提到的'nonce-',是个标识。举个例子,如果定义了 script-src 'nonce-oonne',那么只有带有这个标识的<script>标签允许执行,如:

<script nonce=oonne>
  // 可以执行的代码
</script>

nonce可以由服务端生成网页的时候,顺便随机生成,这样可有效避免攻击。


'sha256-'是把你要执行的代码计算出hash值,这样就能定义你执行的代码,避免被篡改。比如,需要执行以下代码:

<script>doSomething();</script>

把“doSomething()”用openssl计算sha256的base64,并在CSP里定义 script-src 'sha256-RFWPLDbv2BY+rCkDzsE+0fr8ylGr2R2faWMhq4lfEQc=' 即可。


策略指令

把上述策略类型和策略指组合起来,就是一个网站的CSP指令了。举个例子,假设一个网站的CSP设置为:

Content-Security-Policy: default-src 'self'; script-src 'self' blog.oonne.com; style-src  'self' 'unsafe-inline'; img-src 'self' data:;

表示:允许来自当前域名以及blog.oonne.com的脚本;允许来自当前域名以及页面内<style>标签的CSS样式;允许来自当前域名以及dataUrl的图片;其他资源仅允许来自当前域名。


违例报告

除了防范XSS攻击,CSP还可以记录攻击记录。举例,可给CSP策略中新增以下内容:

report-uri /csp-reports;

这样,一旦浏览器判断到CSP策略以外的资源,怀疑遭到XSS攻击,就会向/csp-reports这个路径发起一个POST方法的http请求。内容是一个JSON对象,含有以下字段:


这样就能根据收到的违例报告,判断是自己的CSP没配置对导致本站资源报错,还是有人企图对网站进行XSS攻击。


为了降低CSP的部署成本,还提供了“报告模式”(report-only)。只需要把想测试的CSP策略,放到

Content-Security-Policy-Report-Only字段下。违反策略的资源不会被拦截,但会发送违规报告。这样就能放心进行测试和部署了。


总结

合理规划网站资源储存加载路径,配置严格的CSP,可以有效防止XSS攻击。

一些古董级别的浏览器(主要是IE)依然不支持CSP。如果要照顾这些用户,除了设置X-XSS-Protection等旧浏览器支持的方案外,其他常规安全措施也还得做。


参考文献

  1. https://content-security-policy.com

  2. https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP

  3. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy



本文未经许可禁止转载,如需转载请联系 JAY@oonne.com


TOP