
CSP 指的是内容安全策略
为了缓解很大一部分潜在的跨站脚本(XSS) 问题,浏览器的扩展程序系统引入了内容安全策略(CSP)的一般概念。通过引入一些相当严格的策略使扩展程序在默认情况下更加安全,开发者可以创建并强制应用一些规则,管理网站允许加载的内容。
CSP 以白名单的机制对网站加载或执行的资源起作用,在网页中策略通过 HTTP 头信息或者 meta 元素定义。CSP 虽然提供了强大的安全保护,但是它也令 eval() 及相关函数被禁用、内嵌的 JavaScript 代码将不会执行、只能通过白名单来加载远程脚本。如果要使用 CSP 技术保护自己的网站,开发者就不得不花费大量时间分离内嵌的 JavaScript 代码和做一些调整。
今天就是通过DVWA来详细由浅入深学习如何绕过CSP(CSP Bypass)
代码分析
<?php
//self是指向类本身,也就是PHP self关键字是不指向任何已经实例化的对象,一般self使用来指向类中的静态变量。
//self可以访问本类中的静态属性和静态方法,可以访问父类中的静态属性和静态方法
//存放url
$headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com example.com code.jquery.com https://ssl.google-analytics.com ;";
// allows js from self, pastebin.com, jquery and google analytics.
//header() 函数向客户端发送原始的 HTTP 报头。
//发送$headerCSP的
header($headerCSP);
# https://pastebin.com/raw/R570EE00
?>
<?php
//if判断
//非空
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
";
}
$page[ 'body' ] .= '
';
大致就是
源码定义了一个变量 headerCSP 放置了一些 url,使用 script src 指令指向一个外部 JavaScript 文件,header() 函数以原始形式将 HTTP 标头发送到客户端或浏览器.
根据上面的源码可以被执行的资源,被信任的网站
https://pastebin.com
hastebin.com
example.com
code.jquery.com
https://ssl.google-analytics.com
这个时候我们打开其中白名单里一个网页:
首先在https://pastebin.com/里边创建一个JavaScript代码alert("hahaha")保存记住链接:



复制url
去执行
如何F12
成功载进去了

这里需要说明一下,https://pastebin.com/这个网址是米国的,访问比较慢,有时候可能不会出现弹窗
代码分析
<?php
$headerCSP = "Content-Security-Policy: script-src 'self' 'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=';";
header($headerCSP);
// Disable XSS protections so that inline alert boxes will work
header ("X-XSS-Protection: 0");
//直接利用这个就🆗了
#
?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
" . $_POST['include'] . "
";
}
$page[ 'body' ] .= '
';
他提供了一个给我们
用一下
<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script>


非常理智的内容
代码分析
//没有其他的URL了全部没有了
$headerCSP = "Content-Security-Policy: script-src 'self';";
header($headerCSP);
?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
" . $_POST['include'] . "
";
}
$page[ 'body' ] .= '
. DVWA_WEB_PAGE_TO_ROOT . '/vulnerabilities/csp/source/jsonp.php to load some code. Modify that page to run your own code.
1+2+3+4+5=
';
还要一个js的代码
function clickButton() {
//点击按钮,js创建一个script标签
var s = document.createElement("script");
//src指向source/jsonp.php?callback=solveNum
s.src = "source/jsonp.php?callback=solveSum";
//appendChild(s)函数又将source/jsonp.php?callback=solveNum加入到DOM中
document.body.appendChild(s);
}
function solveSum(obj) {
//源码定义了一个solveNum函数,利用obj传参,若answer在obj中将会被执行
if ("answer" in obj) {
//document对象可以访问HTML中的内容
document.getElementById("answer").innerHTML = obj['answer'];
}
}
//getElementById(id)可返回对拥有指定 ID 的第一个对象的引用
var solve_button = document.getElementById ("solve");
if (solve_button) {
solve_button.addEventListener("click", function() {
clickButton();
//innerHTML 属性设置或返回表格行的开始和结束标签之间的 HTML
//这里的 script 标签会把远程加载的 solveSum({“answer”:“15”}) 当作 js 代码执行, 然后这个函数就会在页面显示答案
});
}

这里也没有输入框了
js代码中可以看到
可以看到src指向的source/jsonp.php?callback=solveNum未做任何XSS的过滤,因此可以构造payload
<script src= "source/jsonp.php?callback=alert("xss")";></script>
修改地方是

点击按钮,js 生成一个 script 标签(src 指向 source/jsonp.php?callback=solveNum),并把它加入到 DOM 中;
js 中定义了一个 solveNum 的函数,因此 script 标签会把远程加载的 solveSum({“answer”:“15”}) 当作 js 代码执行,而这个形式正好就是调用了 solveSum 函数;
然后这个函数就会在界面适当的位置写入答案