文章目录
OWASP Top 10
XSS
一、概述
XSS被称为跨站脚本攻击(Cross Site Scripting),本来应该缩写为CSS,但是由于和CSS脚本语言重名,所以更名为XSS。XSS主要基于JavaScript完成恶意的攻击行为。由于JS可以非常灵活的操作html、css和浏览器,这使得XSS攻击的“想象”"空间特别大。
XSS通过将精心构造的JS代码代码注入到网页中,并由浏览器解释运行这段JS代码,以达到恶意攻击的效果。当用户访问被XSS脚本注入的网页,XSS脚本就会被提取出来,用户浏览器就会解析这段XSS代码,也就是说用户被攻击了。用户最简单的动作就是使用浏览器上网,并且浏览器中有javascript解释器,可以解析javascript;然而浏览器不会判断代码是否恶意,也就是说,XSS的对象是用户和浏览器。
基本攻击模型:
二、XSS危害
微博、留言板、聊天室等收集用户输入的地方,都有可能被注入XSS代码,都存在遭受XSS的风险,只要没有对用户的输入进行严格过滤,就会被XSS。
XSS利用JS代码实现攻击,有很多中攻击方法:
- 盗取各种用户账号;
- 窃取用户Cookie资料,冒充用户身份进入网站;
- 劫持用户会话,执行任意操作;
- 刷流量、执行弹窗广告;
- 传播蠕虫病毒。
三、XSS相关
- EXP
漏洞的完整利用工具。 - POC
XSS漏洞的验证,我们可以用一段简单的代码,验证和检测漏洞的存在,这样的代码叫做PoC(Proof of Concept) 。 - shellcode
是一段用于利用软件漏洞而执行的代码。 - payload
攻击载荷;如sqlmap中的payload即攻击代码的模板、msf中的shellcode类似,功能是建立与目标的连接。
四、使用PoC代码简单验证XSS漏洞
PoC代码:
<script>alert(/xss/)</script> # 常用
<script>confirm('xss')</script>
<script>prompt('xss')</script>
测试网页:
index.php
<html>
<meta charset='utf-8'>
<head>
<title>XSS--测试</title>
</head>
<body>
<h1>XSS--测试</h1>
<form method="post" action="xss.php">
<textarea name="xsscode" rows="10" cols="50"></textarea>
<br />
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>
xss.php
<meta charset='utf-8'>
<?php
if(isset($_REQUEST['submit'])){
echo $_REQUEST['xsscode'];
echo "<a href='./index.php'>返回</a>";
}else{
echo "<a href='./index.php'>返回</a>";
}
?>
测试:
- 在文本域输入内容,提交到xss.php页面
- 提交图片标签代码,提交后并没有显示源代码内容,而是通过浏览器自动解析为图片标签
- 我们提交这样PoC代码
<script>alert(/xss/)</script>
,点击提交按钮,就能看到弹窗操作
我们发现,提交的代码<script>alert(/xss/)</script>
,被当作字符串输出在HTML页面中,浏览器会根据<script>
标签解析为JS语句,并会执行它,执行弹窗操作。也就是说,可以执行其他JS代码,因此我们验证了XSS漏洞的存在性。
五、XSS分类
XSS漏洞大概可以分为三个类型:反射型XSS、存储型XSS、DOM型XSS。
1. 反射型XSS
反射型XSS是非持久性、参数型的跨站脚本。
反射型XSS的JS代码在Web应用的参数(变量) 中,我们上面的XSS验证就是反射型;还有比如在搜索框中就存在反射型XSS:在搜索框中,提交PoC代码,点击搜索,即可触发反射型XSS。
2. 存储型XSS
存储型XSS是持久性跨站脚本。
持久性体现在XSS代码不是在某个参数(变量)中,而是写进数据库或文件等可以永久保存数据的介质中。
存储型XSS通常发生在留言板等地方,我们在留言板位置留言,将恶意代码写进数据库中。此时,我们只完成了第一步,将恶意代码写入数据库。因为XSS使用的JS代码,JS代码的运行环境是浏览器,所以需要浏览器从服务器载入恶意的XSS代码,才能真正触发XSS。
3. DOM型XSS
OWASP关于DOM型XSS的定义是基于DOM的XSS是一种XSS攻击,其中攻击的payload由于修改受害者浏览器页面的DOM树而执行的。其特殊的地方就是payload在浏览器本地修改DOM树而执行,并不会传到服务器上,这也就使得DOM XSS比较难以检测。
示例:
<html>
<head>
<title>DOM-XSS-Test</title>
</head>
<body>
<script>
var a = document.URL; // 获取url
a = unescape(a); // 对字符串进行解码
document.write(a.substring(a.indexOf("hello=")+6,a.length));
// 从url中截取首次出现变量hello=后面的内容(6即hello=的长度)
</script>
</body>
</html>
测试:
提交PoC代码:成功弹窗
我们以锚点的方式(#)提交PoC。PoC并不会发送的服务器,但是已经触发了XSS。
查看当前页面的源代码如下查看提交参数后的HTML页面(DOM树):
六、XSS的构造
1. 利用<>构造HTML或JS标签
2. 伪协议
也可以使用javascript:伪协议的方式构造XSS。
提交参数<a href="javascript:alert(/xss/)">touch me!</a>
,然后点击超链接,即可触发XSS;
也可以使用img标签的伪协议,但是这种方法在 IE6 下测试成功。<img src="javascript:alert('xss')">
。
3. 事件驱动
在网页中会发生很多事件(比如鼠标移动、键盘输入等),JS可以对这些事件进行响应。所以我们可以通过事件触发JS函数,触发XSS。
事件种类:
windows事件:对windows对象触发的事件
Form事件:HTML表单内的动作触发事件
Keyboard事件:键盘按键
Mouse事件:由鼠标或类似用户动作触发的事件
Media事件:由多媒体触发的事件
示例:
<img src='./haha.jpg' onmouseover='alert(/xss/)'>
,引入一个图片,然后鼠标悬停在图片上的时候,会触发XSS代码。
- 单行文本框的键盘点击事件,
<input type: ="text" onkeydown="alert(/xss/)">
,当点击键盘任意一个按键的时触发。
3. 构造错误
<img src='#' onerror='alert(/xss/)'>
,我们将src参数故意写错,提交后就会触发XSS代码。
4. 利用CSS跨站
可以利用CSS脚本触发XSS。但是这种方法比较古老,基本上不适合现在主流的浏览器,IE6下测试可以成功。
如:行内样式,<div style="background- image:url(javascript:alert(/xss/))">
七、XSS的变形
我们可以构造的XSS代码进行各种变形,绕过XSS过滤器的检测。
1. 大小写转换
由于html是不区分大小写的,可以将payload进行大小写转化。
如:
<Img sRc='#' Onerror="alert(/xss/)"/>
<a hREf="jaVaScript:alert(/xss/ )">click me</A>
2. 引号的使用
HTML语言中对弓号的使用不敏感,但是某些过滤函数很严格。
如:下面的标签都可以触发XSS
<img src="#" onerror="alert(/xss/)" />
,全使用双引号;
<img src='#' onerror='alert(/xss/)' />
,全使用单引号;
<img src=# onerror=alert(/xss/) />
,不适用引号。
3. 利用左斜线代替空格
<img src='#'/onerror='alert(/xss/)' />
4. 添加Tab或回车符
<img src='#' onerror =
'alert(/xss/)' />
<a href="
j a
v a
s c
r i
p t:
alert(/xss/)">touch me!</a>
5. 对标签属性值进行转码
可以对标签属性值进行转码,用来绕过过滤。
如:
字母 ASCII码 十进制编码 十六进制编码
a 97 a a
e 101 e e
经过简单编码之后的样子:
<a href="javascript:alert(/xss/ )">click me!</a>
另外,我们可以将以下字符插入到任意位置
Tab 	
换行 

回车 
可以将以下控制字符插入到头部位置
SOH(标题开始(start of header)) 
STX(文本开始(start of text)) 
ETX(文本结尾(end of text)) 
经过编码后的样子。
<A hREf="javas	c r ipt:alert(/xss/ )">click me!</a>
6. 拆分跨站
<script>a='alert'</script> // 将alter赋值给变量a
<script>a=a+'(/xss/)'</script> // a拼接/xss/
<script>eval(a)</script> // 可执行函数eval()完成执行
7. 双写绕过
如果我们写的某些标签疑似被过滤掉了,可以使用双写尝试绕过
<script>
<scr<script>ipt>
XSS练习平台
XSS quiz:http://xss-quiz.int21h.jp/
google浏览器可能存在xss安全机制,无法完成练习,需要配置Chrome --args --disable-xss-auditor
,新建快捷方式在google启动目录后面添加这个配置即可。
1. 闭合标签
以xss-quiz第一关为例。
发现b标签:
闭合b标签:"</b><script>alert(document.domain);</script>
成功过关:
2. 闭合">
以xss-quiz第二关为例。
原本的value=“值”,我们需要闭合后面的 ">
3. 在选择列表中注入
以xss-quiz第三关为例。
当我们直接search:<script>alert(document.domain);</script>
,发现它将我们的输入直接进行字符串转义,使js失效。
选择列表中注入XSS:
使用bp抓包:
注入代码:<script>alert(document.domain);</script>
打开链接,成功弹出,成功过关:
4. hidden域中插入svg标签
SVG意为可缩放矢量图形(Scalable Vector Graphics)。
SVG使用XML格式定义图像。SVG文件可通过以下标签嵌入HTML文档: <embed>、<object>、<iframe>
;也可以使用svg标签插入。
以xss-quiz第四关为例。
bp抓包发现p3(隐藏域),闭合后使用svg标签:
5. 限制输入长度中的XSS
以xss-quiz第五关为例。
当我们在输入框输入到一定长度时就不让输入了,查看表单元素,最大长度为15:
计算js代码长度,使用python的len函数:
修改maxlength参数,闭合value后面的">,即可实现XSS。
八、XSS的防御
1. 使用XSS Filter
XSS Filter的作用是过滤用户(客户端)提交的有害信息,从而达到防范XSS攻击的效果。
1.1 PHP相关函数
- htmlspecialchars(string,flags,character-set,double_encode)
把预定义的字符 “<” (小于)和 “>” (大于)转换为 HTML 实体
参数
string:规定要转换的字符串。
flags:规定如何处理引号、无效的编码以及使用哪种文档类型。
character-set:一个规定了要使用的字符集的字符串,UTF-8 - 默认。
double_encode:布尔值,TRUE - 默认:将对每个实体进行转换。
示例:
<?php
$str = "<script>alert(/XSS/);</script>";
echo $str;
$str2 = htmlspecialchars($str);
echo $str2;
?>
运行结果,先弹窗再输出:
2. htmlentities(string,flags,character-set,double_encode)
htmlentities() 函数把字符转换为 HTML 实体。
示例:
<?php
$str = "<script>alert(/XSS/);</script>";
$str2 = htmlentities($str);
echo $str2;
?>
运行结果查看源码:
- strip_tags(string,allow)
strip_tags() 函数剥去字符串中的 HTML、XML 以及 PHP 的标签。
注释:该函数始终会剥离 HTML 注释。这点无法通过 allow 参数改变;该函数是二进制安全的。
示例:
<?php
$str = "<script>alert(/XSS/);</script>";
$str2 = strip_tags($str);
echo $str2;
?>
运行结果:
1.2 自定义Filter
网上搜索拿来直接使用的一些方法代码。
- 输入过滤
"永远不要相信用户的输入"是网站开发的基本常识,对于用户输入一定要过滤,过滤,再过滤。 - 输入验证
简单的说,输入验证就是对用户提交的信息进行有效验证,仅接受指定长度范围内的,采用适当格式的内容提交,阻止或者忽略除此之外的其他任何数据。 - 输入是否仅包含合法的字符
输入字符串是否超过最大长度限制;输入如果为数字,数字是否在指定的范围;输入是否符合特殊的格式要求,如E-mail 地址、IP地址等。 - 数据消毒
过滤和净化掉有害的输入。 - 输出编码
HTML编码主要是用对应的HTML实体代替字符。 - 黑白名单
不管是采用输入过滤还是输出编码,都是针对数据信息进行黑|白名单式的过滤。
1.3 绕过XSS-Filter的方法
kali自带的XSS字典,CTF比赛中常用。
字典目录:/usr/share/wordlists/wfuzz/Injections/XSS.txt
使用bp自动化工具,使用bp的Intruder模块将shellcode处定义为变量,导入字典 start attack 即可。
2. 防御DOM-XSS
避免客户端文档重写、重定向或其他敏感操作。
九、XSS相关工具
1. xsser
- 概述
xsser (Cross site “scripter”)是一款自动化渗透测试XSS漏洞的安全工具,专门用来检测和利用不同应用程序中存在的xss漏洞。它包含了一些选项用来尝试绕过特定的过滤器,并且具有特殊的代码注入技术。
- 工具原理
不断拼接payload
- xsser启动
- 命令行启动:xsser
- 图形化界面启动:xsser --gtk
2. XSStrike
- 概述
XSStrike是一款检测XSS的高级检测工具。它集成了payload生成器、 爬虫和模糊引擎功能。XSStrike不是像其他工具那样注入有效负载并检查其工作,而是通过多个解析器分析响应,然后通过与模糊引擎集成的上下文分析来保证有效负载。除此之外,XSStrike还具有爬行、模糊测试、参数发现、WAF检测功能、扫描DOM XSS漏洞。
- 安装
下载地址:https://github.com/s0md3v/XSStrike;
XSStrike只可以运行在python 3.6以上版本。
安装pip:apt-get install python3-pip
安装xsstrike:pip3 install -r requirements.txt
加执行权限:chmod +X xsstrike.py
查看帮助文档:
- 示例
测试代码:
<html>
<?php
$n = $_GET["n"];
echo $n;
?>
</html>
会为我们生成很多payload:
选择其中一个进行测试: