CSRF原理与防御措施

版权声明:欢迎转载,转载请标明来源 https://blog.csdn.net/weixin_41973131/article/details/85059100

欢迎关注驿外残香 | HC的博客

一.CSRF概念

CSRF跨站点请求伪造(Cross—Site Request Forgery)

相当于:针对一个特定的正常网站,攻击者利用URL或者Javascript伪造了一个请求,当用户点击攻击者设置的陷阱时(例如未知的第三方链接)即会发送该伪造的请求。若此时用户刚好访问过该正常网站并且此时用户浏览器与服务器的Session尚未过期,浏览器的 cookie 之中含有该用户的认证信息。此时该请求将会认证通过,服务器将会认为这是用户本人发出的合法请求,此时请求生效。CSRF攻击成功。

即攻击者盗用了你的身份,以你的名义发送了恶意请求,而对于服务器来说该请求是合法请求。

由此看来,CSRF攻击成功有两个必须的条件:

1.被伪造身份的目标曾在该浏览器上访问过CSRF站点,且cookies尚未过期。

2.目标被引诱在该浏览器上访问了攻击者放置恶意代码的域名或网站。

受攻击的对象:

由于攻击者是借助目标的cookie来欺骗服务器,但是攻击者并不能够拿到cookie。另外,对于服务器返回的结果,由于浏览器同源策略的限制,攻击者也无法进行解析。

因此攻击者所能做的只有给服务器发送请求,令其执行请求中的命令,起到改变服务器数据的作用。所以我们要保护的对象是那些可以直接产生数据改变的服务,而对于那些读取数据的服务则不需要进行CSRF的保护。

二.CSRF检测

由于CSRF攻击是利用服务器没有对浏览器发来的请求进行检测,从而导致服务器接受并处理了被攻击者修改后的请求。

因此如果抓取一个正常请求的数据包,修改其请求内容并且去掉Referer字段后重新提交能够生效,那么就说明服务器没有对修改后的请求进行检测,即说明其存在CSRF漏洞。

现代的漏洞检测工具有:CSRFTester,CSRF Request Builder等。

三.CSRF防御

(1)验证 HTTP Referer 字段

原理:

在HTTP协议中,规定了利用Referer字段来记录HTTP请求的来源位置。

在通常情况下,用户的安全受限访问操作来源于同一个网站,正常请求发起URL跟REferer字段URL应拥有相同的一级(或二级)域名。

攻击者构建CSRF攻击只能在他自己的网站上进行构建。

综上,当服务器接受到HTTP请求时,可使用拦截器拦截该请求。判断该请求的Referer字段值。若该值为本网站的一级(或二级)域名,则证明是用户合法操作。若该值指向其他网站,则有可能是攻击者的CSRF攻击,可以拒绝该请求。

缺点:

**安全性无保障:**由于Referer值是由浏览器提供,每个浏览器的具体实现可能有差别,并且不能够绝对保证浏览器没有安全漏洞(像IE6 或 FF2,已经出现一些方法可以篡改HTTP请求的Referer值)。

**涉及用户隐私,Referer可禁用:**若REferer字段值被禁用,当用户发出正常请求操作时,可能被服务器认定为CSRF攻击。

(2)在请求地址中添加token验证

原理:

攻击者之所以能够使用CSRF,是因为攻击者可以完全伪造用户的请求。

那么在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中,即可以放在网页的URL上

可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并将该token存在浏览器与服务器相连的Session上。并在服务器端建立一个拦截器来拦截验证请求中的 token参数,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。

缺点:

多个请求添加token很麻烦:一个网站可以发送的请求有很多,要在所有的请求上都加上token参数很麻烦。

难以保证token安全:

虽然攻击者无法得到正常网站中用户的token值。但如果该网站支持用户发布自己的网站地址,这时候攻击者将自己网站的地址发布到正常网站中,而用户通过正常网站跳转到攻击者网站时,攻击者可以取到自己网站URL上被附加的token参数值,此时便可以发动CSRF攻击。

为了避免这一点,系统可以在添加 token 的时候增加一个判断,如果这个链接是链到自己本站的,就在后面添加 token,如果是通向外网则不加。

另外,即使这个 csrftoken 不以参数的形式附加在请求之中,黑客的网站也同样可以通过 Referer 来得到这个 token 值以发动 CSRF 攻击(由于Referer字段会记录请求的来源,而为了使用户能够得到正确的token,在之前的URL中是附带了该token的)。

(3)在HTTP头中自定义属性并验证

原理:

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

缺点

**异步请求无法使用所有场景:**XMLHttpRequest 请求通常用于 Ajax 方法中对于页面局部的异步刷新,并非所有的请求都适合用这个类来发起,而且通过该类请求得到的页面不能被浏览器所记录下,从而进行前进,后退,刷新,收藏等操作,给用户带来不便。

重构无CSRF防护的系统不方便对于没有进行 CSRF 防护的遗留系统来说,要采用这种方法来进行防护,要把所有请求都改为 XMLHttpRequest 请求。但对于前一个方法需要更改所有请求来说,还是比较合算的。

(4)在Cookie中添加token

我们知道,攻击者无法获取目标用户的cookie并且无法查看cookie内容,因此我们可以在用户的cookie上添加上随机用以验证的token。该方法与上面的几个方法基本相同,不同之处是将token的存储地点由服务器端的Session转换到客户端的Cookie中。它与将CSRF-Token存储在Session中是一样的,仅仅是Token的一种储存形式。

缺点:

如果攻击者不单单使用CSRF攻击,而是先使用xss攻击劫持用户的cookie,这时候攻击者将直接实现CSRF攻击。

(5)加验证码

在一下系统的关键服务上使用验证码强制用户与应用进行交互后才能完成请求。

缺点:

**用户体验差:**尽管该方法能够有效遏制CSRF攻击,但过多的验证码无疑会降低用户的体验。

四,思考

在网站无需适配一些能够被篡改Referer字段的浏览器时,使用HTTP Referer字段验证是一个不错的选择。只需要增添一个拦截器判断请求的来源即可,无需太多的额外操作。但若被用户禁用掉Referer字段,该方法反而有点搬石头砸自己脚的感觉。

采用token验证应该是一个更加完善的选择,但也存在这许多问题:

若是放在请求URL内,若该正常网站外联了其他恶意网站,很容易便能被攻击者取得token进行CSRF攻击。而且对于每个请求都要加入附加token的操作,给前端造成了不小的工作量。不过该方法倒是很适合用于不支持用户自定义外部链接的网站。

在HHTP头自定义属性倒是能利用异步请求的XMLHttpRequest 来一次性给Ajax请求加上token,能够有效减少前端工作量,但是缺点也很明显:对于大部分非异步请求仍然是需要自己为其附加上token值。

最后对于作为验证的token是可以存放在客户端的cookie或者是服务器端的Session的,根据CSRF的攻击而言,拿不到cookie的值也就相当于该token是安全的。

但是以上防护的前提仍是要建立在系统上没有XSS漏洞的前提下。否则攻击者将很容易获取到token值或者是cookie内容,此时以上针对CSRF攻击的操作就显得多此一举了。

参考网站

CSRF攻击与防御(写得非常好)

猜你喜欢

转载自blog.csdn.net/weixin_41973131/article/details/85059100
今日推荐