CSP概念
CSP 是 Content Security Policy(内容安全策略)的缩写,是一种用于增强 Web 应用程序安全性的安全机制。它通过允许网站管理员控制页面中加载内容的来源来减少跨站脚本攻击(XSS)等常见的安全风险。
CSP 的工作原理是通过定义一组策略规则,指定哪些来源可以被信任和允许加载到页面中。这些来源可以是同源的网址、特定的域名、安全连接(如 HTTPS)或者是内联脚本和样式表。 CSP 可以阻止恶意代码、恶意插件或其他不受信任的资源被加载到页面上,从而增加页面的安全性。
CSP 提供了一系列的指令和选项,用于配置安全策略,例如:
-
default-src
指令:指定默认情况下允许加载的资源来源。 -
script-src
指令:用于限制可执行脚本的来源。 -
style-src
指令:用于限制可应用的样式表的来源。 -
img-src
指令:用于限制可加载的图像的来源。 -
connect-src
指令:用于限制可建立网络连接的来源。 -
font-src
指令:用于限制可加载的字体文件的来源。 -
frame-src
指令:用于限制可以嵌入页面的框架的来源。 -
report-uri
指令:指定将安全违规报告发送到的 URL。
通过合理配置 CSP,网站管理员可以严格限制哪些资源能被加载,从而减少恶意代码执行的风险。它还可以帮助检测和修复存在的安全漏洞,并提供了一种机制来报告违规行为。
Low level
译文如下:您可以包含来自外部源的脚本,检查内容安全策略,然后在此处输入要包含的URL:
源代码
<?php
$headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com hastebin.com www.toptal.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://www.toptal.com/developers/hastebin/raw/cezaruzeka
?>
<?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>
';
首先,通过设置 $headerCSP
变量来定义 CSP 的策略规则。
-
script-src
指令被用来限制可执行的脚本的来源。通过设置'self'
、https://pastebin.com
、hastebin.com
、www.toptal.com
、example.com
、code.jquery.com
和https://ssl.google-analytics.com
这些来源,来允许从这些地址加载 JavaScript。
然后,使用 header()
函数将定义好的 CSP 头部发送给浏览器,以告知浏览器采用 CSP 策略。
接着是一个简单的网页表单,允许用户输入一个 URL,并在提交表单时使用 $_POST['include']
获取用户输入的 URL。如果用户输入了 URL,那么会根据用户输入的 URL 动态生成一个 <script>
标签来加载外部脚本。
姿势
由代码审计得到以下的外部资源可以被响应
self
https://pastebin.com
hastebin.com
example.com
code.jquery.com
https://ssl.google-analytics.com
在CSP的规则中,'self'
表示当前网站的源。当使用'self'
作为脚本来源时,只有同源的脚本才会被加载和执行。
以 https://pastebin.com 为例
新建Paste并输入脚本:
创建完成后点击raw
复制该网址:
输入URL:
即可在当前页面触发弹窗 1
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>
';
首先,代码通过设置$headerCSP
变量定义了一个内容安全策略的头部。通过"script-src 'self' 'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA='"
指令设置 nonce ,其目的是为了提供额外的安全性,确保只有具有相应 nonce 的脚本能够被执行。这样可以防止未经授权的脚本注入攻击。
然后使用header($headerCSP);
将该内容安全策略头部应用于响应头。
接下来,通过header("X-XSS-Protection: 0");
这行代码,禁用了浏览器的跨站脚本攻击(XSS)防护机制,以便内联的弹窗警告框能够正常工作。
接下来的代码段是一个表单,允许用户输入内容,并将该内容直接输出到页面中。用户可以在文本框中输入任意内容,这些内容将被添加到页面的主体部分。
姿势
在实际应用中,可以根据需要为每个内联脚本生成唯一的 nonce,并将其与相应的脚本标签一起使用,例如:
<script nonce="生成的唯一的nonce值">脚本代码</script>
这样可以确保仅允许具有正确 nonce 值的脚本执行。
综上所述,我们可以构造POC如下:
<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert("qiushuo")</script>
其中的nonce也可以从消息头中得到:
输入POC:
回显如下:
High level
源代码
//vulnerabilities/csp/source/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>
';
//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();
});
}
首先,在文件 high.php
中设置了一个 CSP 头部,规定只允许从同一源的脚本加载,即 script-src 'self'
。这样可以防止恶意代码的注入。然后,通过 PHP 的 header
函数将 CSP 头部发送给浏览器。
接下来,在表单提交时,如果存在名为 include
的 POST 参数,将其作为代码包含在页面主体中。
点击按钮时,会执行 JavaScript 函数 clickButton
,该函数动态创建一个 script
元素,并设置其 src
属性为 source/jsonp.php?callback=solveSum
。这里使用了 JSONP(JSON with Padding)技术,通过指定回调函数名称的方式来获取跨域的数据。当脚本加载完成后,会调用函数 solveSum
,将返回的数据展示在页面上。
在文件 high.js
中定义了 clickButton
函数用于创建 script
元素并加载跨域脚本,以及 solveSum
函数用于处理返回的数据。最后,通过事件监听,当按钮被点击时,调用 clickButton
函数。
简单来说
当点击按钮后,以下步骤会依次发生:
- 首先,浏览器会执行 JavaScript 函数
clickButton
。 - 在
clickButton
函数中,会动态创建一个<script>
元素。 -
<script>
元素的src
属性被设置为source/jsonp.php?callback=solveSum
,其中source/jsonp.php
是一个远程脚本的 URL,callback=solveSum
指定了回调函数的名称为solveSum
。 - 浏览器会开始加载指定的远程脚本文件
source/jsonp.php
。 - 当远程脚本文件加载完成后,返回的数据会通过回调函数
solveSum
进行处理。 - 在
solveSum
函数中,返回的数据会被展示在页面上。
姿势
由于 include
为可控参数且回调函数的名称solveSum
可更改
故构造POC如下:
include=<script src="source/jsonp.php?callback=alert("qiushuo");"></script>
Impossible level
源代码
<?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>
';
vulnerabilities/csp/source/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();
});
}
-
在代码开始处,通过设置
Content-Security-Policy
头部字段,指定了一个 CSP 设置,即script-src 'self';
。这个设置规定只允许从同域名加载 JavaScript 脚本,并且不允许使用内联脚本。 -
接下来的条件语句检查是否存在名为
include
的 POST 参数。如果存在该参数,将其内容添加到$page['body']
变量中。 -
然后创建一个包含说明文本和一个空
<span>
元素的表单,表单的提交方法是 POST。 -
表单中有一个按钮元素,点击该按钮会触发一个事件,调用名为
clickButton()
的 JavaScript 函数。 -
页面加载了一个名为
source/impossible.js
的 JavaScript 文件,通过<script>
标签引入。 -
source/impossible.js
中定义了一个名为clickButton()
的函数。该函数会创建一个新的<script>
元素,并将其src
属性设置为source/jsonp_impossible.php
,然后将该元素添加到页面的<body>
元素中。 -
source/impossible.js
中还定义了一个名为solveSum(obj)
的函数,用于处理异步加载的远程脚本返回的数据。如果返回的数据包含answer
属性,该函数会将该属性值设置为页面中的<span id="answer">
元素的内容。 -
最后,通过获取按钮元素并添加点击事件监听器,实现了按钮点击后调用
clickButton()
函数的功能。
总的来说,这段代码使用 Content Security Policy(CSP)限制了 JavaScript 代码的来源和类型,同时对用户输入进行了处理。可以有效地提高了安全性。
总结
以上为DVWA之Content Security Policy (CSP) Bypass 攻击姿势及解题详析合集,结合PHP代码审计
及Http相关知识
考察CSP渗透姿势。文章来源:https://www.toymoban.com/news/detail-743373.html
我是秋说,我们下次见。文章来源地址https://www.toymoban.com/news/detail-743373.html
到了这里,关于[网络安全] DVWA之Content Security Policy (CSP) Bypass 攻击姿势及解题详析合集的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!