DVWA靶场保姆级通关教程--13CSP

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

CSP(Content Security Policy)是一种由浏览器支持的安全机制,用于防止某些类型的攻击,特别是:

  • XSS(跨站脚本攻击)

  • 数据注入攻击(如恶意代码注入)

  • 资源加载控制(防止加载未授权脚本或内容)

CSP 的核心思想是:告诉浏览器哪些内容是可信的,哪些内容不能加载或执行

CSP 的核心作用:

通过 定义可信的资源来源,限制网页可以加载和执行的内容,比如:

内容类型控制指令示例
脚本script-src
样式style-src
图片img-src
字体font-src
iframeframe-src / child-src
默认来源default-src

一、low级别源码分析

<?php

// 设置 Content Security Policy(CSP)响应头,限制允许加载脚本的域
// 仅允许从本地('self')和几个指定域加载 JavaScript 脚本
$headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com hastebin.com example.com code.jquery.com https://ssl.google-analytics.com ;";

// 将上面的 CSP 头发送给浏览器
header($headerCSP);

// 提供两个示例链接,如果无法自己创建脚本文件可以使用这些
# https://pastebin.com/raw/R570EE00
# https://hastebin.com/raw/ohulaquzex

?>
<?php

// 如果用户通过 POST 请求提交了 'include' 参数
if (isset ($_POST['include'])) {
    // 动态拼接 script 标签,把用户提供的 URL 当作外部脚本引入
    // 注意:这就是一个潜在的 XSS 漏洞点(如果 CSP 没有限制来源)
    $page[ 'body' ] .= "
        <script src='" . $_POST['include'] . "'></script>
    ";
}

// 添加一个表单,让用户可以输入外部脚本的 URL 并提交
// 用户输入的内容将被作为 <script src=""> 载入脚本
$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>
';

上句代码可以看出,除了本地还有以下外部资源可以被执行:

https://pastebin.com
hastebin.com
example.com
code.jquery.com
https://ssl.google-analytics.com

1.外部源测试

访问Pastebin.com - #1 paste tool since 2002!,可以在New Paste中写下代码,点击create去创建链接:

下拉点击create

点击raw===》复制出现的链接

CSP页面的输入框输入刚才的链接:

这里可能是由于网速或者其他原因,反复测试均未出现弹窗,那么由于代码也支持本地的文件测试

2.改为本地测试的思路

可以自己本地创建一个 JS 文件,并确保它的来源在 CSP 中允许(如 self,即本地服务器),然后测试是否能执行。


步骤:本地创建测试脚本并触发 XSS 弹窗

1. 创建一个测试脚本文件

假设你在 DVWA 根目录下创建一个文件,叫做:

payload.js

alert("本地 CSP XSS 测试成功!");
2. 确保文件路径正确

放在 DVWA 的某个可公开访问目录中,例如:

/dvwa/hack/payload.js

然后你访问这个地址能打开脚本:

http://localhost/dvwa/hack/payload.js

注意:确保这个路径属于 self 域,也就是浏览器请求的 localhost 或你本地服务器地址。

3. 在表单中输入脚本 URL

进入 vulnerabilities/csp/ 页面,在表单中输入:

http://localhost/dvwa/hack/payload.js

然后点击 Include 按钮。

4. 如果弹出 alert,就说明 CSP 允许加载并执行这个本地脚本。

二、medium级别的源码分析

<?php

// 设置 CSP 响应头
// 'self':允许加载本地脚本
// 'unsafe-inline':允许执行内联脚本(有安全隐患)
// 'nonce-xxx':带指定 nonce 值的脚本才会被允许执行,是 CSP 常用的防 XSS 手段之一
$headerCSP = "Content-Security-Policy: script-src 'self' 'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=';";

// 发送上面设置的 CSP 头
header($headerCSP);

// 关闭浏览器默认的 XSS 过滤功能,确保测试时 alert 等功能可以正常执行(仅用于教学场景)
header ("X-XSS-Protection: 0");

// 提示:如果你希望通过 nonce 绕过 CSP,可以构造如下代码:
// <script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script>

?>
<?php

// 如果用户通过 POST 提交了 include 参数
if (isset ($_POST['include'])) {
    // 将用户提交的内容直接插入页面
    // 注意:此处没有进行任何过滤,属于直接反射型 XSS 漏洞(不过受 CSP 约束)
    $page[ 'body' ] .= "
        " . $_POST['include'] . "
    ";
}

