DVWA V1.9:Reflected Cross Site Scripting(存储型XSS)
存储型 XSS 介绍
“跨站点脚本(XSS)”攻击是一种注入问题,其中恶意脚本被注入到其他良性的和可信的网站中。
当攻击者使用Web应用程序将恶意代码(通常以浏览器端脚本的形式)发送给不同的最终用户时,会发生XSS攻击。
允许这些攻击成功的缺陷非常普遍,并且在Web应用程序的任何地方使用来自用户的输入在输出中发生,而不验证或编码它。
攻击者可以使用XSS向恶意的用户发送恶意脚本。
终端用户的浏览器没有办法知道脚本不应该被信任,并且将执行JavaScript。
因为它认为脚本来自可信来源,恶意脚本可以访问任何cookie、会话令牌或浏览器保留的其他敏感信息,并与该站点一起使用。
这些脚本甚至可以重写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 = mysql_real_escape_string( $message );
// Sanitize name input
$name = mysql_real_escape_string( $name );
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
//mysql_close();
}
?>
trim(string,charlist)
函数移除字符串两侧的空白字符或其他预定义字符,预定义字符包括、\t、\n、\x0B、\r以及空格,可选参数charlist支持添加额外需要删除的字符。
mysql_real_escape_string(string,connection)
函数会对字符串中的特殊符号(\x00,\n,\r,\,‘,“,\x1a)进行转义。
stripslashes(string)
函数删除字符串中的反斜杠。
可以看到,对输入并没有做XSS方面的过滤与检查,且存储在数据库中,因此这里存在明显的存储型XSS漏洞。
官方提示
低电平将不检查请求输入,然后将其包含在输出文本中使用。
Spoiler: Either name or message field: <script>alert("XSS");</script>.
漏洞利用
name一栏前端有字数限制,抓包改为<script>alert(/name/)</script>:成功弹框:
message一栏输入<script>alert(/xss/)</script>,成功弹框:
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 = mysql_real_escape_string( $message );
$message = htmlspecialchars( $message );
// Sanitize name input
$name = str_replace( '<script>', '', $name );
$name = mysql_real_escape_string( $name );
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
//mysql_close();
}
?>
strip_tags() 函数剥去字符串中的HTML、XML以及PHP的标签,但允许使用标签。
addslashes() 函数返回在预定义字符(单引号、双引号、反斜杠、NULL)之前添加反斜杠的字符串。
可以看到,由于对message参数使用了htmlspecialchars函数进行编码,因此无法再通过message参数注入XSS代码,但是对于name参数,只是简单过滤了《script》字符串,仍然存在存储型的XSS。
官方提示
开发者已经添加了一些保护,但是并没有以相同的方式完成每一个领域。
Spoiler: name field: <sCriPt>alert("XSS");</sCriPt>.
漏洞利用
双写绕过,大小写绕过,两个方法都行,步骤一样不复述了。
双写:<sc<script>ript>alert(/xss/)</script>
大小写:<Script>alert(/xss/)</script>
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 = mysql_real_escape_string( $message );
$message = htmlspecialchars( $message );
// Sanitize name input
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
$name = mysql_real_escape_string( $name );
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
//mysql_close();
}
?>
可以看到,这里使用正则表达式过滤了
官方提示
开发人员现在相信他们可以通过删除模式 “<scrip*t” 来禁用所有JavaScript
Spoiler: HTML events.
漏洞利用
步骤差不多,就不复述了。
利用格式:<img src=1 onerror=alert(1)>
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 = mysql_real_escape_string( $message );
$message = htmlspecialchars( $message );
// Sanitize name input
$name = stripslashes( $name );
$name = mysql_real_escape_string( $name );
$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();
?>
High Stored XSS Source
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = strip_tags( addslashes( $message ) );
$message = mysql_real_escape_string( $message );
$message = htmlspecialchars( $message );
// Sanitize name input
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
$name = mysql_real_escape_string( $name );
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
//mysql_close();
}
?>
Medium Stored XSS Source
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = strip_tags( addslashes( $message ) );
$message = mysql_real_escape_string( $message );
$message = htmlspecialchars( $message );
// Sanitize name input
$name = str_replace( '<script>', '', $name );
$name = mysql_real_escape_string( $name );
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
//mysql_close();
}
?>
Low Stored XSS Source
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = stripslashes( $message );
$message = mysql_real_escape_string( $message );
// Sanitize name input
$name = mysql_real_escape_string( $name );
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
//mysql_close();
}
?>
可以看到,通过使用htmlspecialchars函数,解决了XSS,但是要注意的是,如果htmlspecialchars函数使用不当,攻击者就可以通过编码的方式绕过函数进行XSS注入,尤其是DOM型的XSS。
官方提示
使用内置PHP函数(如htmlspecialchars()“”它可以逃避任何会改变输入行为的值。