深度理解CSRF攻击

 做过Web开发的朋友或多或少都听说过CSRF攻击,但未必真的理解,因为我曾经也在好长一段时间里似懂非懂,比如以为CSRF攻击采用同源策略的限制就可以避免。希望看完本篇文章后能让您有更深的理解,最好有一种豁然开朗的感觉:)。

1、什么是CSRF攻击?

        CSRF,英文全称Cross-site request forgery。翻译过来就是“跨站请求伪造”,怎么理解呢?我们先来看一个例子:

        用户U首先通过浏览器成功登录了一个受信任的电商网站A(比如某宝某东),进入页面后做了些日常操作。这时候因为某些原因在没有关闭网站A页面的情况下又打开了一个新的浏览器页面(一般是通过tab方式打开),访问了一个可能不太安全的网站B(不安全为什么还要打开?别问我,问就是你懂的。),然后在网站的诱惑下做了一些操作,比如点了下按钮什么的。假如开发网站B的攻击者曾经对网站A非常了解(也许就是网站A曾经的高级码农),那么用户U可能就已经中招了。为什么会中招?因为在打开网站B或者说点击网站B页面的某个按钮的那一刻,很可能就执行了类似下面的代码:

<form action="https://网站A/methodC" method="post">
    <input type="hidden" name="amount" value="2000"/>
    <input type="hidden" name="account" value="tom"/>
    <input type="submit" value="点我就送!"/>
</form>

       这段代码的意思是通过表单调用网站A的某个方法向攻击者的账号转了2000元钱。而实际的攻击可能更隐蔽,比如使用JS自动完成上述代码的提交,你完全不知晓。等到你发现后想追回这笔钱?很遗憾,这个网站很可能是境外的,即使你知道被转账户是谁也无能为力。

2、产生CSRF攻击的原因?

现在我们从技术的角度去梳理下CSRF攻击是如何完成的。

受害用户登录了信任网站A,假如网站A在后端的鉴权是通过cookie-session机制完成的,那么此时session内容已被传到了客户端本地的cookie。

受害用户没有关闭网站A也没有注销登录,而是在同一浏览器里打开了网站B,然后触发了网站B的某个操作,恶意代码被执行,受害用户执行了一个他自己并不知道的操作,连同之前记录的session内容随cookie一同传给了网站A。

网站A收到这个请求,因为收到了cookie的session内容,同时跨站防护做的不严谨,以为是登录用户自己的请求操作,正常执行,悲剧就这样发生了。

见下图可能更好的理解(引用自什么是CSRF攻击?如何防御CRSF攻击? - 知乎):

        因为用户访问的网站A和B是两个不同源的网站,而网站B利用了网站A的漏洞进行了攻击,所以这种攻击被称为CSRF即跨站请求伪造攻击。至于什么是同源网站后面会有解释。

我们来分析下产生CSRF攻击的必要条件:

用户执行了不合法的操作,这里特指在登录网站A后不注销的情况下在同一浏览器里打开了不安全网站B页面。

服务端采用了cookie-session机制鉴权。

服务端对跨站请求没有做严谨的防护,认为只要收到客户端发来的session内容就认为是登录用户的请求操作。

3、如何避免CSRF攻击?

        知道了被攻击的过程和原因,那怎么避免呢?

1从客户端用户来说很难避免,因为用户大多数不懂技术,要求他不打开网站B或者登录A后注销(清除本地cookie-session)再打开网站B是不现实的,再说,人家就是想访问网站B你也管不了啊。既然客户端无法避免,那我们只能从服务端来解决。继续往后看

2服务端采用cookie-session机制鉴权,可以改为非cookie传递参数的鉴权机制,比如Header携带WT鉴权,从而避免跨站攻击。

        这里可能有些朋友会有疑问,浏览器传递cookie不是有同源策略的限制么?即不同源的网站之间cookie是不能互相访问的,那么网站B是怎么做到把网站A的cookie数据传到网站A的后端呢?我们来仔细解读下浏览器的同源策略:

所谓同源,就是指浏览器请求的网址有三个相同就是同源:

协议相同,例如都是http或https

域名相同,什么是域名相同请自行谷歌或百度

端口号相同

如果非同源,有以下三种操作受到限制:

Cookie、 localStorage等保存在客户端机器上的数据无法读取;

DOM无法获得;例如恶意网站可以通过iframe打开某个操作界面,如果可以获取DOM就相当于可以获取整个操作界面的信息。

AJAX请求不能发送。

        但其中有个特例,即http实现规范里表单的提交不受同源策略的限制(说实话这个规定我不是特别理解),这也就解释了为什么上面的例子中网站B能将网站A的cooike数据发送给网站A,不相信的朋友可以自行写代码验证一下,我曾经就这在这里误解了很久。

另外,即使是ajax,可能由于网站A采用了前后端分离的方式部署,即前端域名和后端域名不同源,为了保证前后端数据交互,必须解除同源策略的限制。所以在某些网站同源策略的限制实际没有产生作用,ajax的请求默认允许跨站发送。(当然可以通过在服务端以白名单的形式解决这个问题,后面会深入讨论。)

        关于JWT鉴权的详解不是本文的重点,网上有大把文章阐述,请自行谷歌或百度,这里不再赘述。

3假如网站A在后端使用cooie-sessionid机制已经根深蒂固,很难重构,必须使用。那如何解决服务端对跨站请求做严谨防护呢?

通过前面的分析我们知道,产生漏洞的根本原因在于网站A出于某些原因无法从根本上执行同源策略的限制,无法阻止cookie跨站传递,或者说由于前后端分离的部署方式,本身就允许cooike的跨站传递。那我们如何在服务端分辨这个带有合法cookie-sessionid的请求是登录用户真正发出的呢?

A、通过头Referer字段验证

        浏览器请求的header中包含一个Referer字段,这个字段可以获取请求的来源地址。我们可以事先在服务端建立一个访问白名单,如果来源地址不在白名单中,则认为是非法请求。

不过这种方法并非绝对安全,Referer 的值是由浏览器提供的,每个浏览器对于 Referer 的具体实现不尽相同,并不能保证浏览器自身没有安全漏洞。某些浏览器(比如IE系列老版本),存在篡改其Referer字段的可能。攻击者只要将Referer的来源地址改为白名单网站地址,CSRF攻击仍然无法避免。不过现代浏览器基本杜绝了这个安全漏洞,反之存在这个漏洞的浏览器基本绝迹,所以只要网站限制住不安全客户端浏览器的使用,这个方法基本是可行的。

优点:实现简单对原有系统改变较小,尤其是前端代码基本不用改动。

缺点:不能完全保证安全

B、通过在请求地址中添加token字段验证

                token字段一般是一个uuid字符串,可以在用户登录成功后产生并放于 session 之中同时回传给浏览器存储在页面中。在用户后续的请求中在参数中附带这个token,在服务端收到后续请求在拦截器中把 session中的token拿出与请求中的 token 进行比对,一致则表明是合法用户请求。

优点:由于token字段存在于网站A自身的页面中且每次登录都是随机产生的,攻击者无法直接获取,所以这种方法理论上说是绝对安全的。

缺点:由于需要在浏览器端的所有请求中加上token参数,尤其是以表单提交的代码,前端改版的工作量较大。

网上还有两种方法。

        一种是在 HTTP 头中增加自定义属性并验证,类似请求地址token字段验证,这种方法只限于ajax提交的方式,表单提交请求无法实现,局限性太大,所以不推荐。

        一种采用图片验证码的方法。由于对原系统改动量太大且对用户很不友好,所以这里就不具体介绍了。

        当然,以上两种方法在特定场合可以作为一种补充方案。

综上所述,最终解决方案:

服务端将cookie-session机制采用类似Header中携带JWT参数鉴权的解决方案,但其也有缺点,具体请自行网上搜索。

服务端在继续使用cookie-session机制的前提下,如果网站对数据安全要求不是特别高则可以采用A方案,否则采用B方案。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容