// 输出一个表单,用户可以提交任意 HTML 内容(包括脚本标签)进行测试
$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>
';

核心总结(Medium 级别特点):

项目说明
 CSP 内容script-src 'self' 'unsafe-inline' 'nonce-...':允许本地 JS、内联 JS(不安全)、带指定 nonce 的 JS 执行
XSS Protection被关闭,浏览器不会自动拦截 XSS
 漏洞点用户输入被直接插入 HTML 页面中,可注入 <script> 标签
 绕过技巧使用带有正确 nonce 的 <script> 标签进行 XSS 注入

利用示例(成功弹窗):

你可以提交如下内容(直接 POST 表单)来绕过 CSP 并弹窗:

<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert('CSP Medium 成功!')</script>
  • 因为 CSP 要求 <script> 标签包含匹配的 nonce,这里我们用的是页面中指定的 nonce 值。

  • 这个 nonce 是 Base64 编码的,但 CSP 是按字符串匹配,不需要解码。

方法总结

方法可行性说明
本地脚本(payload.js)❌ 不行CSP 中不允许加载未经 nonce 授权的外链脚本,即便是 'self'
<script nonce="...">...</script>✅ 可行CSP 明确允许的方式
<script>...</script>(无 nonce)⚠️ 可能被阻止'unsafe-inline' 不总是可信,取决于浏览器
HTML 属性注入如 <img onerror>❌ 无效不属于 script-src,浏览器 CSP 拦截

 三、high级别的源码分析

<?php
// 设置严格的 Content Security Policy:只允许从本地加载脚本(不允许 inline、外链、nonce、eval 等)
// 这使得一般的 XSS 攻击难以实施
$headerCSP = "Content-Security-Policy: script-src 'self';";

// 发送 CSP 响应头给浏览器
header($headerCSP);
?>
<?php
// 如果用户提交了 include 参数(POST),就直接把它插入到页面中
// 注意:仍然存在 XSS 注入点,但会被 CSP 拦截!
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>  <!-- 加载逻辑功能脚本 -->
';
// 定义点击按钮后执行的操作
function clickButton() {
    // 创建一个新的 <script> 标签
    var s = document.createElement("script");

    // 设置其 src 属性为 jsonp 接口,回调函数为 solveSum
    // jsonp.php 将返回一个 JS 脚本,其内容是:solveSum({...});
    s.src = "source/jsonp.php?callback=solveSum";

    // 将该 <script> 元素动态添加到页面中,从而触发加载并执行返回的脚本
    document.body.appendChild(s);
}

// 回调函数:接收 jsonp.php 返回的数据对象
function solveSum(obj) {
    // 如果对象中包含 "answer" 属性
    if ("answer" in obj) {
        // 将其显示在页面中的 <span id="answer"> 中
        document.getElementById("answer").innerHTML = obj['answer'];
    }
}

// 获取按钮元素
var solve_button = document.getElementById ("solve");

// 给按钮绑定点击事件,用户点击时调用 clickButton 函数
if (solve_button) {
    solve_button.addEventListener("click", function() {
        clickButton();
    });
}
  • 这个级别已经没有输入框了,不过题目已经给了足够多的提示:该页面调用../..//vulnerabilities/csp/source/jsonp.php来加载代码。修改该页面以运行您自己的代码。
    查看页面源码: jsonp.php 如下

 利用方式:修改 jsonp.php

 方法一:直接让 jsonp.php 回传一段恶意代码

<?php
header("Content-Type: application/javascript"); // JS 类型

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

// 你可以将 answer 改为任意值,这里嵌入 JS 代码
echo $callback . "({\"answer\": \"<img src=x onerror=alert('CSP绕过成功!')>\"});";
?>

页面中:

这一段代码最终执行了:

solveSum({"answer": "<img src=x onerror=alert('CSP绕过成功!')>"});

solveSum 函数原本是这样定义的:

function solveSum(obj) {
    if ("answer" in obj) {
        document.getElementById("answer").innerHTML = obj['answer'];
    }
}

它会把 answer 的内容直接写入 HTML 中:

<span id="answer"><img src=x onerror=alert('CSP绕过成功!')></span>

2.经实际测试,img或者svg都没有弹窗,而是有错误处理机制

所以直接暴力的修改jsonp.php

当请求到这个页面的时候,直接触发弹窗,并没有经过 High 级别页面里 solveSum 函数去拼接或操作 answer 内容

<?php
header("Content-Type: application/javascript");
echo "alert('1');";

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值