2019-3-6 dvwa学习(7)--存储型XSS攻击和XSS攻击总结

什么是存储型XSS攻击(Stored XSS Attacks)?

存储型XSS攻击是指注入的恶意脚本永久存储在目标服务器上的攻击。例如数据库、消息论坛、访问者日志、注释字段等。当受害者请求存储的信息时,它会从服务器中检索恶意脚本。存储的XSS有时也称为持久性(Persistent)或I型XSS。

low
看源码low.php

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

?> 

说明:

  • 用了stripslashes()函数处理message参数,删除输入的反斜杠""

name和message提交abcd<>’/"尝试,观察界面返回结果,其中Message处理了反斜杠。

Name: abcd<>’/\"
Message: abcd<>’/"

查看数据库插表结果。单引号,双引号,斜杠之类的都被转义保存到了数据库中。

MariaDB [dvwa]> select * from guestbook;
+------------+-------------------------+--------------+
| comment_id | comment                 | name         |
+------------+-------------------------+--------------+
|          1 | This is a test comment. | test         |
|          2 | aaa                     | aaa          |
|          3 | abcd<>’/"               | abcd<>’/\"   |
+------------+-------------------------+--------------+
3 rows in set (0.00 sec)

除了以上2点之外,只有在index.php中限制name和message2个输入框的长度。

<tr>
		<td width="100">Name *</td>
		<td><input name="txtName" type="text" size="30" maxlength="10"></td>
</tr>
<tr>
		<td width="100">Message *</td>
		<td><textarea name="mtxMessage" cols="50" rows="3" maxlength="50"></textarea></td>
</tr>

既然长度有限制,那么直接在输入框中注入代码是不行了,可以用burp攻击。
界面上输入bb,抓到结果如下

txtName=b%27b&mtxMessage=b%27b&btnSign=Sign+Guestbook

修改name参数后提交

txtName=<script>alert('haha')</script>&mtxMessage=b%27b&btnSign=Sign+Guestbook

显示结果
在这里插入图片描述
post方法提交,URL中是看不到参数的。不过结果显然是成功了。

MariaDB [dvwa]> select * from guestbook;
+------------+-------------------------+--------------------------------+
| comment_id | comment                 | name                           |
+------------+-------------------------+--------------------------------+
|          1 | This is a test comment. | test                           |
|          2 | aaa                     | aaa                            |
|          3 | abcd<>’/"               | abcd<>’/\"                     |
|          4 | abcd<>’/"               | abcd<>’/\"                     |
|          5 |b'b                     | <script>alert('haha')</script> |
+------------+-------------------------+--------------------------------+
5 rows in set (0.00 sec)

medium
查看源码medium.php

<?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增加了3个函数

name过滤了< script>标签。

$name = str_replace( '<script>', '', $name );

注入方法依然可以利用burp参照反射型的例子实现。
先尝试按照以下注入,结果应该是不成功的:

txtName=<script>alert('haha')</script>&mtxMessage=<script>alert('haha')</script>&btnSign=Sign+Guestbook

数据库结果,注意观察2个参数被过滤部分,不一样的。可以知道medium.php对message和name用不同方法处理的不同效果。

MariaDB [dvwa]> select * from guestbook;
+------------+-----------------+------------------------+
| comment_id | comment         | name                   |
+------------+-----------------+------------------------+
|          1 | alert(\'haha\') | alert('haha')</script> |
+------------+-----------------+------------------------+
1 rows in set (0.00 sec)

high
查看源码high.php

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

?> 

和反射型一样,script标签不能再使用,其他照旧。

$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );

impossible
查看代码impossible.php

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

?> 

增加了3个防范措施

  • Check Anti-CSRF token
  • $db->prepare预处理
  • $name = htmlspecialchars( $name );

以上3点在sql注入和反射型注入中都解释过了。

存储型XSS和反射型XSS非常类似,只是会保存数据库中。

XSS攻击总结

对付XSS攻击可以采取以下这些方法
1.在表单提交或者url参数传递前,对需要的参数进行过滤

2.过滤用户输入的 检查用户输入的内容中是否有非法内容。如<>(尖括号)、”(引号)、 ‘(单引号)、%(百分比符号)、;(分号)、()(括号)、&(& 符号)、+(加号)等。、严格控制输出

可以利用下面这些函数对出现xss漏洞的参数进行过滤

(1)htmlspecialchars() 函数,用于转义处理在页面上显示的文本。

(2)htmlentities() 函数,用于转义处理在页面上显示的文本。

(3)strip_tags() 函数,过滤掉输入、输出里面的恶意标签。

(4)header() 函数,使用header(“Content-type:application/json”); 用于控制 json 数据的头部,不用于浏览。

(5)urlencode() 函数,用于输出处理字符型参数带入页面链接中。

(6)intval() 函数用于处理数值型参数输出页面中。

(7)自定义函数,在大多情况下,要使用一些常用的 html 标签,以美化页面显示,如留言、小纸条。那么在这样的情况下,要采用白名单的方法使用合法的标签显示,过滤掉非法的字符。

通常有一些方式可以测试网站是否有正确处理特殊字符:

><script>alert(document.cookie)</script>
='><script>alert(document.cookie)</script>
"><script>alert(document.cookie)</script>
<script>alert(document.cookie)</script>
<script>alert (vulnerable)</script>
%3Cscript%3Ealert('XSS')%3C/script%3E
<script>alert('XSS')</script>
<img src="javascript:alert('XSS')">
<img src="http://xxx.com/yyy.png" "alert('XSS')">

猜你喜欢

转载自blog.csdn.net/weixin_42555985/article/details/88227885