CSRF攻击

相关链接:
http://www.phpddt.com/reprint/csrf.html
https://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html
https://blog.csdn.net/diu_brother/article/details/88367029?spm=1001.2014.3001.5501
侵权删

CSRF概念

Cross-Site Request Forgery(CSRF),中文一般译作跨站请求伪造。经常入选owasp漏洞列表Top10,在当前web漏洞排行中,与XSS和SQL注入并列前三。
跨站请求攻击,简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。这利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
例子
假如一家银行用以运行转账操作的URL地址如下:http://www.examplebank.com/withdraw?account=AccoutName&amount=1000&for=PayeeName
那么,一个恶意攻击者可以在另一个网站上放置如下代码: <img src="http://www.examplebank.com/withdraw?account=Alice&amount=1000&for=Badman">
如果有账户名为Alice的用户访问了恶意站点,而她之前刚访问过银行不久,登录信息尚未过期,那么她就会损失1000资金。
这种恶意的网址可以有很多种形式,藏身于网页中的许多地方。此外,攻击者也不需要控制放置恶意网址的网站。例如他可以将这种地址藏在论坛,博客等任何用户生成内容的网站中。这意味着如果服务端没有合适的防御措施的话,用户即使访问熟悉的可信网站也有受攻击的危险。
透过例子能够看出,攻击者并不能通过CSRF攻击来直接获取用户的账户控制权,也不能直接窃取用户的任何信息。他们能做到的,是欺骗用户浏览器,让其以用户的名义运行操作。

CSRF分类

在跨站请求伪造(CSRF)攻击里面,攻击者通过用户的浏览器来注入额外的网络请求,来破坏一个网站会话的完整性。而浏览器的安全策略是允许当前页面发送到任何地址的请求,因此也就意味着当用户在浏览他/她无法控制的资源时,攻击者可以控制页面的内容来控制浏览器发送它精心构造的请求。
1.网络连接。例如,如果攻击者无法直接访问防火墙内的资源,他可以利用防火墙内用户的浏览器间接的对他所想访问的资源发送网络请求。甚至还有这样一种情况,攻击者为了绕过基于IP地址的验证策略,利用受害者的IP地址来发起他想发起的请求。
2.获知浏览器的状态。当浏览器发送请求时,通常情况下,网络协议里包含了浏览器的状态。这其中包括很多,比如cookie,客户端证书或基于身份验证的header。因此,当攻击者借助浏览器向需要上述这些cookie,证书和header等作验证的站点发送请求的时候,站点则无法区分真实用户和攻击者。
3.改变浏览器的状态。当攻击者借助浏览器发起一个请求的时候,浏览器也会分析并相应服务端的response。举个例子,如果服务端的response里包含有一个Set-Cookie的header,浏览器会相应这个Set-Cookie,并修改存储在本地的cookie

三种危害模型

1、论坛可交互的地方。很多网站,比如论坛允许用户自定义有限种类的内容。举例来说,通常情况下,网站允许用户提交一些被动的如图像或链接等内容。如果攻击者让图像的url指向一个恶意的地址,那么本次网络请求很有可能导致CSRF攻击。这些地方都可以发起请求,但这些请求不能自定义HTTP header,而且必须使用GET方法。尽管HTTP协议规范要求请求不能带有危害,但是很多网站并不符合这一要求。
2、Web攻击者。在这里web攻击者的定义是指有自己的独立域名的恶意代理,比如attacker.com,并且拥有attacker.com的HTTPS证书和web服务器。所有的这些功能只需要花10美元即可以做到。一旦用户访问attacker.com,攻击者就可以同时用GET和POST方法发起跨站请求,即为CSRF攻击。
3、网络攻击者。这里的网络攻击者指的是能控制用户网络连接的恶意代理。比如,攻击者可以通过控制无线路由器或者DNS服务器来控制用户的网络连接。这种攻击比web攻击需要更多的资源和准备,但我们认为这对HTTPS站点也有威胁。因为HTTPS站点只能防护有源网络。

CSRF攻击思想

在这里插入图片描述
要完成一次CSRF攻击,受害者必须依次完成两个步骤:
  1.登录受信任网站A,并在本地生成Cookie。
  2.在不登出A的情况下,访问危险网站B。
看到这里,你也许会说:“如果我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:

1.你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站。

2.你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了…)

3.上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。

攻击方式

(a)在正确的URL页面构造一个登陆框
(b)盗取用户自动填充的密码
(c)在另一个窗口等待用户登陆并读取document.cookie。

CSRF攻击实例

角色

正常浏览网页的用户:User
正规的但是具有漏洞的网站:WebA
利用CSRF进行攻击的网站:WebB

流程

