dvwa靶场 Content Security Policy (CSP) Bypass(CSP绕过)全难度教程(附代码分析)

前置知识

Content Security Policy(内容安全策略),用于定义脚本和其他资源从何处加载或者执行,总结的来说就时白名单。会一定程度的缓解xss脚本问题,也可以自己设定规则,管理网站允许加载的内容。

CSP 以白名单的机制对网站加载或执行的资源起作用,在网页中策略通过 HTTP 头信息或者 meta 元素定义。CSP 虽然提供了强大的安全保护,但是它也令 eval() 及相关函数被禁用、内嵌的 JavaScript 代码将不会执行、只能通过白名单来加载远程脚本。如果要使用 CSP 技术保护自己的网站,开发者就不得不花费大量时间分离内嵌的 JavaScript 代码和做一些调整。

Content Security Policy (CSP) Bypass(Security Level: low)

代码分析

点击查看代码
<?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 https://digi.ninja ;"; // allows js from self, pastebin.com, hastebin.com, jquery, digi.ninja, 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>
<p>
    As Pastebin and Hastebin have stopped working, here are some scripts that may, or may not help.
</p>
<ul>
    <li>https://digi.ninja/dvwa/alert.js</li>
    <li>https://digi.ninja/dvwa/alert.txt</li>
    <li>https://digi.ninja/dvwa/cookie.js</li>
    <li>https://digi.ninja/dvwa/forced_download.js</li>
    <li>https://digi.ninja/dvwa/wrong_content_type.js</li>
</ul>
<p>
    Pretend these are on a server like Pastebin and try to work out why some work and some do not work. Check the help for an explanation if you get stuck.
</p>

源码对http头进行csp定义,接受指定的外部javascript资源的白名单(抓包时可以看到的)

漏洞利用

前面说过了,只允许特定的网站我们先抓个包看一下

注意Content-Security-Policy

上面有几个网站Pastebin.com - #1 paste tool since 2002!

注意检查游览器是不是允许xss

将这个网站下载该文件的文件地址

Content Security Policy (CSP) Bypass(Security Level: 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>
';

合法来源发生变化,并且script-src 还可以设置一些特殊值,unsafe-inline 允许执行页面内嵌的 <script> 标签和事件监听函数,nonce 值会在每次 HTTP 回应给出一个授权 token。

漏洞利用

我们需要通过内连注入

屏幕截图 2026-01-31 121408

Content Security Policy (CSP) Bypass(Security Level: high)

代码分析

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();
    });
}
  1. 在high.php中设置了csp头,规定只允许从同源的脚本加载
  2. 提交表单的时候,如果存在POST形式的include参数
  3. 游览器执行clickbutton,动态创建<script>元素,将src属性设置为‘source/jsonp.php?callback=solveSum’(json.php是一个远程脚本的url)
  4. 加载远程脚本,返回数据给solveSum,展示到页面

漏洞利用

include控制的参数可以更改

那么我们构造一下


Content Security Policy (CSP) Bypass(Security Level: impossible)

代码分析

vulnerabilities/csp/source/impossible.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>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();
    });
}
1. 在代码开始处,通过设置 Content-Security-Policy 头部字段,指定了一个 CSP 设置,即 script-src 'self';。这个设置规定只允许从同域名加载 JavaScript 脚本,并且不允许使用内联脚本。
  1. 接下来的条件语句检查是否存在名为 include 的 POST 参数。如果存在该参数,将其内容添加到 $page['body'] 变量中。

  2. 然后创建一个包含说明文本和一个空 <span> 元素的表单,表单的提交方法是 POST。

  3. 表单中有一个按钮元素,点击该按钮会触发一个事件,调用名为 clickButton() 的 JavaScript 函数。

  4. 页面加载了一个名为 source/impossible.js 的 JavaScript 文件,通过 <script> 标签引入。

  5. source/impossible.js 中定义了一个名为 clickButton() 的函数。该函数会创建一个新的 <script> 元素,并将其 src 属性设置为 source/jsonp_impossible.php,然后将该元素添加到页面的 <body> 元素中。

  6. source/impossible.js 中还定义了一个名为 solveSum(obj) 的函数,用于处理异步加载的远程脚本返回的数据。如果返回的数据包含 answer 属性,该函数会将该属性值设置为页面中的 <span id="answer"> 元素的内容。

  7. 最后,通过获取按钮元素并添加点击事件监听器,实现了按钮点击后调用 clickButton() 函数的功能。

总的来说,这段代码使用 Content Security Policy(CSP)限制了 JavaScript 代码的来源和类型,同时对用户输入进行了处理。可以有效地提高了安全性。

posted on 2026-01-31 12:19  himobrine  阅读(3)  评论(0)    收藏  举报