DVWA靶场-XSS(跨站脚本攻击)

第十关:XSS(跨站脚本攻击)

      XSS,全称Cross Site Scripting,即跨站脚本攻击,某种意义上也是一种注入攻击,是指攻击者在页面中注入恶意的脚本代码,当受害者访问该页面时,恶意代码会在其浏览器上执行。

反射型XSS

Low

<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    
    
    // Feedback for end user
    echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
?>

      分析源码可得,代码直接打印用户的输入,没有做任何其他的防护。使用最简单的xss payload:<script>alert("xss")</script>
在这里插入图片描述
在这里插入图片描述

Medium

<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    
    
    // Get input
    $name = str_replace( '<script>', '', $_GET[ 'name' ] );

    // Feedback for end user
    echo "<pre>Hello ${name}</pre>";
}
?>

代码中使用str_replace函数对<script>字符进行过滤,然而用处不大,可使用大小写和双写进行绕过
在这里插入图片描述
在这里插入图片描述

High

<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    
    
    // Get input
    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );

    // Feedback for end user
    echo "<pre>Hello ${name}</pre>";
}
?>

源码分析可得,代码将用户输入的数据使用了正则表达式,将<script给过滤了,因此这里不能使用<script>标签构造payload,所以需要使用其他的标签构造。此时使用payload语句<img src="" onerror=alert("xss")>
在这里插入图片描述
在这里插入图片描述

Impossible

<?php
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    
    
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $name = htmlspecialchars( $_GET[ 'name' ] );

    // Feedback for end user
    echo "<pre>Hello ${name}</pre>";
}
// Generate Anti-CSRF token
generateSessionToken();
?>

htmlspecialchars(string): 把预定义的字符 “<” (小于)、 “>” (大于)、& 、‘’、“” 转换为 HTML 实体,防止浏览器将其作为HTML元素
使用htmlspecialchars函数将name参数中的预定义字符转换为html实体,这样防止了我们填入标签被浏览器解析。有效防御了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();
}
?>

trim(str,str1)
       移除str字符两侧的预定义字符,预定义字符包括\t 、 \n 、\x0B 、\r以及空格,可选参数str1支持添加额外需要删除的字符

stripslashes(str)
       去除掉string字符的反斜杠\

mysqli_real_escape_string(str,connection)
       函数会对字符串str中的特殊符号(\x00,\n,\r,\,‘,“,\x1a)进行转义。

$GLOBALS
       引用全局作用域中可用的全部变量。$GLOBALS这种全局变量用于在 PHP 脚本中的任意位置访问全局变量(从函数或方法中均可)。PHP 在名为 $GLOBALS[index] 的数组中存储了所有全局变量。变量的名字就是数组的键。

       输入图中的数据,页面中多了一条记录,就是abb,被存储到数据库中,这种xss危害性非常大,具有永久性,且可以窃取所有访问该页面的用户的cookie,而不需要像csrf和xss需要欺骗用户进行点击。
在这里插入图片描述

Medium

<?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框做了很多限制,但是对name未作过多的限制,只使用了str_replace函数过滤字符<script>,所以可用大小写进行绕过。并且在页面中还设置了name框的输入限制,可使用浏览器修改数值绕过限制
在这里插入图片描述
在这里插入图片描述

High

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

与medium级别代码相比,name部分设置了<script>的正则表达式,所以不能使用<script>构造payload
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Impossible

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

impossible代码对name参数也做了严格的过滤,导致name参数的位置也无法进行xss攻击。

DOM型XSS

Low

<?php
# No protections, anything goes
?>

       源码中,没有做任何防护。所以使用最简单的注入语句。注入成功后在浏览器的解析代码中添加成功。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Medium

<?php
// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
    
    
    $default = $_GET['default'];
    # Do not allow script tags
    if (stripos ($default, "<script") !== false) {
    
    
        header ("location: ?default=English");
        exit;
    }
}
?>

从源码中可以得到,首先判断前端提交数据中是否存在default,并判断default是否为空。不为空则将default中的值赋值给变量,之后使用stripos函数检测default中是否存在<script,如果有则令default=English。由于这里使用了stripos函数,且对大小写不敏感,所以构造payload要避开script,使用<svg οnlοad=alert(“xss”)>

当访问url:http://127.0.0.1/dvwa/vulnerabilities/xss_d/?default=<svg onload=alert("xss")>,此时页面没有任何弹框,说明注入未成功,查看网页源码发现,payload被插入到option中的value值中。
在这里插入图片描述

因此需要闭合标签,</option><svg onload=alert("xss")>,使用该payload后发现依然未注入成功,继续闭合标签</option></select><svg onload=alert("xss")>,此时注入成功
在这里插入图片描述
在这里插入图片描述

High

<?php
// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
    
    

    # White list the allowable languages
    switch ($_GET['default']) {
    
    
        case "French":
        case "English":
        case "German":
        case "Spanish":
            # ok
            break;
        default:
            header ("location: ?default=English");
            exit;
    }
}
?>

从源码中发现程序使用白名单写死了,于是查看帮助,其意思是需要找一种方法在本地运行你的JS代码而无需经过服务器端的处理。这里提供的一种方法就是,使用#号,URL栏的#号之后的内容并不会发送至服务器端,JS应用该符号实现在页面创建加载过程中定向到指定的页面内容上。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Impossible

<?php

# Don't need to do anything, protction handled on the client side

?>

impossible代码中没有任何东西,其中注释的意思是保护程序的代码写在客户端中。并且在输入框中输入数据后发现嵌入网页源码中的数据是经过url编码的,说明程序对用户输入的数据没有进行url解码,然后直接赋值给option标签,因此不存在xss漏洞

猜你喜欢

转载自blog.csdn.net/qq_43707926/article/details/123405034