DVWA之XSS存储型

文章讨论了XSS攻击的两种主要类型——存储型和反射型,解释了它们的工作原理和危害。存储型XSS的攻击脚本存储在服务器,影响广泛,而反射型XSS需要用户交互。文中通过PHP代码示例展示了不同级别的防护措施,指出即使在防护级别提高的情况下,仍有可能通过特定方式绕过过滤机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

理论知识

存储型XSS又称持久型XSS,攻击脚本将被永久地存放在目标服务器的数据库或文件中,具有很高的隐蔽性。反射型XSS的被攻击对象一般是攻击者去寻找的,就比如说:一个攻击者想盗取A的账号,那么攻击者就可以将一个含有反射型XSS的特制URL链接发送给A,然后用花言巧语诱骗A点击链接。当A不小心点进去时,就会立即受到XSS攻击。这种攻击方式需要一点骗术,所以这种攻击范围不是特别的广,并且提交漏洞时要么平台不认,要么会被认定为低危漏洞。

存储型XSS可以采用广撒网的方式,就是攻击者将存储型XSS代码写进一些有XSS漏洞的网站上,只要有用户访问这个链接就会自动中招。所以我们可以看出,存储型XSS的危害性更大,范围更广,可以不需要寻找被攻击对象,只要存储型XSS在服务器上就能实施攻击。所以提交的存储型XSS评级一般为中危漏洞。

这种攻击多见于论坛、博客和留言板。攻击者在发帖的过程中,将恶意脚本连同正常信息一起注入帖子的内容中。随着帖子被服务器存储下来,恶意脚本也永久地被存放在服务器的后端数据库中。当其他用户浏览这个被注入了恶意脚本的帖子时,恶意脚本会在他们的浏览器中得到触发。如果我们能够谨慎对待不明链接,那么反射型XSS攻击将没有多大作为,而存储型XSS则不同,由于它注入在一些我们非常信任的页面中,因此无论我们多么小心,都难免会受到攻击。

LOW

先查看源码

 <?php

if( isset( $_POST[ 'btnSign' ] ) ) {
    // Get input
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );

    // Sanitize message input
    $message = stripslashes( $message );
    $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! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Sanitize name input
    $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! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Update database
    $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>' );

    //mysql_close();
}

?>

1.trim(string,charlist)
函数移除字符串两侧的空白字符或其他预定义字符,预定义字符包括、\t、\n、\x0B、\r以及空格,可选参数charlist支持添加额外需要删除的字符。
2.mysql_real_escape_string(string,connection)
函数会对字符串中的特殊符号(\x00,\n,\r,\,‘,“,\x1a)进行转义。
3.stripslashes(string)函数删除字符串中的反斜杠。
可以看到,对输入并没有做XSS方面的过滤与检查,且存储在数据库中,因此这里存在明显的存储型XSS漏洞。

其实LOW级依然没有任何对XSS又影响的过滤,我们用到语句

<script>alert('1')</script>

和之前一样,弹窗成功就说明攻击成功。
在这里插入图片描述
在这里插入图片描述
存储型和反射型最大的不同就是存储型会将这句恶意代码存储到数据库中,每次打开指定页面都会执行,所以我们现在切换到别的页面再切换回来,无需任何操作,依旧会弹窗在这里插入图片描述
在这里插入图片描述

中级

源码

 <?php

if( isset( $_POST[ 'btnSign' ] ) ) {
    // Get input
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );

    // Sanitize message input
    $message = strip_tags( addslashes( $message ) );
    $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! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $message = htmlspecialchars( $message );

    // Sanitize name input
    $name = str_replace( '<script>', '', $name );
    $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! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Update database
    $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>' );

    //mysql_close();
}

?>

strip_tags() // 函数剥去字符串中的HTML、XML以及PHP的标签,但允许使用标签。
addslashes() // 函数返回在预定义字符(单引号、双引号、反斜杠、NULL)之前添加反斜杠的字符串。
htmlspecialchars(string,flags,character-set,double_encode) // 把预定义的字符转换为 HTML 实体。
由于对message参数使用了htmlspecialchars函数进行编码,因此无法再通过message参数注入XSS代码,但是对于name参数,只是简单过滤了

观察可知,该代码只针对message参数进行了彻底的过滤,但对于name参数依然存在XSS漏洞,这里可以用两种方法,一种是抓包改包,一种是双写或者大写绕过。

<s<script>cript>alert('1')</script>

需要注意name参数有长度限制,但这种限制比较蠢,只在页面上限制,并没有在源码上限制,我们我们可以更改限制
先更改限制在这里插入图片描述

在这里插入图片描述

高级

源码

<?php

if( isset( $_POST[ 'btnSign' ] ) ) {
    // Get input
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );

    // Sanitize message input
    $message = strip_tags( addslashes( $message ) );
    $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! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $message = htmlspecialchars( $message );

    // Sanitize name input
    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
    $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! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Update database
    $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>' );

    //mysql_close();
}

