CSP内容安全策略基础版

白屏问题

  • 小伙伴业务中经常会遇到白屏问题,其中一大原因是资源被CSP策略拦截了,那么什么是CSP呢?遇到了此问题要如何解决呢?

基础原理

什么是CSP?

  • 内容安全策略 (CSP) 是一个策略,该策略可以定义哪些资源可以被当前的web页面加载。

为什么要配置CSP?

  • CSP 的主要目标是减少和报告 XSS (Cross Site Scripting)攻击 。一般同源策略只对网页的HTML文档做了限制,对加载的其他静态资源如javascript、css、图片等资源等还是可以加载。而XSS攻击则刚好利用了浏览器对于从服务器所获取的内容的信任。CSP则在此基础上加了一层白名单,只有在白名单里的内容才会被信任。

原理是什么?

  • 就像上文所说XSS利用了浏览器对HTML其加载资源的信任,来执行一些不法操作。而CSP相当于给资源的访问加了一层白名单,只有在白名单里的资源才能被信任。
  • 比如说,对于没有设置CSP的浏览器来说,HTML文档加载的静态资源都会被浏览器认为安全的。
    CSP内容安全策略基础版_第1张图片
  • 而一旦这些资源里有恶意的脚本,浏览器无法识别哪些是恶意的脚本,还是认为都是安全可加载的,而导致悲剧的发生
    CSP内容安全策略基础版_第2张图片
  • 当我们加了CSP配置,告诉浏览器哪些是安全可加载的,那么那些恶意脚本就会被过滤掉,达到了防止攻击的效果
    CSP内容安全策略基础版_第3张图片
    那么这个白名单是在哪里配置并且以何种规则来告诉浏览器的哪些是可安全加载的呢?

CSP有以下两种方式可以配置:

  • Header
    • 你可以使用Content-Security-Policy HTTP响应头来进行配置
    Content-Security-Policy: default-src 'self'; script-src userscripts.example.com
    
    CSP内容安全策略基础版_第4张图片
  • Meta
    • 或者使用meta标签来配置,但是并不推荐此类方式,如果要使用需要放到html的最前面
    <meta http-equiv="Content-Security-Policy" content="default-src 'self' *.xx.com *.xx.cn 'unsafe-inline' 'unsafe-eval';">
    
  • 注意Header 和Meta不要混用,因为CSP是以最严格的策略为准,混用时很容易出问题,导致配置不生效,详情参考文档 [The effect of multiple policies]

CSP的规则都有哪些呢?

  • 一般CSP的HTTP Header张这样
Content-Security-Policy: 
base-uri 'self';
object-src 'self';
script-src 'self' 'unsafe-eval' 'unsafe-inline' 'report-sample' *.xxx.com; 
frame-src 'self' *.xxx.com;
report-uri https://xxx.log.xxx.com
  • base-uri
    • 用于控制base标签能加载的资源范围
    • ‘self’ 只允许加载当前域下的资源,具体匹配规则详见文档 [Does url match expression in origin with redirect count?]
  • object-src
    • 防止浏览器加载执行嵌入的插件资源,或标签。最常见的示例是防止Flash based xss
    • ‘self’ 只允许加载当前域下的资源,具体匹配规则详见文档 [Does url match expression in origin with redirect count?]
  • script-src
    • 用于控制浏览器加载页面脚本的范围,包括加载的url及内联脚本,其中:
      • ‘self’ 该指令指加载当前域下的js资源
      • ‘unsafe-inline’ 该指令值允许内联脚本加载
      • ‘unsafe-eval’ 该指令值允许页面加载eval()、new Founction()、定时器等JavaScript函数
      • ‘report-sample’ 指外界尝试XSS攻击时或有脚本触发了违例,浏览器会异步将payload的前40个字节POST给 report-uri 对应的链接,可以用于定位XSS漏洞、CSP制定阶段排查内联脚本位置
      • ‘*.xxx.com’ 允许这个域名下的js脚本加载,具体匹配规则详见文档 [Does url match expression in origin with redirect count?]
  • frame-src
    • 用于控制浏览器加载iframe资源的范围,其中:
      • ‘self’ 该指令指 加载当前域下的js资源,具体匹配规则详见文档 [Does url match expression in origin with redirect count?]
      • ‘*.xxx.com’ 允许这个域名下的iframe脚本加载,,具体匹配规则详见文档 [Does url match expression in origin with redirect count?]
  • report-uri
    • 就像上文所说,用来定义上报的地址
    • https://www.w3.org/TR/CSP/#directive-report-uri