步骤一:用户登录、浏览并信任正规网站WebA,同时,WebA通过用户的验证并在用户的浏览器中产生Cookie。
在这里插入图片描述
步骤二
攻击者WebB通过在WebA中添加图片链接等方式诱导用户User访问网站WebB。
在这里插入图片描述
步骤三
在用户User被诱导访问WebB后,WebB会利用用户User的浏览器访问第三方网站WebA,并发出操作请求。
在这里插入图片描述

步骤四
用户User的浏览器根据WebB的要求,带着步骤一中产生的Cookie访问WebA。
在这里插入图片描述

步骤五
网站WebA接收到用户浏览器的请求,WebA无法分辨请求由何处发出,由于浏览器访问时带上用户的Cookie,因此WebA会响应浏览器的请求,如此一来,攻击网站WebB就达到了模拟用户操作的目的。
在这里插入图片描述

防御策略

详细信息见:

验证token值

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

这种方法要比检查 Referer 要安全一些,token 可以在用户登陆后产生并放于 session 之中,然后在每次请求时把 token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成 http://url?csrftoken=tokenvalue。 而对于 POST 请求来说,要在 form 的最后加上 ,这样就把 token 以参数的形式加入请求了。但是,在一个网站中,可以接受请求的地方非常多,要对于每一个请求都加上 token 是很麻烦的,并且很容易漏掉,通常使用的方法就是在每次页面加载时,使用 javascript 遍历整个 dom 树,对于 dom 中所有的 a 和 form 标签后加入 token。这样可以解决大部分的请求,但是对于在页面加载之后动态生成的 html 代码,这种方法就没有作用,还需要程序员在编码时手动添加 token。

该方法还有一个缺点是难以保证 token 本身的安全。特别是在一些论坛之类支持用户自己发表内容的网站,黑客可以在上面发布自己个人网站的地址。由于系统也会在这个地址后面加上 token,黑客可以在自己的网站上得到这个 token,并马上就可以发动 CSRF 攻击。为了避免这一点,系统可以在添加 token 的时候增加一个判断,如果这个链接是链到自己本站的,就在后面添加 token,如果是通向外网则不加。不过,即使这个 csrftoken 不以参数的形式附加在请求之中,黑客的网站也同样可以通过 Referer 来得到这个 token 值以发动 CSRF 攻击。这也是一些用户喜欢手动关闭浏览器 Referer 功能的原因。
session标识符。浏览器的cookie存储方式就是为了防止不同域之间互相访问cookie。一个普遍的做法是直接利用用户的session标识符来作为验证token。服务器在处理每一个请求时,都将用户的token与session标识符来匹配。如果攻击者能够猜测出用户的token,那么他就能登录用户的账户。而且这样做有个不好的地方在于,偶尔用户正在浏览的内容会发送给第三方,比如通过电子邮件直接上网页内容上传到浏览器厂商的bug跟踪数据库。如果正好这个页面包含有用户的session标识符,任何能看到这个页面的人都能模拟用户登陆到网站,直到会话过期。
独立session随机数。与直接使用用户的session标识符不一样的是,当用户第一次登陆网站的时候,服务器可以产生一个随机数并将它存储在用户的cookie里面。对于每一个请求,服务器都会将token与存储在cookie里的值匹配。例如,广泛使用的Trac问题跟踪系统就是用的此技术。但是这个方法不能防御主动的网络攻击,即使是整个web应用都使用的是HTTPS协议。因为攻击者可以使用他自己的CSRF token来覆盖来覆盖这个独立session随机数,进而可以使用一个匹配的token来伪造一个跨站请求。
依赖session随机数。有一个改进产生随机数的方法是将用户的session标识符与CSRF token建立对应关系后存储在服务端。服务器在处理请求的时候,验证请求中的token是否与session标识符匹配。这个方法有个不好的地方就是服务端必须要维护一个很大的对应关系表(哈希表)。
session标识符的HMAC。有一种方法不需要服务端来维护哈希表,就是可以对用户的session token做一个加密后用作CSRF的token。例如, Ruby on Rails的web程序一般都是使用的这种方法,而且他们是使用session标识符的HMAC来作为CSRF token的。只要所有的网站服务器都共享了HMAC密钥,那么每个服务器都可以验证请求里的CSRF token 是否与session标识符匹配。HMAC的特性能确保即使攻击者知道用户的CSRF token,也不能推断出用户的session标识符。
鉴于有充足的资源,网站都可以使用HMAC方法来防御CSRF攻击。但是,很多网站和一些CSRF的防御框架(比如NoForge, CSRFx 和CSRFGuard)都不能正确的实现比较隐秘的token防御。一个常见的错误就是在处理跨站请求的时候暴露了CSRF token。举个例子,一个可信的网站在对另一个网站发起请求的时候附加上了CSRF token,那么那个网站就可以对这个可信的网站伪造一个跨站请求。

Referer

