DVWA-XSS (Stored)-存储型XSS

文章详细分析了不同级别存储型XSS漏洞的测试环境,从低级到高级展示了如何通过PHP函数如strip_tags、addslashes、htmlspecialchars、preg_replace等进行输入过滤和转义,以防止恶意脚本存储在数据库中并执行。同时,提到了CSRF防护措施,包括检查令牌和使用PDO进行预编译的SQL查询,以增强Web应用的安全性。
摘要由CSDN通过智能技术生成

存储型XSS 存储在数据库中。XSS 是永久性的,直到重置数据库或手动删除有效负载。

低水平

1、查找输入输出点,在Name和message输入内容,内容显示在了页面下方,且再次点进该页面,内容仍显示在了页面上,说明输入的内容被存储了。

2、构造脚本,输入带script脚本的XSS,显示了弹窗。 因为内容被存储,所以每次点进该页面,都会出现一个弹窗。

每次刷新页面,都会出现该弹窗。这说明输入的恶意<script>脚本被存储在后端数据库或文件中,在每次打开这个页面的时候,脚本都会执行一遍,系统存在存储型XSS漏洞。


<?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();
}

?>

初级存储型XSS渗透测试环境对输入的“name”和“message”参数值主要使用了3个函数进行处理:trim()函数、stripslashes()函数和mysqli_real_escape_string()函数。trim()函数用于删除字符串两侧的空白字符或者其他自定义字符。源代码并没有指定自定义字符,因此,主要用于删除“name”和“message”参数值两侧的空白字符。stripslashes()函数用于删除字符串中的反斜杠。mysqli_real_escape_string()函数用于转义字符串中的特殊字符。上述3个函数都无法实现JavaScript脚本的过滤,因此,插入数据的SQL语句(变量$query的值)被执行后,将输入的恶意脚本插入到数据库中。

中级

<?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();
}

?>

①对“message”参数加强了防护:使用addslashes()函数在每个双引号“"”前添加反斜杠;使用strip_tags()函数删除字符串中的HTML、XML以及PHP的标签;使用htmlspecialchars()函数将所有的预定义字符转换成了HTML实体,不会将其作为脚本执行。因此,“Message”文本框做了较强的防护,无法通过该输入处插入JavaScript脚本。②对“name”参数也加强了防护:使用“str_replace(′<script>′,′′,$name);”语句将“<script>”字符串替换成空字符串。 

  1. 使用 strip_tags 函数移除 $message 中的HTML标签。
  2. 使用 addslashes 函数对 $message 进行转义,防止SQL注入。
  3. 使用 mysqli_real_escape_string 函数对 $message 进行额外的转义,这是为了防止SQL注入攻击。这个函数会根据当前数据库的字符集,将可能导致SQL语法错误的字符进行转义。
  4. 最后,使用 htmlspecialchars 函数将 $message 转换为HTML实体,这样可以防止HTML标签被浏览器解析为HTML代码。

构造攻击脚本,“name”参数仅仅将指定的字符串“<script>”进行了替换,因此,大小写和双写就可以绕过这个防护。同时,在前端页面中,“Name”文本框有字符长度最大为10的限制,我们借助Burp Suite来绕过该字符长度限制。

高水平

开发人员认为他们已经通过删除模式“<s*c*r*i*p*t”来禁用所有脚本使用。

高级存储型XSS渗透测试环境的源代码中“name”参数的值使用preg_replace()函数基于正则表达式进行替换,且添加“i”修饰符,不区分大小写,以防止发生大小写绕过和双写绕过的XSS攻击。与高级反射型XSS渗透测试环境的防护机制相同,因此,考虑使用标签绕过即可。


<?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();
}

?>

不可能的水平

使用内置的PHP函数(如“htmlspecialchars()”), 可以转义任何会改变输入行为的值。


<?php

if( isset( $_POST[ 'btnSign' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // 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)) ? "" : ""));
    $message = htmlspecialchars( $message );

    // Sanitize name input
    $name = stripslashes( $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)) ? "" : ""));
    $name = htmlspecialchars( $name );

    // Update database
    $data = $db->prepare( 'INSERT INTO guestbook ( comment, name ) VALUES ( :message, :name );' );
    $data->bindParam( ':message', $message, PDO::PARAM_STR );
    $data->bindParam( ':name', $name, PDO::PARAM_STR );
    $data->execute();
}

// Generate Anti-CSRF token
generateSessionToken();

?>

不可能水平,

这是一个将用户输入数据插入到数据库中的 PHP 脚本,并增加了防范CSRF攻击的安全措施。

脚本首先使用 `checkToken()` 函数验证用户提交的token是否与当前session中的token相同,以避免CSRF攻击的风险。

随后,脚本使用多种净化方法来加强安全性,包括:

- 使用 `strip_slashes()` 函数删除用户输入消息和用户名中可能存在的反斜杠字符。
- 使用 `mysqli_real_escape_string()` 函数对用户输入数据进行SQL注入攻击的防御。
- 使用 `htmlspecialchars()` 函数转义用户输入消息和用户名中的特殊字符。

此外,脚本还使用了PDO数据库抽象层来执行对数据库的操作,避免了使用原生SQL语句时,出现的SQL注入漏洞。

最后,脚本调用 `generateSessionToken()` 函数生成新的Session token。

使用这些净化方法和安全措施可以大大增强Web应用程序的安全性和可靠性,并避免恶意攻击。

防护

  • 禁止解析为html标签

有的输入显示没有过滤字符,但是页面不会显示alert,是因为显示被过滤了。复制如下元素,显示为<span>&lt;/span&gt;10.100.40.35&lt;script&gt;alert(1)&lt;/script&gt;&lt;span&gt;</span> 。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值