dvwa XSS(跨站脚本攻击)通关手册

Preface

本博文仅用于信息安全防御,切勿用于其他用途!!!!!

XSS

XSS:跨站攻击脚本

恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页时
,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户
的目的。

OWASP TOP10 一直排前十

XSS 可以用来进行钓鱼攻击,前端js挖矿、获取用户cookie,甚至对
用户主机进行控制

XSS形成原因:
程序对输入和输出的控制不够严格,导致攻击者的脚本输入后,
在输出到前端时被浏览器当作有效的代码解析执行从而产生危害。

XSS攻击的危害:
1.盗取账号
2.控制企业数据,读取、篡改、添加、删除敏感数据
3.盗窃企业重要的具有商业价值的资料
4.非法转账
5.强制发送电子邮件
6.网站挂马
7.控制受害者机器,向其它网站发起攻击

XSS(Reflected)

反射型XSS,也叫非持久性CSS,当用户访问一个带有XSS代码的
URL请求时,服务器端接收数据后处理,然后把带有XSS代码
的数据发送到浏览器,浏览器解析这段XSS代码的数据后,
最后造成XSS漏洞。这个过程就像一次反射,故称反射型XSS

反射型XSS不会存储在服务器端 我们利用需要结合社工等条件。

XSS(Stored)

存储型XSS

存储型XSS和反射型XSS形成原因一样,不同的是存储型XSS
后台会将构造的payload保存起来,构成更加持久的危害,因此
存储型XSS也称“永久型XSS”

存储型XSS 不需要我们结合社工等条件触发,破坏性要大于反射型XSS

可以从网上搜集payload

XSS(DOM)

HTML DOM 树

DOM XSS 是一种特殊类型的反射型 XSS, 它是基于DOM文档
对象模型的一种漏洞。

Low

XSS(Reflected)

Source Code

<?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>';
}

?> 

array_key_exists(key,array) 函数检查某个数组中是否存在指定的键名,如果键名存在则返回 true,如果键名不存在则返回 false

key 	必需。规定键名。
array 	必需。规定数组。

Solution

这关我们由源代码知道,作者并没有对我们的输入进行过滤,所以我们可以任意插入js代码,比如我们插入

<script>alert(1)</script>
在这里插入图片描述

XSS(Stored)

Source Code

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

?> 

$GLOBALS — 引用全局作用域中可用的全部变量
trigger_error(errormsg,errortype) 函数创建用户级别的错误消息。

errormsg 	必需。规定错误消息。最大长度 1024 字节。
errortype 	可选。规定错误类型。可能的值:

E_USER_ERROR
E_USER_WARNING
E_USER_NOTICE(默认)

mysql_query(query,connection) 函数执行一条 MySQL 查询

query 	    必需。规定要发送的 SQL 查询。注释:查询字符串不应以分号结束。
connection 	可选。规定 SQL 连接标识符。如果未规定,则使用上一个打开的连接。

作者对我们的输入进行了两边去空,然后去除了message变量的反斜杠,并且对我们的输入SQL语句中的特殊字符,但并不影响我们进行xss攻击。

Solution

我们可以直接从message一栏输入我们想要攻击的代码(因为name一栏的最长限制为10,所以如果我们想要在name处攻击,那么就需要更改前端或者抓包更改)

<script>alert(1)</script>
在这里插入图片描述

XSS(DOM)

Source Code

服务器端代码

<?php

# No protections, anything goes

?> 

Solution

由源代码知道,作者没有做任何防护,所以我们直接在地址栏提交我们的xss攻击

http://127.0.0.1/dvwa/vulnerabilities/xss_d/?default=%3Cscript%3Ealert(1)%3C/script%3E

在这里插入图片描述

Medium

XSS(Reflected)

Source Code

 <?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>";
}

?>

Solution

这关相较与Low难度,对我们输入的script标签进行了过滤且替换为空,我们一听到替换为空,那么我们就想到用双写或者大小写混写来进行绕过处理

