DVWA靶场通关笔记-存储型XSS(Stored High级别)

目录

一、存储型XSS

二、源码分析

1、index.php

2、High.php

3、XSS注入分析

三、渗透实战

1、渗透准备

2、修改前端maxlength字段

3、XSS注入获取cookie


DVWA(Damn Vulnerable Web Application)中的存储型XSS关卡(Stored)是用于练习和演示存储型XSS的不同场景,不同安全等级存在不同的脆弱点和绕过方法,本文对高等级别(High)的关卡进行渗透实战。

一、存储型XSS

存储型XSSStored Cross-Site Scripting是恶意脚本被持久化保存到服务器(如数据库、文件等),当其他用户访问包含该脚本的页面时自动执行。常见于留言板、评论系统等用户提交内容被展示的场景。相对于上一章节的反射型XSS,存储型XSS与反射型XSS的主要区别如下所示。

对比项存储型 XSS反射型 XSS
攻击向量存储恶意脚本存储在目标服务器(如数据库)恶意脚本仅在 URL 参数等地方,不存储在服务器
触发条件受害者访问包含恶意脚本的页面(如论坛帖子)受害者点击特制链接或提交含恶意代码的表单
持久性长期有效,直到内容被管理员删除单次有效,仅当前请求 - 响应周期生效
传播范围影响所有访问该页面的用户仅影响点击链接的特定用户
典型场景评论区、留言板、用户资料等搜索结果、错误提示、登录表单反馈等
防御重点严格过滤用户输入并转义输出内容对 URL 参数等外部输入进行严格校验和编码

二、源码分析

1、index.php

进入DVWA靶场源目录,找到index.php源码,如下所示。

这段代码是DVWA(Damn Vulnerable Web Application)中存储型XSS关卡的演示页面,主要功能包括:初始化DVWA环境、连接数据库、提供留言板表单(包含姓名和消息输入字段)、根据安全等级(low/medium/high/impossible)加载不同的处理逻辑、支持清空留言板(TRUNCATE),并在页面上显示留言内容和相关参考资料。代码的处理逻辑具体如下所示。

  • 环境初始化:设置路径常量,加载DVWA核心文件,启动会话和PHPIDS安全检测。
  • 页面配置:设置页面标题、ID及帮助按钮。
  • 数据库连接:dvwaDatabaseConnect() 建立MySQL连接。
  • 清空留言板:通过TRUNCATE语句清除所有留言(触发条件:btnClear提交)。
  • 安全等级控制:根据Cookie中的security值加载对应的级别文件(low.php/medium.php/high.php/impossible.php)。
  • 留言板表单:提供姓名(txtName,限10字符)和消息(mtxMessage,限50字符)的输入字段。
  • CSRF防护:仅在impossible级别添加令牌验证(tokenField())。
  • 动态内容渲染:{$html}显示对应级别文件处理后的内容,dvwaGuestbook()展示历史留言。

详细注释后的代码如下所示。

<?php
// 定义DVWA根目录的相对路径(向上两级)
define('DVWA_WEB_PAGE_TO_ROOT', '../../');

// 引入DVWA核心页面初始化文件
require_once DVWA_WEB_PAGE_TO_ROOT . 'dvwa/includes/dvwaPage.inc.php';

// 启动DVWA页面,要求用户已认证并启用PHPIDS安全检测模块
dvwaPageStartup(array('authenticated', 'phpids'));

// 创建新页面对象(初始化页面结构)
$page = dvwaPageNewGrab();

// 设置页面标题(包含级别名称和默认分隔符)
$page['title'] = 'Vulnerability: Stored Cross Site Scripting (XSS)' . $page['title_separator'] . $page['title'];

// 设置当前页面ID(用于标识)
$page['page_id'] = 'xss_s';

// 设置帮助按钮和源码按钮的链接目标
$page['help_button'] = 'xss_s';
$page['source_button'] = 'xss_s';

// 连接数据库
dvwaDatabaseConnect();

// 检查是否点击了"Clear Guestbook"按钮(清空留言板)
if (array_key_exists("btnClear", $_POST)) {
    // 执行SQL清空guestbook表
    $query = "TRUNCATE guestbook;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"], $query) 
        or die('<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? 
            mysqli_error($GLOBALS["___mysqli_ston"]) : 
            (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false) . '</pre>');
}

