浅析 Web 安全之 XSS 与 CSRF

一个小插曲:写了两个多小时的时候网页崩溃了,当时心态都崩了,又重新写了一遍。

1 前言

整理面经的时候好多前端的面经里面都有和 web 安全相关的内容,所以就详细了解了一下,但是这几次面试其实都没有问到,今天晚上也问了面试官虽然 XSS 和 CSRF 和前端安全相关,但是其实前端能做的并不多,最多只是对一些特殊字符进行转义,但是其实主要的工作还是后端来做,所以前端到底能做什么来预防这些东西。面试官是这么跟我说的,他说前端只是一个大门,并不能挡住所有东西,但是还是要对这些东西有所了解。
所以呢,在安全方面,前端能做的东西真的不多,但是要有这个意识,如果你连防御的意识都没有的话那么写的程序肯定是有漏洞的,话不多说,接下来开始介绍 XSS 和 CSRF。

2 XSS 攻击

XSS 即跨站脚本攻击,英文名称 Cross Site Scripting。之所以不叫 CSS 因为 CSS 已经被层叠样式表用了。

2.1 攻击原理

2.1.1 反射型

反射型攻击主要是用户输入了一段可执行的代码,然后后台没有对输入进行处理,如

<-- 反射型 XSS -->
<form action="" method="get">
    <input type="text" name="xss"/>
    <input type="submit" value="test"/>
</form>

假设这是一个查询框,用户输入了下面一段代码

 <script> alert(1) </script>

然后后台没有对数据进行任何处理,重定向到查询结果界面以后显示查询不到任何结果并且显示了警告 1;查看网页结构会发现结构变成如下这样

<form action="" method="get">
    <input type="text" name="xss"/>
    <script> alert(1) </script>
    <input type="submit" value="test"/>
</form>

这段用户输入的代码变成了网页中的元素。
假设你点击了一段陌生的链接
localhost:8080?xss=<script>alert(1)</script>
其实这段代码和上面的操作是一样的,只不过这是别人发给你的链接,需要你来点击,当然这种链接很多人可能会有警惕,但是可以通过转换变成一个短网址
http://crogps.cn/j8Ca1R
这样还能看出来吗,于是你点击了以后,就显示了一个警告。

可能显示警告造不成太大的危害,如果里面是将你的 Cookie 发送攻击者的网站呢,或者链接了攻击者的 js,改变了页面的逻辑等等,那么危害就大了。但是这种攻击方式并不会保存到数据库中,而且需要用户点击,所以危害相对小一些。

2.1.2 存储型

存储型攻击攻击原理和反射型类似,不过存储型攻击输入的代码会被保存到数据库中,所有的用户都可以看到这些信息。

比如在微博的评论里面加入这么一条评论

 <a href = "www.attack.com" >点击这里有钱拿</a>

如果后端没有做任何处理,将这条信息保存到数据库中。那么所有人都可以看到这条评论。并且显示的是一个链接的形式,如果用户好奇点击了,就会被引导到攻击者的网站,进行后续的操作。
点击的转化率不是太高,所以如果攻击者写的是这样的一条

<img src = "abc" onerror="alert(1)"/>

因为该文件不存在,所以就会触发 onerror 事件。那么当用户加载评论的时候就会运行攻击代码,造成危害。

由于存储型攻击是将攻击代码存储到数据库中,并且可以扩散到所有人,所以危害特别大。

2.2 攻击方式

  • 富文本攻击
  • script 攻击
  • html 内容
  • html 属性

这些攻击方式的话和上面基本类似,除了富文本的攻击。富文本就是类似邮件和写博客时候的编辑框,可以设置字体颜色等,因为它本身用的就是 html 属性,所以它允许用户嵌入代码,如果这段代码是发给管理者的,就可能获取管理者的数据,造成危害,因此富文本的防御和其他的有所区别。

2.3 防御方式

2.3.1 浏览器自带防御机制

目前大多数浏览器都有自带的防御 XSS 攻击的机制,而且默认是开启的,但是这种防御机制只能防御一些基本的反射型的 XSS 攻击,功能十分有限。

2.3.2 对特殊字符进行转义

这也是前端唯一可以做的,当然也可以后端来做,即将特殊字符进行转义,因此浏览器解析的时候就不会将它渲染成元素,而是渲染成文字,具体操作如下