所以我们可以输入

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

<sCript>alert(1)</sCript>
在这里插入图片描述

XSS(Stored)

Source Code


<?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(string,allow) 函数剥去字符串中的 HTML、XML 以及 PHP 的标签。

string 	必需。规定要检查的字符串。
allow 	可选。规定允许的标签。这些标签不会被删除。

addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。

预定义字符是:

单引号(')
双引号(")
反斜杠(\)
NULL

Solution

此关对我们的message变量彻底进行了过滤,首先在预定义字符增加反斜杠,然后删除我们的html标签,最后又将我们的预定义字符转换为html实体,所以彻底杜绝了我们的攻击

但是对于name变量它只把script标签替换为空,我们可以采用混写或者双写来进行绕过。

我们首先通过更改前端来把最大长度更改,然后写入我们的注入代码
在这里插入图片描述

<sCript>alert(1)</sCript>

<s<script>cript>alert(2)</s<script>cript>

XSS(DOM)

Source Code

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

?> 

Solution

这关变化的是,它把我们的script标签进行了处理,只要我们输入script标签(无论大小写)就会跳转到主页面,所以这关我们可以用其它标签进行绕过。(由前端代码得知我们是往option标签拼接语句,所以需要我们注意的是如果用其他标签进行攻击的时候,就要闭合其它的标签)
在这里插入图片描述

</option></select><img src='' onerror=alert(1)>
在这里插入图片描述
</option></select><body onload=alert(3)>
在这里插入图片描述

High

XSS(Reflected)

Source Code

 <?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>";
}

?>

Solution

此关源代码,把我们的script只要是按照顺序输入的都替换成了空,且不区分大小写,所以我们的双写绕过和混写绕过都无法进行了,所以我们就不能用script标签了,但是我们可以用运用body、img、iframe等标签配合事件来进行绕过

<body onload=alert(1)></body>

在这里插入图片描述

<a herf='' onclick=alert(1)>click here</a>

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

<img src='' onerror=alert(2)>//因为src地址错误,所以执行onerror

在这里插入图片描述

XSS(Stored)

Source Code

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

?>

Solution

此难度相较于medium难度来说,对于message变量的过滤一样严格,而且还相当于屏蔽了我们的script标签,意味着我们需要用别的标签来进行xss攻击

<body onload=alert(3)>

<img src='' onerror=alert(3)>

<a herf onclick=alert(3)>click here</a>

在这里插入图片描述

XSS(DOM)

Source Code

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

?>

Solution

作者这会直接用白名单来限制我们的选择只能是它提供的,如果不是,则直接跳转到主页面

但是我们可以用#来绕过,因为在url中#后面的数据不会传到服务器端。

具体可以参考这片文章:参考文章

所以我们可以构造如下payload

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

在这里插入图片描述

Impossible

XSS(Reflected)

Source Code

<?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() 函数把预定义的字符转换为 HTML 实体。

预定义的字符是:
& (和号)成为 &
" (双引号)成为 "
' (单引号)成为 '
< (小于)成为 <
> (大于)成为 >

Solution

此难度下,作者不仅验证了我们的token还将我们的所有的输入都当做字符串,且预定义字符转换为HTML实体,因为我们注入的js代码都是标签,都必须有<>,所以我们就彻底不能进行绕过了

XSS(Stored)

Source Code

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

?> 

Solution

由源代码可知,作者不仅验证了我们的身份,而且还对我们的所有输入进行了 htmlspecialchars过滤,所以我们无法进行xss攻击

XSS(DOM)

Source Code

<?php

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

?> 

这里服务器端代码没有了,那么一定是在前端代码上做了手脚。

在这里插入图片描述

Solution

我们可以看到前端的源码与前三个难度的源码唯一区别是在,对于lang变量的url解码,但是impossible难度并没有对我们的输入进行解码,所以上传上去的只是URL编码,所以就不存在了XSS攻击。
在这里插入图片描述

本文所有函数解析参考自w3cschool

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值