前端安全之CSRF

Anna 2020年1月15日23:07:54安全防范评论阅读模式

如果你使用过axios,想必你一定听说过XSRF吧。其实它还有一个名字,叫做CSRF。CSRF的全称是Cross Site Request Forgery,中文名是跨站请求伪造。

提出问题

如果目标网站上不存在XSS漏洞,那还有没有可能冒充用户进行一些操作呢?比如说攻击门户网站,冒充用户发布一篇文章。攻击邮箱网站,转发用户的邮件。攻击社交网站,强制让用户关注你。

攻击方法

不知道你有没有发现,进行这些操作,只需要调用目标网站的api就行了。调用api就是向目标网站发送一个HTTP请求,而这个请求是可以跨域发送的。这种跨站请求网站接口的方法,就是CSRF。

这种攻击方式有几个特点:跨域发送请求、可以没有Javascript参与、请求时需要携带用户身份信息。

场景1

比如说,你写了一篇文章,放在网站A上,想让大家都给你点赞。你可以这样做,首先找到点赞的接口是:

http://aaa.com/like?postid=文章ID

于是你把自己的文章ID套进去,把链接发到知名网站B上。网站B上的用户点击这个链接,如果用户同时登录了网站A,那么就会点赞成功。

你大概会想,用户还要点击一下链接,点进去还可能看到奇怪的东西。其实可以做得更好,比如写一个评论放到网站B上,评论里插入一张图片,将请求地址放入图片的src中。这样不用点击链接也可以发出请求了。如果你用这种方法,直接把图片插在文章里面,那么看到你文章的人都会自动帮你点赞了。

所以,在访问重要网站的时候不要随便打开或浏览别的网站,访问完之后记得退出登录。

但是,如果网站B不允许自己设置图片地址,或者网站A的接口是POST请求呢?其实问题也不大,我们看另一个场景。

场景2

假设攻击目标已经在网页上登录邮箱,攻击者想要悄悄删除对方的所有邮件,可以这样做。

首先,找出目标网站清空所有邮件的接口,发现是一个如下的POST请求:

http://mail.xxx.com/mails/rm-rf-all

于是攻击者在自己的网站上新建一个页面,页面上有一个空表单,表单的提交方法设为POST,提交的目标地址设置成清空邮件的接口地址,并且文档加载好后用JS提交该表单。ajax请求会有跨域的限制,但表单提交是没问题的。

攻击者想办法把链接地址发送给目标用户,并引导用户点开链接。用户点开链接后,表单自动提交。在用户已经登录邮箱的情况下,邮件将被清空。

所以,不要随便点开莫名其妙的链接。

关于Cookie

如果你足够细心,你会发现这些操作的前提是发送的请求能够携带用户登录信息,而登录信息往往保存在cookie中。在用ajax发送跨域请求时,默认是不会带有cookie的,那么这种攻击方式发送的请求会带有cookie吗?

其实,浏览器不会拒绝所有的跨域请求。像这种利用iframe、图片地址、提交表单之类的方式发出的跨域请求,脚本并不能拿到数据内容,所以是正常、合法的。大多数情况下都是会发送cookie的,只有少数浏览器会有一些限制。如果你想了解详细的话,不妨查一查P3P和cookie的关系。

另外,就算直接使用ajax发送跨域请求,也有可能成功。虽然JS脚本的执行结果告诉你请求失败,但浏览器的确向服务器发送了请求。这一点在之后讲跨域的时候会详细谈到。

关于防御

要对CSRF进行防御,主要有以下几种方式。

  1. 校验HTTP Referer请求头浏览器在发送HTTP请求时,会设置一个Referer请求头,表示发送请求的页面地址。这个请求头是无法用脚本更改的,即使是通过ajax发送请求。利用CSRF跨域的特点,服务器只需要检查Referer请求头,即可判断请求是否来自本站。

    但是,这种方法有两个缺陷。第一,虽然无法修改这个请求头,但是为了用户的隐私考虑,浏览器允许通过代码或设置禁用这个请求头。这样浏览器就不会发送Referer首部,服务器也就无法判断请求是否来自本站。第二,CSRF虽然名为跨站请求,但其实在站内也是可以发动这种攻击的,所以这种方式无法防止站内CSRF攻击。

    其实Referer首部很有用。有些网站上的图片在别的网站上引用时,会无法显示,也是利用这个请求头,这就是图片防盗链技术。如果你非要引用这种网站的图片,那就想办法禁用掉Referer。

  2. 使用验证码验证码是防止CSRF的一个很有效的手段。在提交重要的表单时,增加一个验证码,后台校验验证码不正确,则判定此次请求失败。

    但是,使用验证码会降低用户体验,也不可能每次调用接口都让用户输入一个验证码。

  3. 使用token使用token是目前最常用的方式了。每次发送请求之前,服务器生成一个随机字符串(token字符串)发送给浏览器,浏览器请求的时候,把这个字符串一并发送回服务器。服务器如果检测到接收到的token值和之前生成的不一样,则判定本次提交失败。仔细想想,其实这种方式和验证码的方式原理是一样的。

    因为CSRF无法读取数据,只能发送固定的请求,所以不可能知道token。但如果token的生成方式太过简单,还是有可能被猜中的。

    token可能通过两个地方发送:一个是随请求数据发送,例如表单字段;另一个是随请求头发送。使用请求头发送是更安全的方式,因为跨域时是很难发送自定义的请求头的,所以即使token被猜到也影响不大。

声明:本文属于技术文章,仅供学习使用。请勿使用文中的方法进行真实的攻击,否则造成的后果与作者无关。

本文来自:变化吧门户-www.bianhb.com
特别声明:以上文章内容仅代表作者本人观点,不代表变化吧门户观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与变化吧联系。

  • 赞助本站
  • 微信扫一扫
  • weinxin
  • 加入Q群
  • QQ扫一扫
  • weinxin
Anna

发表评论