CSRF定义: 跨站请求伪造(英语:Cross-site request forgery)是一种对网站的恶意利用,也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。 CSRF跨站点请求伪造(Cross—Site Request Forgery) 跟XSS攻击一样,存在巨大的危害性。
你可以这样来理解:攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。
简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并执行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去执行。这利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
CSRF地位: 是一种网络攻击方式,是互联网重大安全隐患之一,NYTimes.com(纽约时报)、Metafilter,YouTube、Gmail和百度HI都受到过此类攻击。
对比XSS: 跟跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。
如下:其中Web A为存在CSRF漏洞的网站,Web B为攻击者构建的恶意网站,User C为Web A网站的合法用户。
如果上面 CSRF 原理看不懂,可以再看这个原理:
先了解第一方和第三方cookie概念
Cookie是一个域服务器存储在浏览器中的一小段数据块,只能被这个域访问,谁设置则谁访问。
第一方Cookie:比如,访问www.a.com这个网站,这个网站设置了一个Cookie,这个Cookie也只能被www.a.com这个域下的网页读取。
第三方Cookie:比如,访问www.a.com这个网站,网页里有用到www.b.com网站的一张图片,浏览器在www.b.com请求图片的时候,www.b.com设置了一个Cookie,那这个Cookie只能被www.b.com这个域访问,反而不能被www.a.com这个域访问,因为对我们来说,我们实际是在访问www.a.com这个网站被设置了一个www.b.com这个域下的Cookie,所以叫第三方Cookie。
简而言之: 通过访问恶意网址,恶意网址返回来js自动执行访问你之前登陆的网址,因为你已经登录了,所以再次访问将会携带cookie,因为服务器只认有没有cookie,无法区分是不是用户正常的访问,所以会欺骗服务器,造成伤害
CSRF攻击防御
CSRF攻击防御的重点是利用cookie的值只能被第一方读取,无法读取第三方的cookie值。
防御方法:
预防csrf攻击简单可行的方法就是在客户端网页上再次添加一个cookie,保存一个随机数,而用户访问的时候,先读取这个cookie的值,hash一下这个cookie值并发送给服务器,服务器接收到用户的hash之后的值,同时取出之前设置在用户端的cookie的值,用同样的算法hash这个cookie值,比较这两个hash值,相同则是合法。(如果用户访问了病毒网站,也想带这个cookie去访问的时候,此时,因为病毒网站无法获取第三方cookie的值,所以他也就无法hash这个随机数,所以也就会被服务器校验的过滤掉)
CSRF 比 XSS更具危险性。想要深入理解 CSRF 的攻击特性,我们有必要了解一下网站session的工作原理。
session 我想大家都不陌生,无论你用.net或PHP开发过网站的都肯定用过session对象,然而session它是如何工作的呢?如果你不清楚请往下看。
先问个小问题:如果我把浏览器的cookie禁用了,大家认为session还能正常工作吗?
答案是否定的,我在这边举个简单的例子帮助大家理解session。
比如我买了一张高尔夫俱乐部的会员卡,俱乐部给了我一张带有卡号的会员卡。我能享受哪些权利(比如我是高级会员卡可以打19洞和后付费喝饮料,而初级会员卡只能在练习场挥杆)以及我的个人资料都是保存在高尔夫俱乐部的数据库里的。我每次去高尔夫俱乐部只需要出示这张高级会员卡,俱乐部就知道我是谁了,并且为我服务了。
这里我们的高级会员卡卡号 = 保存在cookie的sessionid; 而我的高级会员卡权利和个人信息就是服务端的session对象了。
我们知道http请求是无状态的,也就是说每次http请求都是独立的无关之前的操作的,但是每次http请求都会将本域下的所有cookie作为http请求头的一部分发送给服务端,所以服务端就根据请求中的cookie存放的sessionid去session对象中找到该会员资料了。
当然session的保存方法多种多样,可以保存在文件中,也可以内存里,考虑到分布式的横向扩展我们还是建议把它保存在第三方媒介中,比如redis或者mongodb。
我们理解了session的工作机制后,CSRF也就很容易理解了。CSRF攻击就相当于恶意用户A复制了我的高级会员卡,哪天恶意用户A也可以拿着这张假冒的高级会员卡去高尔夫俱乐部打19洞,享受美味的饮料了,而我在月底就会收到高尔夫俱乐部的账单!
了解CSRF的机制之后,危害性我相信大家已经不言而喻了,我可以伪造某一个用户的身份给其好友发送垃圾信息,这些垃圾信息的超链接可能带有木马程序或者一些欺骗信息(比如借钱之类的),如果CSRF发送的垃圾信息还带有蠕虫链接的话,那些接收到这些有害信息的好友万一打开私信中的连接就也成为了有害信息的散播着,这样数以万计的用户被窃取了资料种植了木马。整个网站的应用就可能在瞬间奔溃,用户投诉,用户流失,公司声誉一落千丈甚至面临倒闭。曾经在MSN上,一个美国的19岁的小伙子Samy利用css的background漏洞几小时内让100多万用户成功的感染了他的蠕虫,虽然这个蠕虫并没有破坏整个应用,只是在每一个用户的签名后面都增加了一句“Samy 是我的偶像”,但是一旦这些漏洞被恶意用户利用,后果将不堪设想,同样的事情也曾经发生在新浪微博上面。
举例:
CSRF攻击的主要目的是让用户在不知情的情况下攻击自己已登录的一个系统,类似于钓鱼。如用户当前已经登录了邮箱,或bbs,同时用户又在使用另外一个,已经被你控制的站点,我们姑且叫它钓鱼网站。这个网站上面可能因为某个图片吸引你,你去点击一下,此时可能就会触发一个js的点击事件,构造一个bbs发帖的请求,去往你的bbs发帖,由于当前你的浏览器状态已经是登陆状态,所以session登陆cookie信息都会跟正常的请求一样,纯天然的利用当前的登陆状态,让用户在不知情的情况下,帮你发帖或干其他事情。
所以要被CSRF攻击,必须同时满足两个条件: