Web安全 // CSRF(跨站请求伪造)

一、简介

  跨站请求伪造(Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。跟跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任CSRF 利用的是网站对用户网页浏览器的信任

二、用处

  简单来说,CSRF 攻击就是攻击者盗用了用户的身份,然后以用户的名义去发送恶意请求。CSRF 能够做许多事情,例如:以用户的名义发送邮件、发表博客、盗取账号甚至于购买商品、交易转账……

三、攻击原理

  我们知道,绝大多数网站都是通过 Cookie 等方式来辨识用户身份再予以授权的。因此攻击者可以利用用户在浏览器端保存的 Cookie 等认证信息,向相应的站点发送伪造请求,由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去执行。这利用了 Web 中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。

在这里插入图片描述
在这里插入图片描述

四、示例

  假如某论坛网站的发贴是通过 GET 请求访问,点击发表后 JS 把发贴内容拼接成目标 URL 并访问:

http://www.someforum.com/bbs/create_post.php?title=标题&content=内容

  那么攻击者可以在某网站中插入一个 HTML 的 img 标签如下:
  
<img src=http://www.someforum.com/bbs/create_post.php?title=暂时没想到什么花里胡哨的标题&content=同上>

  当用户登录该论坛后,若又访问了攻击者的危险网站,那么用户的帐户就会在其不知情的情况下发表这一新帖子。
  原因在于,当用户访问攻击者的危险网站时,浏览器在解析网页时会自动向 img 标签中的 src 属性中的地址发送请求。然而此时用户在论坛的登录信息仍保存在 cookie 中,其登录信息尚未过期,所以浏览器会带上登录信息去向论坛服务器请求,服务器在收到请求后根据 Cookie 判断此操作是用户所为,进而进行发表操作。
  这种恶意的请求网址可以有很多种形式,藏身于网页中的许多地方。此外,攻击者也不需要控制放置恶意网址的网站。例如他可以将这种地址藏在论坛,博客等任何用户生成内容的网站中。这意味着如果服务端没有合适的防御措施的话,用户即使访问熟悉的可信网站也有受攻击的危险。透过例子能够看出,攻击者并不能通过 CSRF 攻击来直接获取用户的账户控制权,也不能直接窃取用户的任何信息。他们能做到的是,欺骗用户浏览器,让其以用户的名义运行操作。   

五、防御手段

  虽然现实中很少有网站会使用GET请求来执行包含数据更改等敏感操作,但这并不意味着就可以避免 CSRF 攻击。CSRF 攻击可分为许多种类,按请求类型,可分为 GET 型和 POST 型;按攻击方式,可分为 HTML CSRF、JSON HiJacking、Flash CSRF 等。由于发起请求的方式多种多样,几乎没有彻底杜绝 CSRF 攻击的方式,但我们可以采取各种方式来提高攻击的门槛,例如:

检查Referer字段

  HTTP头中有一个Referer字段,这个字段用以标明请求来源于哪个地址。在处理敏感数据请求时,通常来说,Referer字段应和请求的地址位于同一域名下。这种办法简单易行,工作量低,仅需要在关键访问处增加一步校验。但这种办法也有其局限性,因其完全依赖浏览器发送正确的Referer字段。虽然http协议对此字段的内容有明确的规定,但并无法保证来访的浏览器的具体实现,亦无法保证浏览器没有安全漏洞影响到此字段。并且也存在攻击者攻击某些浏览器,篡改其Referer字段的可能。

添加校验token

  由于CSRF的本质在于攻击者欺骗用户去访问自己设置的地址,所以如果要求在访问敏感数据请求时,要求用户浏览器提供不保存在cookie中,并且攻击者无法伪造的数据作为校验,那么攻击者就无法再运行CSRF攻击。这种数据通常是窗体中的一个数据项。服务器将其生成并附加在窗体中,其内容是一个伪随机数。当客户端通过窗体提交请求时,这个伪随机数也一并提交上去以供校验。正常的访问时,客户端浏览器能够正确得到并传回这个伪随机数,而通过CSRF传来的欺骗性攻击中,攻击者无从事先得知这个伪随机数的值,服务端就会因为校验token的值为空或者错误,拒绝这个可疑请求。