web漏洞 XSS

形成原理

xss 中文名是“跨站脚本攻击”,英文名“Cross Site Scripting”。
xss也是一种注入攻击,当web应用对用户输入过滤不严格,攻击者写入恶意的脚本代码(HTML、JavaScript)到网页中时,如果用户访问了含有恶意代码的页面,恶意脚本就会被浏览器解析执行导致用户被攻击。
常见的危害有

cookie窃取,session劫持,钓鱼攻击,蠕虫,ddos等。


xss的分类

xss根据其特性和利用方式可以分为三大类:反射型xss,存储型xss,DOM型xss

1、反射型xss

反射型xss一般出现在URL参数中及网站搜索栏中,由于需要点击包含恶意代码的URL才可以触发,并且只能触发一次,所以也被称为“非持久性xss”

2、存储型xss

存储型xss一出现在网站留言板,评论处,个人资料处,等需要用户可以对网站写入数据的地方。

比如一个论坛评论处由于对用户输入过滤不严格,导致攻击者在写入一段窃取cookie的恶意JavaScript代码到评论处,这段恶意代码会写入数据库,当其他用户浏览这个写入代码的页面时,网站从数据库中读取恶意代码显示到网页中被浏览器执行,导致用户cookie被窃取,攻击者无需受害者密码即可登录账户。所以也被称作“持久性xss”。持久性xss比反射型xss危害要大的多。

3、dom型xss

DOM xss是基于dom文档对象模型,前端脚本通过dom动态修改页面,由于不与服务端进行交互,而且代码是可见的,从前端获取dom中的数据在本地执行。

常见的可以操纵dom的对象:URL,localtion,referrer等

案例分析

案例环境:DVWA
DVWA (Dam Vulnerable Web Application)DVWA是用PHP+Mysql编写的一套用于常规WEB漏洞教学和检测的WEB脆弱性测试程序。

包含了SQL注入、XSS、盲注等常见的一些安全漏洞。
官网:http://www.dvwa.co.uk
以下用dvwa中4个漏洞等级Low、Medium、High、Impossible的xss进行举例:

1、反射型xss

①、low

漏洞代码:

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

分析与利用:
直接通过$_GET方式获取name的值,之后未进行任何编码和过滤,导致用户输入一段js脚本会执行。
构造payload:


<script>alert(/xss/)</script>

直接执行代码,如下图:

反射型XSS

②、medium

漏洞代码:

<?php

// 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>标签进行替换为空,这样当在输入上面low等级的payload的时候,就会进行过滤导致代码执行不成功,此时可以多写入一个<script>
EG:
<scrip<script>t>alert(/xss/)</script>,过滤方法把中间的<script>标签替换为空之后 <scrip 与t>重新组合一个<script>,成功执行代码。<>

也可以构造别的标签 如<img src=0 onerror=alert(/xss1/)>
或者把标签转换大小写的方式进行绕过<scRipt>alert(/xss2/)</sCript>

执行payload之后URL分别变化为:
http://localhost/dvwa/vulnerabilities/xss_r/?name=%3Cscrip%3Cscript%3Et%3Ealert%28%2Fxss%2F%29%3C%2Fscript%3E#
http://localhost/dvwa/vulnerabilities/xss_r/?name=%3Cimg+src%3D0+onerror%3Dalert%28%2Fxss1%2F%29%3E+#
http://localhost/dvwa/vulnerabilities/xss_r/?name=%3CscRipt%3Ealert%28%2Fxss2%2F%29%3C%2FsCript%3E#

③、high

漏洞代码:

<?php

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

?>

分析与利用:
preg_replace执行一个正则表达式的搜索和替换,这时候不论是大小写、双层<script>都无法绕过,此时可以使用别的标签,比如刚刚使用过的<img>,构造payload

<img src=0 onerror=alert(/xss/)>

执行payload之后URL变化为
http://localhost/dvwa/vulnerabilities/xss_r/?name=%3Cimg+src%3D0+onerror%3Dalert%28%2Fxss%2F%29%3E#
④、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方法将用户输入的特殊字符转换为 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去除字符串首尾处的空白字符(或者其他字符)。之后stripslashes方法返回一个去除转义反斜线后的字符串(’ 转换为 ’ 等等),双反斜线()被转换为单个反斜线()。
之后mysqli_real_escape_string对字符串特殊符号n r ‘ “ 等进行转义
最终未对用户输入数据进行xss检测编码,直接写入到数据库中,于是造成存储型xss漏洞。

构造利用:

存储型XSS

Message文本框可以直接写入<script>

这里写图片描述

name字段对输入字符有长度限制,这个可以通过burpsuite抓包改包绕过:(burp使用在此不再赘述,请自行查阅教程)

这里写图片描述
修改txtname字段为payload脚本:

这里写图片描述

成功执行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 = htmlspecialchars( $message );
$name = str_replace( '<script>', '', $name );

Message由于使用了htmlspecialchars方法对用户输入数据进行编码转换,因此不存在xss漏洞。
但是name由于仅仅用了str_replace方法把<script>替换为空,于是我们有以下三种方法来绕过:
<script>标签:

<img src=0 onerror=alert(/xss1/)>

大小写转换:

<Script>alert(/xss2/)</sCript>

双重

<sc<script>ript>alert(/xss3/)</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();
}

?>

分析与利用:
这里我们重点关注一行代码:

$message = htmlspecialchars( $message );

Message依旧不可绕过

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

preg_replace执行一个正则表达式的搜索和替换,此时可以使用别的标签<img> <a> <iframe>等,比如刚刚使用过的<img>,构造payload :<img src=0 onerror=alert(/xss/)>,改包替换绕过,成功执行xss代码:

这里写图片描述

④、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();

?>

分析:
在此name和message都使用了htmlspecialchars方法,于是此处不存在xss漏洞。

申明:
本文借鉴:看雪学院 常规Web漏洞
https://www.kanxue.com/book-6-41.htm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值