XSS Stored 测试
dvwa存储型XSS
存储型XSS:会把用户输入的数据“存储”在服务器端,一般出现在需要用户可以输入数据的地方,比如网站的留言板、评论等地方,当网站这些地方过滤不严格的时候,就会被黑客注入恶意攻击代码,存储在服务器端,每当用户加载该页面时,都会受到攻击,所以这种攻击行为也称为“持久型XSS(Persistent XSS)”。
漏洞测试
low级别

在Name和Message输入框中分别输入一个String(admin)发现输入的数据会显示在当前页面中,同时可以知道数据提交是以POST请求的方式
查看源码:
<?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();
}
?>
代码审计发现,并不存在Protect,trim()函数、stripslashes()函数、mysqli_real_escape_string()函数等不会对JS代码进行过滤
trim(string,charlist) 函数移除字符串两侧的空白字符或其他预定义字符。
string 必需。规定要检查的字符串。
charlist 可选。规定从字符串中删除哪些字符。如果被省略,则移除以下所有字符:
"\0" - NULL
"\t" - 制表符
"\n" - 换行
"\x0B" - 垂直制表符
"\r" - 回车
" " - 空格
########################################################################################
stripslashes(string) 函数删除由 addslashes() 函数添加的反斜杠。
string 必需。规定要检查的字符串。
提示:该函数可用于清理从数据库中或者从 HTML 表单中取回的数据。
########################################################################################
addslashes(string) 函数返回在预定义字符之前添加反斜杠的字符串。
预定义字符是:
单引号(')
双引号(")
反斜杠(\)
NULL
string 必需。规定要转义的字符串。
提示:该函数可用于为存储在数据库中的字符串以及数据库查询语句准备字符串。
########################################################################################
mysql_real_escape_string(string,connection) 函数转义 SQL 语句中使用的字符串中的特殊字符。
下列字符受影响:
\x00
\n
\r
\
'
"
\x1a
如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。
string 必需。规定要转义的字符串。
connection 可选。规定 MySQL 连接。如果未规定,则使用上一个连接。
提示:可使用本函数来预防数据库攻击。
构造payload,执行最简单的XSS攻击
POST data
txtName=admin&mtxMessage=<script>alert("_XSS_")</script>&btnSign=Sign+Guestbook
恶意代码被存入服务端,每当用户打开该网页都会受到攻击
服务端数据库文件已存入攻击者的恶意代码

进入该网页,触发恶意攻击

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();
}
?>
经过代码审计,可以发现medium级别进行了Protect,对POST请求到的的内容进行过滤:
str_replace()函数 对 Name data进行<script>标签匹配置空
strip_tags()函数 对 message data进行标签匹配删除
str_replace(find,replace,string,count) 函数以其他字符替换字符串中的一些字符(区分大小写)。 该函数必须遵循下列规则: 如果搜索的字符串是数组,那么它将返回数组。
如果搜索的字符串是数组,那么它将对数组中的每个元素进行查找和替换。
如果同时需要对数组进行查找和替换,并且需要执行替换的元素少于查找到的元素的数量,那么多余元素将用空字符串进行替换
如果查找的是数组,而替换的是字符串,那么替代字符串将对所有查找到的值起作用。
注释:该函数区分大小写。请使用 str_ireplace() 函数执行不区分大小写的搜索。 参数 描述
find 必需。规定要查找的值。
replace 必需。规定替换 find 中的值的值。
string 必需。规定被搜索的字符串。
count 可选。对替换数进行计数的变量。 ########################################################################################### strip_tags(string,allow) 函数剥去字符串中的 HTML、XML 以及 PHP 的标签。 注释:该函数始终会剥离 HTML 注释。这点无法通过 allow 参数改变。 参数 描述
string 必需。规定要检查的字符串。
allow 可选。规定允许的标签。这些标签不会被删除。
分析可知要想利用XSS攻击,只有对Name data进行注入,利用<script>标签大小写进行绕过,但你会发现Name data length=10 受到限制

篡改数据,绕过length限制

构造payload
POST Name data
txtName=%3CScript%3Ealert%281111%29%3C%2FscriPt%3E&mtxMessage=admin&btnSign=Sign+Guestbook
Name data的绕过

服务端数据库文件已存入攻击者的恶意代码

在这里也可以使用<img>标签进行绕过:<img src=# onerror=alert("_XSS_")>
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();
}
?>
代码审计之后,发现high级别的Name data存在另外一种的Protect,利用preg_replace()函数进行匹配“< s r i p t”等字符,将其置为空,此时Name data里面的<script>标签是不能使用的,不管是大小进行区分写都不可以进行绕过
所以,就需要利用其它标签进行XSS攻击,此处可以利用 medium 级别 中提到的<img>标签进行绕过preg_replace()函数的Protect
构造payload
POST Name data
txtName=%3Cimg+src%3D%23+onerror%3Dalert%28%22_XSS_%22%29%3E&mtxMessage=Hello+admin&btnSign=Sign+Guestbook
<img>标签成功绕过preg_replace()

