CSP全称是: Content-Security-Policy, 内容安全策略。
是指HTTP返回报文头中的标签,浏览器会根据标签中的内容,判断哪些资源可以加载或执行。主要是为了缓解潜在的跨站脚本问题(XSS),浏览器的扩展程序系统引入了内容安全策略这个概念。原来应对XSS攻时,主要采用函数过滤转义输入中的特殊字符、标签、文本来规避攻击。CSP的实质就是白名单制度,开发人员明确告诉客户端,哪些外部资源可以加载和执行。开发者只需要提供配置,实现和执行全部由浏览器完成。
简单说就是应运程序为了防止XSS而在前端制定的安全策略(就是添加一些标签),告诉浏览器哪些资源可以加载访问
查看源代码:
$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.定义了CSP 标签,‘self’指可以访问的网址,网址白名单
header($headerCSP);
# https://pastebin.com/raw/R570EE00
?>
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
";
}
$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头中定义了CSP定义了CSP 标签,‘self’指可以访问的网址,网址白名单及 https://pastebin.com ,访问后发现为文本编辑网址,我们可以在该网址编辑xss脚本,然后包含该网址实现XSS
进入该网址:
然后编辑xss语句,点击CREAt new paste
这里因为标签里已经说明为javascript 所以不需要加标签
我们也可以通过查看http头部信息,找到收信人网址:
最后把链接发送给用户点击,实现注入。
源代码:
$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");
#
?>
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
" . $_POST['include'] . "
";
}
$page[ 'body' ] .= '
';
分析:
http头信息中的script-src的合法来源发生了变化,他没有使用信任网站而是两个内联:
unsafe-inline,允许使用内联资源,如内联< script>元素,javascript:URL,内联事件处理程序(如onclick)和内联< style>元素。必须包括单引号。
nonce-source,仅允许特定的内联脚本块,nonce=“TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA”
意思是只能使用script元素且脚本块值nonce值为TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA
结果:
构造一个标签,输入
<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert('qisheng')</script>
源代码:
$headerCSP = "Content-Security-Policy: script-src 'self';";
header($headerCSP);
?>
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=
';
进入高级别后发现没有输入框,查看源代码的CSP "Content-Security-Policy: script-src ‘self’;"意思是只能从本页面调用javascript
脚本。这里换是不明白
发现题目有这个提示(大体就是这个页面调用了jsonp.php,并且这个页面可以执行你自己的代码)
突然想到源代码中还有一个js代码
vulnerabilities/csp/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代码的功能就是,当点击求和是跳转到题目所示的php页面,成一个 script 标签(src 指向 source/jsonp.php?callback=solveNum), 并把它加入到 DOM 中 ,js中定义了一个 solveNum 的函数 -> 因此 script 标签会把远程加载的 solveSum({“answer”:“15”}) 当作 js 代码执行, 而这个形式正好就是调用了 solveSum 函数, 然后这个函数就会在界面适当的位置写入答案
查看jsonp.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).")";
?>
但是json.php中的参数通过get方式获取,且没有做过滤, 这可能作为一个注入点, 我们构造
并把这个当做 include 参数传给界面就 注入成功!
源码:
$headerCSP = "Content-Security-Policy: script-src 'self';";
header($headerCSP);
?>
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
" . $_POST['include'] . "
";
}
$page[ 'body' ] .= '
';