目录
一、CSP
1.简介
CSP(Content Security Policy):即内容安全策略
它的本质是建立一个白名单,告诉浏览器哪些外部资源可以加载和执行。我们只需要配置规则,如何拦截由浏览器自己来实现。
通常有两种方式来开启 CSP,一种是设置 HTTP 首部中的 Content-Security-Policy,另一种 是设置 meta 标签的方式 <meta http-equiv="Content-Security-Policy">
CSP 也是解决 XSS 攻击的一个强力手段
script-src脚本:只信任当前域名。
object-src:不信任任何URL,即不加载任何资源。
style-src样式表:只信任的网站
child-src:必须使用HTTPS协议加载。
当启用CSP后,不符合CSP的外部资源会被阻止加载。
二、(CSP) Bypass
1.Low
您可以包括来自外部源的脚本,检查内容安全策略并在此处输入要包含的URL:
源码
<?php
$headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com hastebin.com example.com code.jquery.com https://ssl.google-analytics.com ;"; // allows js from self, pastebin.com, hastebin.com, jquery and google analytics.
header($headerCSP);
# These might work if you can't create your own for some reason
# https://pastebin.com/raw/R570EE00
# https://hastebin.com/raw/ohulaquzex
?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
<script src='" . $_POST['include'] . "'></script>
";
}
$page[ 'body' ] .= '
<form name="csp" method="POST">
<p>You can include scripts from external sources, examine the Content Security Policy and enter a URL to include here:</p>
<input size="50" type="text" name="include" value="" id="include" />
<input type="submit" value="Include" />
</form>
';
当然,从http头部也可以得到允许什么访问。
以下的外部资源可以被响应
https://pastebin.com
hastebin.com
example.com
code.jquery.com
https://ssl.google-analytics.com
访问pastebin.com
在New Paste里面写上JS代码:
直接Create New Paste 创建新帖,不用管登录什么的。
在点击raw
复制新生成的网址
在csp靶场输入框中输入新网址, 点击inxlude就会触发弹窗。(如果一直没弹窗是因为https://pastebin.com这个网址是米国的)
2.Medium
<?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");
# <script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script>
?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
" . $_POST['include'] . "
";
}
$page[ 'body' ] .= '
<form name="csp" method="POST">
<p>Whatever you enter here gets dropped directly into the page, see if you can get an alert box to pop up.</p>
<input size="50" type="text" name="include" value="" id="include" />
<input type="submit" value="Include" />
</form>
';
http头信息中的script-src的合法来源发生了变化:
unsafe-inline:允许使用内联资源,如内联 <script> 元素:javascript:URL,内联事件处理程序(如onclick)和内联 <style> 元素,必须包括单引号。
nonce-source:仅允许特定的内联脚本块, nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA="
所以可以直接输入以下代码:
<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script>
同样F12http包头也可得到
测试一下
成功触发
3.high
给我们的提示
源码
high.php
<?php
$headerCSP = "Content-Security-Policy: script-src 'self';";
header($headerCSP);
?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
" . $_POST['include'] . "
";
}
$page[ 'body' ] .= '
<form name="csp" method="POST">
<p>The page makes a call to ' . DVWA_WEB_PAGE_TO_ROOT . '/vulnerabilities/csp/source/jsonp.php to load some code. Modify that page to run your own code.</p>
<p>1+2+3+4+5=<span id="answer"></span></p>
<input type="button" id="solve" value="Solve the sum" />
</form>
<script src="source/high.js"></script>
';
high.js
function clickButton() {
var s = document.createElement("script");
s.src = "source/jsonp.php?callback=solveSum";
document.body.appendChild(s);
}
function solveSum(obj) {
if ("answer" in obj) {
document.getElementById("answer").innerHTML = obj['answer'];
}
}
var solve_button = document.getElementById ("solve");
if (solve_button) {
solve_button.addEventListener("click", function() {
clickButton();
});
}
大致流程
1,点击按钮,js创建一个script标签
2,src指向source/jsonp.php?callback=solveNum
3,appendChild(s)函数又将source/jsonp.php?callback=solveNum加入到DOM中
4,源码定义了一个solveNum函数,利用obj传参,若answer在obj中将会被执行
5,document对象可以访问HTML中的内容
6,getElementById(id)可返回对拥有指定 ID 的第一个对象的引用
7,innerHTML 属性设置或返回表格行的开始和结束标签之间的 HTML
8,这里的 script 标签会把远程加载的 solveSum({“answer”:“15”}) 当作 js 代码执行, 然后这个函数就会在页面显示答案
我们点击计算,然后查看http包头,得到GET方式传参。
也可以bp抓包查看一下
我们可以根据http头部构造payload:
include=<script src="source/jsonp.php?callback=alert(1);"></script>
4.Impossible
<?php
$headerCSP = "Content-Security-Policy: script-src 'self';";
header($headerCSP);
?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
" . $_POST['include'] . "
";
}
$page[ 'body' ] .= '
<form name="csp" method="POST">
<p>Unlike the high level, this does a JSONP call but does not use a callback, instead it hardcodes the function to call.</p><p>The CSP settings only allow external JavaScript on the local server and no inline code.</p>
<p>1+2+3+4+5=<span id="answer"></span></p>
<input type="button" id="solve" value="Solve the sum" />
</form>
<script src="source/impossible.js"></script>
';
function clickButton() {
var s = document.createElement("script");
s.src = "source/jsonp_impossible.php";
document.body.appendChild(s);
}
function solveSum(obj) {
if ("answer" in obj) {
document.getElementById("answer").innerHTML = obj['answer'];
}
}
var solve_button = document.getElementById ("solve");
if (solve_button) {
solve_button.addEventListener("click", function() {
clickButton();
});
}
impossible等级执行JSONP调用,但不使用callback参数,而是硬编码要调用的函数。CSP设置只允许本地服务器上的外部javascript,不允许内联代码。
可以看到,callback传参删除,也没有办法进行渗透了。
bp抓包,啥参也没传。