[网络安全]DVWA之XSS(Stored)攻击姿势及解题详析合集


免责声明:本文仅分享XSS攻击相关知识,不承担任何法律责任。
DVWA请读者自行安装,本文不再赘述。


XSS(Stored)-low level

源代码

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

?> 

trim() 函数移除字符串两侧的空格,以确保数据在插入到数据库时没有多余的空白字符。

使用 stripslashes() 函数去除反斜杠,同时使用 mysqli_real_escape_string() 函数转义特殊字符。

使用 mysqli_real_escape_string() 函数将特殊字符转义为它们的 Unicode 编码,以确保它们不会被视为 SQL 语句的一部分。
从源代码来看,它没有明确的防御 XSS 攻击的措施。

姿势

基于Message板块

Payload:<script>alert("qiu")</script>
在这里插入图片描述

基于Name板块

Name只允许输入八个字符,而XSS语句是比八个字符的。
绕开长度限制: \color{#00FF00}{绕开长度限制:} 绕开长度限制:页面Name元素maxlength改为100

在这里插入图片描述
Payload:<script>alert("qiu")</script>
在这里插入图片描述

XSS(Stored)-medium level

源代码

<?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 进行了三种过滤:

  • 使用 strip_tags() 函数移除所有 HTML 和 PHP 标签
  • 使用 addslashes() 函数将字符串中的特殊字符转义(例如单引号、双引号和反斜杠)
  • 使用 htmlspecialchars() 函数message中特殊字符(例如 < > ' " &)转换为相应的 HTML 实体,以防止 XSS 攻击。

对姓名 $name 进行了两种过滤:

  • 使用 str_replace() 函数将字符串中的<script>替换为空字符串
  • 使用 mysqli_real_escape_string() 函数转义字符串中的特殊字符(例如单引号和双引号)以防止 SQL 注入攻击。

姿势

双写绕过

message为注入点,Payload:<scrip<script>t>alert(1)</scr<script>ipt>
在这里插入图片描述无回显,原因:htmlspecialchars() 函数message中的特殊字符(例如 < > ' " &)转换为相应的 HTML 实体

Name为注入点:
在这里插入图片描述


大小写绕过

由于str_replace() 函数对大小写敏感,可通过大小写绕过限制。
Name为注入点,Payload:<Script>alert(1)</sCript>
在这里插入图片描述


Xss标签绕过

由于针对Name的str_replace() 函数只对<script>起过滤作用,因此可使用不同的Xss标签进行绕过。
Name为注入点,Payload:<img src=1 onerror=alert(1)>
在这里插入图片描述


XSS(Stored)-high level

源代码

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

?> 

对留言内容 $message 进行了三种过滤:

  • 使用 strip_tags() 函数移除所有 HTML 和 PHP 标签
  • 使用 addslashes() 函数将字符串中的特殊字符转义(例如单引号、双引号和反斜杠)
  • 使用 htmlspecialchars() 函数将特殊字符如 < > ' " &转换为相应的 HTML 实体,以防止 XSS 攻击

对姓名 $name 进行了两种过滤:

  • 使用 preg_replace() 函数将字符串中的 <script> 替换为空字符串
  • 使用mysqli_real_escape_string() 函数转义字符串中的特殊字符(例如单引号和双引号)以防止 SQL 注入攻击。

姿势:Xss标签绕过

切换 X S S 标签 \color{#FF00FF}{切换XSS标签} 切换XSS标签

  1. Name为注入点,Payload:<img src=1 onerror=alert(1)>

在这里插入图片描述

  1. Name为注入点,Payload:<audio src=1 onerror=alert(1)>

在这里插入图片描述


XSS(Stored)-Impossible level

源代码

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

?> 

代码审计

if( isset( $_POST[ 'btnSign' ] ) ) {

该行通过 isset() 函数判断 PHP 脚本是否是由提交按钮 btnSign 触发的。如果是,则执行后续代码。

接着,代码调用了 checkToken() 函数,用于验证 Anti-CSRF token 是否匹配:

checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

这个函数需要三个参数:用户提交的 CSRF token、服务器存储的 CSRF token 和当前页面的 URL。函数会检查两个 token 是否相同,以及请求是否来自于正确的来源,从而避免跨站点攻击。

接下来的代码获取了用户输入的姓名和留言信息:

$message = trim( $_POST[ 'mtxMessage' ] );
$name    = trim( $_POST[ 'txtName' ] );

trim() 函数移除字符串两侧的空格。这样可以确保数据在插入到数据库时没有多余的空白字符。

然后,使用 stripslashes() 函数去除反斜杠,同时使用 mysqli_real_escape_string() 函数转义特殊字符:

$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 );

$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 );

mysqli_real_escape_string() 将特殊字符转义为 Unicode 编码。

最后,使用 htmlspecialchars() 函数对用户输入的数据进行 HTML 编码,以防止 XSS 攻击。该函数将 HTML 特殊字符转义为实体,从而避免恶意代码在浏览器中执行。

接下来的代码,使用 PDO 对用户数据进行插入:

$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();

$db 是一个预先创建的 PDO 数据库连接。这个代码段使用了 PDO 的预准备语句(prepared statement)功能,这是一种避免 SQL 注入攻击的最佳方法之一。使用 bindParam() 函数将实际插入的值与数据库字段绑定起来,确保即使用户输入包含非法字符也不会对 SQL 查询产生影响。

最后,调用 generateSessionToken() 函数来生成 Anti-CSRF token:

generateSessionToken();

这个函数采用某些规则生成随机的 session_token,并将其存储在 PHP 会话中。


总结

以上为[网络安全]DVWA之XSS(Reflected)攻击姿势及解题详析合集,读者可躬身实践。

[网络安全]DVWA之XSS合集:

[网络安全]DVWA之XSS(DOM)攻击姿势及解题详析合集

[网络安全]DVWA之XSS(Reflected)攻击姿势及解题详析合集

我是秋说,我们下次见。

posted @ 2023-05-18 19:14  秋说  阅读(64)  评论(0编辑  收藏  举报  来源