// 根据Cookie中的安全等级加载对应的文件
$vulnerabilityFile = '';
switch($_COOKIE['security']) {
    case 'low':
        $vulnerabilityFile = 'low.php';    // 低防护
        break;
    case 'medium':
        $vulnerabilityFile = 'medium.php'; // 中防护
        break;
    case 'high':
        $vulnerabilityFile = 'high.php';   // 高防护
        break;
    default:
        $vulnerabilityFile = 'impossible.php'; // 最高防护
        break;
}

// 引入对应安全等级的文件
require_once DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/xss_s/source/{$vulnerabilityFile}";

// 构建页面主体HTML
$page['body'] .= "
<div class=\"body_padded\">
    <h1>Vulnerability: Stored Cross Site Scripting (XSS)</h1>

    <div class=\"vulnerable_code_area\">
        <form method=\"post\" name=\"guestform\">
            <table width=\"550\" border=\"0\" cellpadding=\"2\" cellspacing=\"1\">
                <tr>
                    <td width=\"100\">Name *</td>
                    <td><input name=\"txtName\" type=\"text\" size=\"30\" maxlength=\"10\"></td>
                </tr>
                <tr>
                    <td width=\"100\">Message *</td>
                    <td><textarea name=\"mtxMessage\" cols=\"50\" rows=\"3\" maxlength=\"50\"></textarea></td>
                </tr>
                <tr>
                    <td width=\"100\">&nbsp;</td>
                    <td>
                        <input name=\"btnSign\" type=\"submit\" value=\"Sign Guestbook\" onclick=\"return validateGuestbookForm(this.form);\" />
                        <input name=\"btnClear\" type=\"submit\" value=\"Clear Guestbook\" onClick=\"return confirmClearGuestbook();\" />
                    </td>
                </tr>
            </table>";

// 如果是最高防护等级,添加CSRF令牌
if($vulnerabilityFile == 'impossible.php')
    $page['body'] .= tokenField();

// 继续构建页面(包含动态生成的HTML内容和历史留言)
$page['body'] .= "
        </form>
        {$html}
    </div>
    <br />
    " . dvwaGuestbook() . "
    <br />
    <h2>More Information</h2>
    <ul>
        <li>" . dvwaExternalLinkUrlGet('https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)') . "</li>
        <li>" . dvwaExternalLinkUrlGet('https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet') . "</li>
        <li>" . dvwaExternalLinkUrlGet('https://en.wikipedia.org/wiki/Cross-site_scripting') . "</li>
        <li>" . dvwaExternalLinkUrlGet('http://www.cgisecurity.com/xss-faq.html') . "</li>
        <li>" . dvwaExternalLinkUrlGet('http://www.scriptalert1.com/') . "</li>
    </ul>
</div>";

// 输出最终生成的HTML页面
dvwaHtmlEcho($page);
?>

2、High.php

进入DVWA靶场源目录,找到源码High.php,对比Medium.php源码如下所示。

相比medium.php,high.php关卡主要区别如上图红框所示,即是对留言板的name输入处理部分,将其由大小写敏感的str_replace('<script>', '', $name )变为大小写不敏感的preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name )函数处理,high.php完整代码如下所示

High这段代码实现了一个留言板的数据提交功能。它对留言内容进行了三重防护(移除HTML标签、SQL转义、HTML实体编码),对姓名通过正则表达式移除<script>标签并做SQL转义,最后将数据插入数据库。虽然对留言内容防护充分,但姓名字段的XSS防护仍存在缺陷。

  • 输入获取:通过$_POST接收mtxMessage和txtName。
  • 留言板输入处理
    • trim():去除首尾空格
    • addslashes() + strip_tags():转义并移除HTML标签。
    • mysqli_real_escape_string():防止SQL注入。
    • htmlspecialchars():HTML实体编码。
  • name输入处理
    • preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name ):正则移除<script>标签(不区分大小写)。
    • mysqli_real_escape_string():转义SQL特殊字符。
  • 错误处理:SQL错误时显示详细报错信息

详细注释后的源码如下所示。

