CSP(Content Security Policy):即内容安全策略。点击这里有详细的介绍。
不过简单了解下就是指:开发者在开发过程中设置了一个类似于白名单的策略,要信任某个页面,哪些外部资源可以执行,哪些不可以,这可以从根本上防御XSS,如果CSP配置的好,可以从根本上杜绝XSS(关于XSS的文章可以点击这里)
今天就是通过DVWA来详细由浅入深学习如何绕过CSP(CSP Bypass)吧!
low level
首先查看源码:
$headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com hastebin.com example.com code.jquery.com https://ssl.google-analytics.com ;";
这句语句就可以看出以下外部资源可以被执行:
https://pastebin.com
hastebin.com
example.com
code.jquery.com
https://ssl.google-analytics.com
这里就算不看源码,用BP拦截响应包也可以看到:
还有个直接的方式就是按F12,在network查看:
这个时候我们打开其中白名单里一个网页:
首先在https://pastebin.com/
里边创建一个JavaScript代码alert("hahaha")
保存记住链接:
其他不用修改:
raw一下:
记住url
(因为这里是后边补充的,重新生成的url,所以不一样)
https://pastebin.com/raw/zSLDySJn
然后粘贴在输入框:
点击Include:
这里需要说明一下,https://pastebin.com/这个网址是米国的,访问比较慢,可能不会出现弹窗,比较蛋疼,解决了一早上
因为https://pastebin.com/是被信任的所以会执行,若不在白名单里是不会被执行的
medium level
分析源码:
<?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>
';
emmmm源码有个备注,输入试试:
# <script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script>
输入可以直接弹窗 😃
接下来看看csp信息:
$headerCSP = "Content-Security-Policy: script-src 'self' 'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=';";
unsafe-inline:当csp有Unsafe-inline时, 并且受限于csp无法直接引入外部js, 不过当frame-src
为self, 或者能引入当前域的资源的时候, 即有一定可能能够引入外部js。
nonce-source,仅允许特定的内联脚本块。如源码中:
nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA='
因此这个就更加简单了,就像上边那个备注里那样,输入即可~
high level
分析源码;
$headerCSP = "Content-Security-Policy: script-src 'self';";
这里可以看到除了自身,其余的外部资源全部过滤了
这里可以看到已经没有输入框了
不过给了提示:
先看看按钮执行的逻辑是怎样的:
大概看了看源码,逻辑在source/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();
});
}
代码依次分析:
- 点击按钮,js创建一个script标签
- src指向source/jsonp.php?callback=solveNum
- appendChild(s)函数又将source/jsonp.php?callback=solveNum加入到DOM中
- 源码定义了一个solveNum函数,利用obj传参,若answer在obj中将会被执行
- document对象可以访问HTML中的内容
- getElementById(id)可返回对拥有指定 ID 的第一个对象的引用
- innerHTML 属性设置或返回表格行的开始和结束标签之间的 HTML
- 这里的 script 标签会把远程加载的 solveSum({“answer”:“15”}) 当作 js 代码执行, 然后这个函数就会在页面显示答案
这里纯属按资料个人理解,若有误,请各位大佬多多批评指正 [/拜谢]
看清楚代码以后,可以看到src指向的source/jsonp.php?callback=solveNum
未做任何XSS的过滤,因此可以构造payload:
<script src= "source/jsonp.php?callback=alert("hahaha")";></script>
忽然发现怎么把这个写到source/jsonp.php里去呢???
这里不会弄了,有路过大佬有解决办法的,希望可以多多指教
突然发现,代码没有过滤可以直接在代码里修改:
将solveSum修改为恶意代码:alert(document.cookie)
impossible level
可以看到给的提示:
Unlike the high level, this does a JSONP call but does not use a callback, instead it hardcodes the function to call.
不像高级那样,此操作执行JSONP调用,但不使用回调,而是对要调用的函数进行硬编码。
The CSP settings only allow external JavaScript on the local server and no inline code.
CSP设置仅允许本地服务器上使用外部JavaScript,而不能使用内联代码。
这里可以看到代码的不同:
high level:
s.src = "source/jsonp.php?callback=solveSum";
impossible level:
s.src = "source/jsonp_impossible.php";
解决了callback不可控的问题~
·
·
·
·
·
·
<小白初试 望路过大佬多多指教>