服务端数据库文件已存入攻击者的恶意代码

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();
?>
impossible 级别的Protect不能被绕过,由于Name data和Message data都受到htmlspecialchars()函数的保护作用
htmlspecialchars() 函数把预定义的字符转换为 HTML 实体。
预定义的字符是: & (和号)成为 &
" (双引号)成为 "
' (单引号)成为 '
< (小于)成为 <
> (大于)成为 > 它的语法如下:
htmlspecialchars(string,flags,character-set,double_encode)
其中第二个参数flags需要重要注意,很多开发者就是因为没有注意到这个参数导致使用htmlspecialchars()函数过滤XSS时被绕过。因为flags参数对于引号的编码如下: 可用的引号类型: ENT_COMPAT - 默认。仅编码双引号。
ENT_QUOTES - 编码双引号和单引号。
ENT_NOQUOTES - 不编码任何引号。
默认是只编码双引号的
因为输入的所有标签都被转义,所以此处不存在XSS攻击,但是要注意flags属性,使用不当过滤XSS时就会被绕过
XSS Stored 测试的更多相关文章
- XSS Reflected 测试
由于最近在做XSS方面的测试,于是找到了DVWA平台进行实验测试,通过这三篇文章让大家了解XSS方面的大概内容,这三篇文章只是把你领进XSS的大门,要想真正深入的学习XSS,你还需要去学习很多东西来提 ...
- 如何在SAE搭建属于自己的黑盒xss安全测试平台
Author:雪碧 http://weibo.com/520613815 此篇文章技术含量不高,大牛不喜勿喷,Thx!写这篇文章主要是为了各位小伙伴在SAE搭建XSSING平台的时候少走点弯路(同志们 ...
- DVWA XSS (Stored) 通关教程
Stored Cross Site Scripting 存储型XSS,持久化,代码是存储在服务器中的,如在个人信息或发表文章等地方,加入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,用户 ...
- xss跨站脚本测试
测试的时候会涉及到xss测试,下面简要整理下xss的知识 xss跨站脚本特点就是能注入恶意的HTML/JS代码到用户浏览器,劫持用户会话 常用alert来验证网站存在漏洞 如果确认存在漏洞,会随着注入 ...
- XSS DOM 测试
dvwa DOM XSS DOM Based XSS:是基于DOM文档对象模型的操作,通过前端脚本修改页面的DOM节点形成的XSS,该操作不与服务器端进行交互,而且代码是可见的,从前端获取到DOM中的 ...
- OWASP出品:Xenotix XSS漏洞测试框架及简单使用
OWASP Xenotix XSS Exploit Framework是一个高效的跨站脚本漏洞(XSS)检测和攻击测试框架.它通过特有的三大浏览器引擎(包括Trident, WebKit和Gecko) ...
- XSS攻击测试代码
'><script>alert(document.cookie)</script>='><script>alert(document.cookie)&l ...
- 简单的XSS手动测试
好吧,我也是初学者,写这个随笔,主要也是为了记录,自学到的点. 简单的案例,见http://www.cnblogs.com/trhimily/p/3898915.html 总结一下主要的点: 1. u ...
- 如何发起、防御和测试XSS攻击,我们用DVWA来学习(上)
XSS 全称Cross Site Scripting 即‘跨站脚本攻击’. 从其中文释义我们能直观的知道,这是一种对网站的攻击方式. 其原理在于,使用一切可能手段,将可执行脚本(scripting)植 ...
随机推荐
- 印象笔记 MAC安装使用旧版本
印象笔记终于支持markdown了,赞! 第一个beta版用起来非常不错.提示更新安装新版本后保存markdown一直提示 "Note content is invalid.",无 ...
- Linux Kernel C语言编程范式
介绍 不同的编程语言具有不同的抽象原语(如下),有的原语抽象层次低,有的原语抽象层次高.其中函数式.DSL是这几年十分热门的编程语言概念. 过程式抽象原语:变量 对象式抽象原语:对象 函数式抽象原语: ...
- Idea下的springboot mysql8.0等报错解决随笔
cannot load jdbc class path:mysql8.0装载失败,可能原因,驱动名称错误,连接字符串中需要加入时区UTC,否则8.0一定会报错无法连接,关闭SSL 在applicati ...
- docker安装,无法正常启动
报错信息: Job for docker.service failed because the control process exited with error code. See "sy ...
- 【自动化测试】搭建一个简单从Excel读取用例内容并输出结果的脚本
# -*- coding:utf-8 -*- from selenium import webdriver import xlrd import xlwt from xlutils.copy impo ...
- 2.postman安装及使用
一.postman说明 postman是研发和测试进行接口调试的工具.可以用来很方便的模拟get或者post或者其他方式的请求来调试接口. 二.postman安装 ①作为谷歌浏览器插件安装 参考资料: ...
- Eclipse自动补全调教
方法来自http://www.cnblogs.com/sunjie21/archive/2012/06/28/2567463.html 调教后可以做到: 1. sout + Tab 输出System. ...
- mysql_Navicat数据库破解
Navicat Premium 12.1.16.0安装与激活 Navicat Premium 12是一套数据库开发管理工具,支持连接 MySQL.Oracle等多种数据库,可以快速轻松地创建.管理和维 ...
- django+javascrpt+python实现私有云盘代码
丁丁:由于篇幅有限,这里暂时只展示python后端代码,前端js代码后面上传,有需要的也可以留言私信我. 1.view.py 使用用户.部门.公司等相关账号的创建,已经个人,部门账号的冻结,删除,相关 ...
- .NET Core的依赖注入[1]: 控制反转
写在前面:我之前写过一系列关于.NET Core依赖注入的文章,由于.NET Core依赖注入框架的实现原理发生了很大的改变,加上我对包括IoC和DI这些理论层面的东西又有了一些新的理解,所以我在此基 ...