XSS的绕过姿势(三)

本章提及的几种姿势将在dvwa靶场进行演示

存储型XSS的绕过姿势

image-20230416153751520

URL:

1
http://localhost:8081/dvwa/vulnerabilities/xss_s/

安全等级:Medium

猜测与尝试

存储型,注意到有两个文本框,一个是姓名,一个是评论消息。

可能只对评论信息做了过滤,名字通过前端限制了输入字长,但没做过滤。

尝试修改名字的限制长度,然后在名字的文本框发脚本。

image-20230416154209736

改成100,然后痛快地写脚本

image-20230416154341442

失败:

image-20230416154409127

推测可能对script标签做了过滤,老套路,换img

image-20230416154853881

image-20230416154918355

成功

尝试以下在评论消息框发同样的脚本

image-20230416155125217

image-20230416155137551

失败

message直接没了……可能是过滤掉了尖括号

查看源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );//返回去掉两边空格的字符串
$name = trim( $_POST[ 'txtName' ] );

// Sanitize message input
$message = strip_tags( addslashes( $message ) );//addslashes 向串中‘“\这些预定义字符添加反斜杠,strip_tags:剥去字符串中的 HTML 标签
$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 );//htmlspecialchars函数 老朋友

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

?>

第8行是对评论消息做过滤,非常全面,无懈可击

第14行对名字做过滤,只替换script标签,老毛病了。实战很难遇到这种代码。

安全等级:high

猜测与尝试

故技重施:

image-20230416161212287

image-20230416161342846

成功 img标签真好用。

查看源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

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

?>

第15行,还是只过滤了script标签,其他标签没过滤

总结

img比script标签 更好用,但是如果做了addslashes、strip_tags、htmlspecialchars三重过滤 这就有点麻烦了