var escapeHtml = function(str){
    if (!str) return '';
    str = str.replace(/</g,'&lt;');
    str = str.replace(/>/g,'&gt;');
    str = str.replace(/"/g,'&quto;');
    str = str.replace(/'/g,'&#39;');
    str = str.replace(/&/g,'&amp;');
    return str
};
2.3.3 设置白名单或黑名单

这个主要是针对富文本进行处理的,因为富文本允许用户输入代码。

主要思路就是将字符串解析成 dom 树,然后对 dom 树做黑名单或白名单处理。

黑名单即去掉指定的标签和属性,如

// 黑名单
var xssFilter = function(html){
    if(!html) return '';
    // 过滤 script 标签
    html = html.replace(/<\s*\/?script\s*>/g,'');
    // 过滤 a 标签如 <a href="javascript:alert(1)">
    html = html.replace(/javascript:[^'"]*/g,'');
    // 过滤 img 标签的 onerror 事件如 <img src="abc" onerror="alert(1)">
    html = html.replace(/onerror\s*=\s*['"]?[^'"]*['"]?/g,'');
    return html;
}

由于能触发的标签属性太多,不可能把所有情况都考虑到,所以可以考虑做白名单

白名单即只保留想要的属性和标签,实现方式如下

// 假设 htmlList 是解析完以后的 dom 节点
 var xssFilter = function(htmlList){
    if(!htmlList) return '';
    // 假设只允许 img 标签,并且只允许它带有 src 属性
    var whiteList = {
        'img':['src'],       
    };
    htmlList.each(function(elem,index){
    // 如果标签不在白名单中
        if(!whiteList[elem.name]){
        // 删除该标签
            htmlList.splice(index,1);
            return;
        }
        for(var attr in elem.attributes){
        // 如果标签的属性不在白名单中
            if(whiteList[elem.name].indexOf(attr)===-1){
            // 删除该属性
                elem.setAttribute(attr,null);
            }
        }
    });
    return htmList;
};
2.3.4 CSP

CSP 即内容安全策略,英文全称 Content Security Policy,即用于指定哪些内容可以执行,是最近提出的一种解决方案。

2.3.5 Http-Only

后端设置 Http-Only Header,使得前端无法读取及修改 cookie,无法获取用户身份。

3 CSRF 攻击

CSRF 即 跨站请求伪造,英文全称 Cross Site Request Forgery,即攻击者在用户不知情的情况下利用用户的身份进行转账,消费,发帖等

3.1 攻击原理

  • 用户登录 A 网站
  • A 网站验证用户身份
  • 登录 B 网站,B 网站向 A 网站发起请求(带 A 网站的身份)

例如你登录了银行网站 A,银行网站确认了你的身份,这时你又登录了攻击者的网站 B,攻击者的网站里面有这么一段代码

<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>

这段代码向银行网站的转账接口发起了一次请求,并且携带了用户的身份,假设银行网站并没有做相应的防御措施,则你就会向攻击者的账户转账 1000,刷新一次转 1000。因为每刷新一次相当于重新发起一次请求。

若还是不理解的话可以参考这篇文章 浅谈CSRF攻击方式

3.2 防御方式

CSRF 的防御主要放在攻击原理的第三步,即如何让第三方网站发起请求时无法携带用户身份,所以通过下面几种方式

3.2.1 验证码

后台生成验证码保存在服务器中,并且返回到前台。待用户提交的时候校验。若 B 网站没有经过 A 网站的前台则无法获取这个验证码,因此不能通过后台的验证,但是如果干什么都要验证码的话会极大的影响用户体验。

3.2.2 token

token 即后台按照一定规则生成的随机字符串,一个放在后台,一个放在 cookie 中,一个放在表单中(如果是 ajax 请求一般放到 meta 中,用户发起请求时从 meta 中获取)。然后提交数据时对比这三个的值是否一致,因为 B 网站没有经过 A 网站的前端,获取不到前两个值,所以无法通过验证。

3.2.3 referer

这个单词在 header 中就是错的,就一直继承了下来,应该为 referrer 。
这个字段表明了用户是在哪个网站发起的请求,即来源。
后台可以设置只通过来自本网站的请求。

4 总结及面试怎么讲

如果你没看过上面的内容的话,就算按照这里的内容说出来,面试官稍微问一下就露馅了,所以建议最好看完上面内容再来看这部分。括号中的内容代表可以不说诱导面试官来问,当然你也也可以直接说。

问:对 web 安全有所了解吗或对 XSS、CSRF 有所了解吗

  • 和前端安全相关的主要有 XSS(跨站脚本攻击)攻击及 CSRF(跨站请求伪造)
  • XSS 的攻击方式主要分为反射型及存储型,(反射型攻击主要是攻击者写了一段代码放在链接中,诱导用户去点击触发。存储型攻击主要是攻击者将攻击代码写到如评论之类的公共平台中,当其他用户刷到这些攻击代码时触发这些代码,影响较大。)
  • 主要的防御方式有 (1) 浏览器自带的防御机制 (2) 前台或后台对特殊字符进行转义 (3) 对于富文本来说可以设置黑名单或白名单(就是先将字符串转换成 dom 节点,然后黑名单就是将要屏蔽的标签属性列出来,屏蔽这些标签属性,白名单正好相反,将允许的标签属性列出来,屏蔽其他标签和属性) (4) CSP 内容安全策略 (用于指定哪些内容可以执行)

  • CSRF 攻击的主要原理是用户登录网站 A,网站 A 验证用户身份,生成用户信息,然后登录攻击者的网站 B,然后 B 网站向 A 网站发起请求但是这个请求携带了 A 网站的身份,所以就会在用户不知情的情况下进行一些损害用户利益的操作

  • 主要的防御方式有 (1) 验证码(后台生成验证码,第三方网站由于没有访问目标网站前端,获取不到验证码,无法通过校验)(2) token (后台生成随机字符创,放在 cookie 和表单中,如果是 ajax 请求可以将 token 放在 meta 中,然后攻击者发起请求时也获取不到这些值,无法通过校验) (3) 可以通过 referer (即限制第三方请求的来源网站)

微信

我是啦啦啦,期待与大家共同进步,有什么问题可以共同讨论

猜你喜欢

转载自blog.csdn.net/zhang6223284/article/details/81322736