跨站请求伪造防御(CSRF)

2021-09-08  本文已影响0人  菜鸡前端

CSRF夸站点请求伪造(Cross Site Request Forgery),跟XSS攻击一样存在巨大的危害性。攻击者通过伪造身份发送恶意请求达到期望的目标。

1. 攻击原理

1.1 场景1

(1)用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
(2) 用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功;
(3) 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
(4) 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
(5) 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。

1.2 场景2

某一天,某个陌生人给你发一个链接,点开这个页面的链接后,会自动发送 POST 请求,然后跳转到原始首页:

<body>
    <iframe name="hiddenIframe"  style="display:none"></iframe>
  <form action="https://xxxx.com/deal"
        id="form"
        method="post"
        style="visibility:hidden"
        target="hiddenIframe">
    <input type="text" name="giftId" value="ab231">
  </form>
<script>
    document.getElementById('form').submit();
    location.href = "http://xxxx.com";
</script>
</body>

2. 防御手段

目前防御 CSRF 攻击主要有5种策略:

总体来说,使用“在HTTP 头中自定义属性并验证”是更为安全的做法,因为它还可以防止部分的 XSS 攻击,比如通过 img.src 去发起攻击。

2.1 验证 HTTP Referer 字段

根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。对于某些浏览器,目前已经有一些方法可以篡改 Referer 值。

2.2 在请求中添加 CSRF Token

CSRF 攻击之所以能够成功,是因为用户验证信息都是存在于 cookie 中,这个防御失效了,要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。

在一个网站中,可以接受请求的地方非常多,要对于每一个请求都加上 token 是很麻烦的,并且很容易漏掉,通常使用的方法就是在每次页面加载时,使用 javascript 遍历整个 dom 树,对于 dom 中所有的 a 和 form 标签后加入 token。这样可以解决大部分的请求,但是对于在页面加载之后动态生成的 html 代码,这种方法就没有作用,还需要程序员在编码时手动添加 token。

2.3 双重提交 Cookie

在提交前先使用JS读取用于验证的cookie值加入到提交字段。这样就形成了双提交(验证字段有两份,一份在cookie中,一份在POST或URL中)。单纯的csrf只能让请求中带有cookie,但是并不能读取cookie加入到POST或URL中。服务端从 URL/POST 取出该值,并和 cookie 字段进行验证。

2.4 请求头自定义属性验证

这种方法也是使用 token 并进行验证,和上一种方法不同的是,这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。

然而这种方法的局限性非常大。XMLHttpRequest 请求通常用于 Ajax 方法中对于页面局部的异步刷新,并非所有的请求都适合用这个类来发起,它不适用于非 Ajax 请求。

2.5 基于用户交互的 CSRF 防御

一些很重要的操作,比如资金转移操作,可以让用户参与校验,比如:

虽然这些是非常强大的 CSRF 防御,但它可以对用户体验产生重大影响。因此,它们通常仅用于安全关键操作,例如密码更改、汇款等。

3. CSRF漏洞检测

检测CSRF漏洞是一项比较繁琐的工作,最简单的方法就是抓取一个正常请求的数据包,去掉Referer字段后再重新提交,如果该提交还有效,那么基本上可以确定存在CSRF漏洞。

随着对CSRF漏洞研究的不断深入,不断涌现出一些专门针对CSRF漏洞进行检测的工具,如CSRFTester,CSRF Request Builder等。

以CSRFTester工具为例,CSRF漏洞检测工具的测试原理如下:使用CSRFTester进行测试时,首先需要抓取我们在浏览器中访问过的所有链接以及所有的表单等信息,然后通过在CSRFTester中修改相应的表单等信息,重新提交,这相当于一次伪造客户端请求。如果修改后的测试请求成功被网站服务器接受,则说明存在CSRF漏洞,当然此款工具也可以被用来进行CSRF攻击。

4. 使用框架集成

通常情况下,框架都集成了这个功能,尽量开启。

上一篇下一篇

猜你喜欢

热点阅读