关于那些Web漏洞--CSP

CSP

CSP即content security policy(内容安全策略),通过设置策略指令来规定资源的加载来源,简单地说就是CSP可以规定页面能从哪些域(站点)加载资源,这里的资源包括js脚本、图片和音频等等。如图,可以在响应头中看到它的存在:
MDN文档对CSP解释的非常清楚。链接:MDN_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设置了脚本的来源(script-src)只能是self(此页面所在的站点)、https://pastebin.com、example.com、code.jquery.com和https://ssl.google-analytics.com。那么,要绕过CSP,只能从这些站点入手,如果这些站点上的某一个页面能插入脚本代码,就把它加载进来。逐个检查站点,可以发现在https://pastebin.com这个站点可以自主编辑页面。
点击raw后,就可以生成一个包含脚本代码的页面。然后再引入到页面中,点击include成功弹框。
那为什么不直接闭合标签注入脚本代码?因为默认情况下,CSP禁止内联脚本(形如就是内联脚本)和事件处理属性中的代码(如οnerrοr=“code)”)。
如果要取消禁止,就设置指令为:script-src unsafe-inline。

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");
// 设置了这个头部,浏览器会检测到XSS,从而采取相应防御措施,但并非所有
// 浏览器都支持,例如Firefox就不支持。设置为 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,设置了"unsafe-inline"说明可以执行内联脚本,而"nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA="说明只有设置了nonce属性,并且属性值为"TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA="的script标签才能执行内联脚本。思路很清晰了,输入:,成功弹框。
这个nonce值可以在响应头中得到,它的作用跟token值有点类似,含有nonce值的script标签才能执行脚本,实际上这个nonce值应该要随机生成的,而不是固定的。

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();
    });
}

// jsonp.php
<?php
header("Content-Type: application/json; charset=UTF-8");

if (array_key_exists ("callback", $_GET)) {
	$callback = $_GET['callback'];
} else {
	return "";
}

$outp = array ("answer" => "15");

echo $callback . "(".json_encode($outp).")";
?>

首先给"solve the sum"按钮注册一个"click"的监听事件,当点击这个按钮后,就会执行solveSum函数,这个函数的作用是创建一个script元素,其src属性为"…jsonp.php…",说明script元素的内部脚本是从jsonp.php加载进来的,然后在body元素中添加这个script元素,里面的脚本代码就会被执行。接下来看看jsonp.php代码,$callback值是GET方式传递的,它可以被控制,并且还原样返回。测试一下:
在这里插入图片描述跟Low级别一样,这些数据加载进来后,就是script元素内部的脚本,可以被执行。
在这里插入图片描述

Impossible

// jsonp_impossible.php
<?php
header("Content-Type: application/json; charset=UTF-8");

$outp = array ("answer" => "15");

echo "solveSum (".json_encode($outp).")";
?>

这级别修复了High级别中jsonp.php的小漏洞,不再用$callback接收参数值了,而是把"solveSum"写死在代码中,因此也就没有可利用的地方了。

总结

这几道题给出了一些绕过CSP的方法:
(1)仔细分析站点的CSP策略,检查它设置的来源是否可以修改其中的页面数据,嵌入脚本后把它加载进来即可;
(2)是否允许内联脚本,是否设置对应的nonce值,nonce值是否固定的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值