注意:以上仅仅为很粗略的规则介绍,CSP的规则很复杂,若遇到问题需要查阅文档https://www.w3.org/TR/CSP/#index (level 3)解决

CSP很好的拦截了非法的加载,但是在实际业务中很容易因为CSP配置问题导致我们正常需要加载的资源无法加载,那么当我们遇到此类问题时要如何解决呢?

业务定位

什么情况是csp导致的?

  • 只要看到控制台里有这样的报错,一定是CSP无疑了
    CSP内容安全策略基础版_第5张图片

如果遇到CSP问题怎么办?

  1. 打开控制台找到CSP报错
  2. 读报错,明确是哪个域名何种类型的加载出了问题
    a. Refused to frame -> 加载iframe资源时出了问题,需要在frame-src中添加被拦截的域名
    b. Refused to load the script -> 加载js资源时出了问题 需要在script-src中添加被拦截的域名
    c. …
  3. 验证
    a. chrome插件验证
    https://chrome.google.com/webstore/detail/caspr-enforcer/fekcdjkhlbjngkimekikebfegbijjafd/related?hl=zh-CN
    b. charles断点验证
    抓包 -> 设置断点 -> 断点时更改数据
  4. 验证成功后联系server加上配置,把需要添加/修改的地方告诉server,也可发送配置成功的header以供参考

另:对于某些复杂问题不是添加域名就能解决的问题,建议查阅官方文档解决
https://www.w3.org/TR/CSP/ (level 3)

CSP相关问题

当meta标签和响应头同时设定了CSP会怎样?

  • 无论协议写在哪里,都以最严格的策略为准
    • https://w3c.github.io/webappsec-csp/#multiple-policies
    • 但这个在目前标准中被标注为This section is not normative.

mac旧版本(10.11)CSP报错

因mac旧版本的实现的CSP协议为2012年的版本
https://www.w3.org/TR/2012/WD-CSP11-20121213/
而新版本mac实现为较新协议
https://www.w3.org/TR/CSP2/#match-source-expression
而新协议与旧协议对没有设定schema(http:// | https:// ftp://)时是否匹配的规则不一致

旧版本
If the source expression does not have a scheme and if uri-scheme is not a case insensitive match for the scheme of the protected resource’s URI, then return does not match.
大意:若没有scheme 访问的资源需与受保护页面的scheme一致
因为出问题页面为http协议,而加载了https的资源,所以旧版本中,资源被拦截

新版本
If the source expression does not have a scheme, return does not match if any of the following are true:
the scheme of the protected resource’s URL is a case insensitive match for HTTP, and url-scheme is not a case insensitive match for either HTTP or HTTPS
the scheme of the protected resource’s URL is not a case insensitive match for HTTP, and url-scheme is not a case insensitive match for the scheme of the protected resource’s URL.
大意:若没有scheme 以下两种情况为不匹配
受保护页面为http或https协议,请求资源不是http或https协议时
受保护页面不为http协议,请求资源和受保护资源协议不同时
而出问题页面恰好不在不匹配规则内 所以新版本没有问题

结论
旧版本mac的CSP协议为2012版本
新版本mac依据新版本协议(粗略)
建议不在http内加载https或反之

参考

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP
https://developers.google.com/web/fundamentals/security/csp
https://www.freebuf.com/articles/web/185654.html
https://www.w3.org/TR/CSP/

后语

  • 好文章要分享给大家,转载 / 作者: 狐狸鹿妹子 百度

你可能感兴趣的:(前端&&沉淀,csp,xss,安全,web)