?> 

相对于中级,这次name参数对script进行了彻底过滤,我们可以用插入图片的方式进行绕过

<img src=1 onerror=alert(1) />

具体方法同中级

如果采用抓包的方式
在这里插入图片描述
直接更改name参数就可以

<think>嗯,用户想了解DVWA中的存储XSS漏洞示例及防御方法。首先,我得回忆一下DVWA是什么,DVWA是一个用于练习Web应用漏洞的平台,包含不同难度的漏洞环境。存储XSS是其中一种漏洞类,恶意脚本被存储在服务器上,比如数据库里,当其他用户访问时就会执行。 根据用户提供的引用,特别是引用1和2,里面提到了存储XSS的原理和不同安全等级(Low、Medium、High、Impossible)的处理方式。需要分别分析每个级别的示例和防御方法。比如在Low级别,可能没有任何过滤,直接输入脚本就会被存储;Medium级别可能有一些过滤,比如转义<script>标签;High级别可能有更严格的过滤或使用黑名单;而Impossible级别可能结合了输入验证和输出编码,或者使用CSRF令牌。 还要注意用户提到的引用3,虽然主要讲反射XSS,但防御方法可能有共通之处,比如输入过滤和输出编码。需要确保回答中涵盖不同级别的示例代码,比如PHP中的处理方式,以及如何通过输入验证、输出编码、内容安全策略(CSP)等方式进行防御。 用户可能需要具体的漏洞示例,比如在留言板中注入<script>alert('XSS')</script>,然后展示不同级别的后端代码如何处理。同时,防御方法需要分点说明,比如输入验证、输出编码、CSP、HttpOnly Cookie等,确保结构清晰。 另外,用户可能希望了解如何实际操作,比如在DVWA中如何测试这些漏洞,以及防御措施的具体实现。需要确保回答中的代码示例正确,比如使用htmlspecialchars函数进行输出编码,或者使用正则表达式过滤特定标签。 最后,生成相关问题时要围绕存储XSS的不同方面,比如各等级区别、实际应用中的案例、CSP的作用、HttpOnly如何帮助防御,以及与其他XSS的比较。确保问题能帮助用户进一步深入理解。</think>### DVWA 存储 XSS 漏洞示例及防御方法 #### 一、存储 XSS 漏洞示例 在 DVWA 中,存储 XSS 漏洞常出现在用户输入持久化存储的场景,例如留言板功能。攻击者提交包含恶意脚本的内容后,脚本会被存入数据库,其他用户访问时自动执行该脚本。 **示例代码(Low 级别未过滤):** ```php // 后端处理代码(Low级别) $message = $_POST['mtxMessage']; $name = $_POST['txtName']; $query = "INSERT INTO guestbook (comment, name) VALUES ('$message', '$name');"; ``` 攻击者可输入以下内容实现攻击: `<script>alert('XSS')</script>` 当其他用户查看留言时,脚本会触发弹窗[^1][^2]。 #### 二、不同安全等级的防御方法 1. **Low 级别(无过滤)** - **漏洞原因**:直接拼接用户输入到 SQL 语句,未做过滤。 - **修复建议**:对用户输入进行 HTML 实体编码,例如使用 PHP 的 `htmlspecialchars()` 函数: ```php $message = htmlspecialchars($_POST['mtxMessage'], ENT_QUOTES, 'UTF-8'); ``` 2. **Medium 级别(部分过滤)** - **漏洞原因**:使用 `stripslashes()` 和 `htmlspecialchars()` 但未完全覆盖所有危险字符。 - **修复示例**: ```php $message = strip_tags($_POST['mtxMessage']); // 移除 HTML 标签 ``` 3. **High 级别(严格过滤)** - **漏洞原因**:使用正则表达式黑名单过滤 `<script>` 标签,但可能被其他标签绕过。 - **修复示例**: ```php $message = preg_replace('/<script.*?>/i', '', $_POST['mtxMessage']); // 过滤 script 标签 ``` 4. **Impossible 级别(综合防御)** - **防御方法**: - 输入验证:仅允许特定字符(如字母、数字)。 - 输出编码:强制使用 `htmlspecialchars()`。 - CSRF 防护:添加 Token 验证[^1]。 ```php $message = htmlspecialchars(strip_tags($_POST['mtxMessage']), ENT_QUOTES, 'UTF-8'); ``` #### 三、通用防御策略 1. **输入验证** - 使用白名单机制限制输入格式(如正则表达式 `/[a-zA-Z0-9\s]+/`)。 2. **输出编码** - 对动态内容进行 HTML 编码(如 PHP 的 `htmlentities()`)。 3. **内容安全策略(CSP)** - 通过 HTTP 头限制脚本来源: ```http Content-Security-Policy: default-src 'self' ``` 4. **HttpOnly Cookie** - 设置 Cookie 的 `HttpOnly` 属性防止通过 `document.cookie` 窃取。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值