目录
XSS 简介
XSS(Cross Site Script),全称跨站脚本攻击,为了与 CSS(Cascading Style Sheet) 有所区别,所以在安全领域称为 XSS。
XSS 攻击,通常指黑客通过 HTML 注入 篡改网页,插入恶意脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击行为。
详细介绍可以看之前的文章:【Web安全】跨站脚本攻击XSS_RexHarrr的博客-CSDN博客
DOM—based XSS漏洞的产生
DOM—based XSS漏洞是基于文档对象模型Document Objeet Model,DOM)的一种漏洞。DOM是一个与平台、编程语言无关的接口,它允许程序或脚本动态地访问和更新文档内容、结构和样式,处理后的结果能够成为显示页面的一部分。DOM中有很多对象,其中一些是用户可以操纵的,如uRI,location,refelTer等。客户端的脚本程序可以通过DOM动态地检查和修改页面内容,它不依赖于提交数据到服务器端,而从客户端获得DOM中的数据在本地执行,如果DOM中的数据没有经过严格确认,就会产生DOM—based XSS漏洞。
可能触发DOM型XSS的属性:document.referer属性
window.name属性
location属性
innerHTML属性
documen.write属性
1、级别:Low
看一下源码:
<?php
# No protections, anything goes
?>
Nothing~转战网页源代码
indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
document.location.href 当前页面完整 URL
substring(start,stop)方法用于提取字符串中介于两个指定下标之间的字符。
decodeURI() 函数可对 encodeURI() 函数编码过的 URI 进行解码。
document.write是JavaScript中对document.open所开启的文档流(document stream操作的API方法,它能够直接在文档流中写入字符串,一旦文档流已经关闭,那document.write就会重新利用document.open打开新的文档流并写入,此时原来的文档流会被清空,已渲染好的页面就会被清除,浏览器将重新构建DOM并渲染新的页面
这段代码的意思就是说如果存在default,则取出 default 的值赋值给变量lang,然后写入<option value='"lang"'>"decodeURL(lang)</option>,也就是说我们可以注入一些 JS 代码进去,然后这部分会被包含到 lang 变量中,最终回显到页面上。
构造注入payload:?default=<script>alert(document.cookie)</script>
2、级别:Medium
源码:
<?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;
}
}
?>
array_key_exists() 函数检查某个数组中是否存在指定的键名,如果键名存在返回 true,键名不存在则返回 false。
stripos(string,find,start) 函数查找字符串在另一字符串中第一次出现的位置(不区分大小写)。
header() 函数向客户端发送原始的 HTTP 报头。
“script” 标签被过滤了,当函数匹配到 <script 字符串的时候就会将URL后面的参数修正为 ?default=English,我们不能直接注入 JS 代码了。
采用图片插入语句法:
HTML 的 < img > 标签定义 HTML 页面中的图像,该标签支持 onerror 事件,在装载文档或图像的过程中如果发生了错误就会触发。使用这些内容构造出 payload 如下,因为我们没有图片可供载入,因此会出错从而触发 onerror 事件输出 cookie。
构造payload:
?default=English</option></select><img src = 1 onerror = alert(document.cookie)>
(这里的标签 </option></select> 是根据页面源码写的)
注入后的网页代码
3、级别:High
源码:
<?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;
}
}
?>
这里用switch:case来给default赋值,相当于设置了白名单,只允许传 default值为English
、French
、German
、Spanish
其中一个。
可以在注入的 payload 中加入注释符 “#”,注释后边的内容不会发送到服务端,但是会被前端代码所执行。
payload:
?default=English #<script>alert(document.cookie)</script>
4、级别:Impossible
源码:
<?php
# Don't need to do anything, protection handled on the client side
?>
意思是不需要做任何事,保护在客户端处理。
看下网页源代码:
这里的语句变了,并没有对我们输入的内容进行URL解码,所以我们输入的任何内容都是经过URL编码,然后直接赋值。因此不存在XSS漏洞。