<?php
// 检查用户是否点击了提交按钮(btnSign)
if(isset($_POST['btnSign'])) {
    // 获取用户输入的留言和姓名,并去除首尾空格
    $message = trim($_POST['mtxMessage']);
    $name = trim($_POST['txtName']);

    // 对留言内容进行安全处理:
    $message = strip_tags(addslashes($message)); // 先转义特殊字符再移除HTML标签
    // 转义SQL特殊字符防止注入(兼容性写法)
    $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? 
               mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message) : 
               ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call!", E_USER_ERROR)) ? "" : ""));
    $message = htmlspecialchars($message); // HTML实体编码防御XSS

    // 对姓名进行安全处理:
    $name = preg_replace('/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name); // 正则移除<script>标签(不区分大小写)
    // 转义SQL特殊字符
    $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? 
            mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name) : 
            ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call!", E_USER_ERROR)) ? "" : ""));

    // 将数据插入数据库(使用字符串拼接SQL语句)
    $query = "INSERT INTO guestbook (comment, name) VALUES ('$message', '$name');";
    $result = mysqli_query($GLOBALS["___mysqli_ston"], $query) 
              or die('<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? 
                      mysqli_error($GLOBALS["___mysqli_ston"]) : 
                      (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>');
}
?>

3、XSS注入分析

虽然采取了多种防护措施,但Name处仍存在被存储型XSS攻击的可能性,原因如下所示。

  • 留言内容安全:经过strip_tags()htmlspecialchars()双重处理,理论上安全。
  • 姓名name输入处理不足
    • 仅通过正则移除<script>标签(不区分大小写),且未处理其他HTML标签和事件属性
    • 未使用htmlspecialchars()对姓名进行编码。

三、渗透实战

1、渗透准备

配置security为High级别,具体如下所示。

进入到存储型XSS关卡High页面,这是一个留言板的页面,具体如下所示。

http://127.0.0.1/dvwa/vulnerabilities/xss_s/ 

2、修改前端maxlength字段

name处的注入语句为“<img src=0 οnerrοr=alert(document.cookie)>”,留言处填2,和medium关卡一样注入失败,因为name处输入被截断,如下所示。

在name输入框右键元素,果然此关卡maxlength长度同样为10,将maxlength改为100,输入注入语句“<img src=0 οnerrοr=alert(document.cookie)>”,留言处填入2,效果如下所示。

3XSS注入获取cookie

此时注入语句为“<img src=0 οnerrοr=alert(document.cookie)>”,点击sign guestbook后效果如下,展示留言板列表后渗透成功,弹框cookie值,注意此时security为high。

再次进入存储型XSS关卡的low级别页面(此时使用vmnet8对应的网卡ip地址192.168.59.1访问dvwa靶场),再次弹框,如下所示。

此时点击确定后,再次点击clear guestbook,清除有XSS注入语句的留言板,便于后续注入不被影响,如下所示。

### DVWA XSS漏洞利用教程 #### 3.1 环境准备 为了进行DVWA中的XSS攻击实验,需先完成DVWA靶场环境的搭建以及Kali Linux系统的安装配置[^1]。 #### 3.2 设置DVWA难度级别 进入DVWA主页后,在左上角可调整安全性等级至低级以便于学习者更容易理解和实践XSS攻击原理。 #### 3.3 反射跨站脚本攻击(Reflected XSS) 当用户输入的数据未经适当过滤就被返回给浏览器显示时就会发生反射XSS。在DVWA中选择“XSS (Reflected)”选项卡并尝试提交恶意JavaScript代码作为查询参数的一部分来触发弹窗警告框`<script>alert('XSS')</script>`[^2]。 ```html <script>alert('XSS')</script> ``` #### 3.4 存储跨站脚本攻击(Stored XSS) 存储XSS发生在应用程序接收不可信数据并将这些数据永久保存下来之后再发送回其他用户的场景下。可以通过向留言板功能注入持久化的HTML/JS片段实现该类的攻击模拟,比如发布一条包含如下内容的消息: ```html <img src="javascript:alert('Persistent%20XSS')"> ``` #### 3.5 DOM-based 跨站点脚本(DOM Based XSS) DOM-Based XSS不同于上述两种情况,它不涉及服务器端处理过程而是完全由客户端执行所引起的错误行为造成。可以在URL哈希部分附加带有潜在危害性的指令从而影响页面加载后的动态渲染效果,例如访问链接`http://localhost/DVWA/vulnerabilities/xss_d/?default=<img%20src=1%20onerror='alert(String.fromCharCode(88,83,83))'>#`将会导致图像加载失败事件被用来启动一个对话窗口展示字符串"XSS"。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mooyuan天天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值