大多数情况下,当浏览器发起一个HTTP请求,其中的Referer标识了请求是从哪里发起的。如果HTTP头里包含有Referer的时候,我们可以区分请求是同域下还是跨站发起的,因为Referer离标明了发起请求的URL。网站也可以通过判断有问题的请求是否是同域下发起的来防御CSRF攻击。
不幸的是,通常Referer会包含有一些敏感信息,可能会侵犯用户的隐私。比如,Referer可以显示用户对某个私密网站的搜索和查询。尽管这些内容对私密网站站长来说是好事,因为他们可以通过这些内容来优化搜索引擎排名,但是一些用户还是认为侵犯了他们的隐私。另外,许多组织也很担忧Referer可能会将内网的一些机密信息泄露出去。
漏洞。从历史上来看,浏览器的一些漏洞使得一些恶意网站有欺骗Referer的价值,尤其是在使用代理服务器的时候。很多对Referer欺骗的讨论都标明浏览器允许Referer可以伪造。Mozilla在Fire-fox 1.0.7里面已经修复了Referer欺骗的漏洞。目前的IE则还有这方面的漏洞,但是这些漏洞只能影响XMLHttpRequest,并且只能用来伪造Referer跳转到攻击者自己的网站。
尺度。如果网站选择使用Referer来防御CSRF攻击的话,那么网站的开发人员就需要决定到底是使用比较宽松还是比较严格的Referer验证策略。如果采用宽松的Referer验证策略,网站就应该阻止Referer值不对的请求。如果请求里面没有Referer,就接收请求。尽管这个方法用的很普遍,但是它很容易被绕过。因为攻击者可以在header里面去掉Referer。例如,FTP和数据URL发起的请求里面就不包含Referer。如果使用严格的Referer验证策略,网站还要阻止没有Referer的请求。这样做主要是为了防止恶意网站主动隐藏Referer,但也会带来兼容性问题,比如会误杀一部分合法的请求,因为有些浏览器和网络的设置默认就是不含有Referer的。

自定义HTTP header

我们可以用自定义HTTP头的方法来防御CSRF攻击,因为虽然浏览器会阻止向外站发送自定义的HTTP头,但是允许向本站通过XMLHttpRequest的方式发送自定义HTTP头。比如,prototype.js这个JavaScript库就是使用这种方法,并且增加了 X-Requested-By头到XMLHttpRequest里面 。Google Web Toolkit 也建议开发者用在XMLHttpRequest里增加一个X-XSRF-Cookie头的方法来防御CSRF攻击,其中XMLHttpRequets包含有cookie的值。当然XMLHttpRequets里面的cookie并不需要用来防御CSRF,因为只需要有头部分就足够了。
在使用这种方法来防御CSRF攻击的时候,网站必须在所有的请求里使用XMLHttpRequest并附加一个自定义头(比如X-Requested-By),并且拒绝所有没有自定义头的的请求。例如,为了防御登陆CSRF的攻击,网站必须通过XMLHttpRequest的方式发送用户的身份验证信息到服务器。在我们的实验里,在服务器接收到的请求里面,大约有99.90–99.99%的请求是含有X-Requested-By头的,这表明这一方法适用于绝大多数的用户。
为了防止CSRF的攻击,我们建议修改浏览器在发送POST请求的时候加上一个Origin字段,这个Origin字段主要是用来标识出最初请求是从哪里发起的。如果浏览器不能确定源在哪里,那么在发送的请求里面Origin字段的值就为空。
安全性分析:虽然Origin字段的设计非常简单,但是用它来防御CSRF攻击可以起到很好的作用。
1、去掉Origin字段。由于支持这种方法的浏览器在每次POST请求的时候都会带上源header,那么网站就可以通过查看是否存在这种Origin字段来确定请求是否是由支持这种方法的浏览器发起的。这种设计能有效防止攻击者将一个支持这种方法的浏览器改变成不支持这种方法的浏览器,因为即使你改变浏览器去掉了Origin字段,Origin字段还是存在,只不过值变为空了。这跟Referer很不一样,因为Referer 只要是在请求里去掉了,那服务器就探测不到了。
2、DNS重新绑定。在现有的浏览器里面,对于同站的XMLHttpRequests,Origin字段可以被伪造。只依赖网络连接进行身份验证的网站应当使用在第2章里提到的DNS重新绑定的方法,比如验证header里的Host字段。在使用Origin字段来防御CSRF攻击的时候,也需要用到DNS重新绑定的方法,他们是相辅相成的。当然对于在第四章里提到的CSRF防御方法,也需要用到DNS重新绑定的方法。
3、插件。如果网站根据crossdomain.xml准备接受一个跨站HTTP请求的时候,攻击者可以在请求里用Flash Player来设置Origin字段。在处理跨站请求的时候,token验证的方法处理的不好,因为token会暴露。为了应对这些攻击,网站不应当接受不可信来源的跨站请求。
4、应用。Origin字段跟以下四个用来确定请求来源的建议非常类似。Origin字段以下四个建议的基础上统一并改进了,目前已经有几个组织采用了Origin字段的方法建议。

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值