文章首发于公众号【程序员读书】,欢迎关注。
CSRF是一种常见的Web攻击方式,不过还是有挺多小伙伴对CSRF的概念不太了解,没有重视CSRF可能对自己站点造成的危害,因此今天我们在这篇文章中来谈一谈CSRF这个概念,好让大家对CSRF有一个比较全面的了解。
什么是CSRF
CSRF攻击,英文全称为Cross-site request forgery,中文的名称为跨站请求伪造,也被称为one click attack/session riding,其缩写为CSRF/XSRF,是一种非常常见的Web攻击方式,不过很多小伙伴在开发项目时可能没有这样的安全意识,因此会产生有一些CSRF漏洞,给攻击者可趁之机,Web站点一旦受到攻击,往往会对Web站点造成严重的危害。
CSRF的危害
CSRF具体有哪些危害呢?我们要先理解CSRF是如何攻击的。
CSRF的攻击方式可以概括为:CSRF攻击者盗用了你的身份,并以你的名义发送恶意请求。
比如使用你的账号发送邮件,发消息,盗取你的账号,删除你的个人信息,购买商品,虚拟货币或银行转账。
总而言之,就是会造成个人隐私泄露以及财产损失。
CSRF的原理
在一次CSRF攻击中,有以下三个角色,受害者(User)、受用户信任的网站(存在CSRF漏洞的网站被攻击的网站,假设为Web A)、攻击者(Web B),CSRF原理如下图所示:

从上面的示意图我们可以看来,要触发一次CSRF攻击,必须满足两个条件:
- 正常登录
Web A,并且在本地生成了Cookie。 - 在没有退出
Web A登录状态的情况下,进入Web B中并触发了构造的请求。
我们假设Web A站点有一个文章列表,在该列表中支持用户使用HTTP的GET删除自己的文章,链接如下:
https://www.article.com/article_list.php?action=delete&article_id=1
那么用户登录Web A后,如果没有退出就访问Web B站点,在Web B可以通过下面的语句构造一个删除文章的请求,如果用户在Web B点击下面的图片,就会删了自己的文章。
<img src="https://www.article.com/article_list.php?action=delete&article_id=1">
上面代码的使用GET,很容易被其他站点伪造请求,如果改成Post请求呢,比如在Web A中把删除文章的代码改为:
<form method="POST" name="article" action="https://www.article.com/article_list.php">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="article_id" value="1">
</form>
虽然在Web A中把代码改为Post请求了,但在Web B中同样可以伪造相应的Post请求,如下:
<html> <head> <script type="text/javascript"> function btn(){ iframe = document.frames["delArticle"]; iframe.document.Submit("article"); } </script> </head>
<body onload="btn()"> <iframe name="delArticle" display="none"> <form method="POST" name="article" action="www.article.com/article_lis…"> <input type="hidden" name="action" value="delete"> <input type="hidden" name="article_id" value="1"> </form> </iframe> </body> </html>
如今我们打开浏览器,可以访问成千上万的网站,因此在某站点登录后,再访问另一个站点,这种情况经常发生,所以网站只有避免出现CSRF漏洞,才能保证用户的信息安全,避免用户遭受损失。
如何防御
通过上面的介绍,我们应该明白了CSRF原理,只有在了解了原理,才知道应该如何防御这种攻击,我们主要介绍下面三种方式。
验证码
验证码是一种防御CSRF攻击有效方法。其原理是每一种操作都让用户输入验证码。
CSRF攻击是在攻击者的攻击站点中构造网络请求,然后用户在不知情的状况下触发,而强制输入验证码,则可以让用户知道当前在操作什么,进而达到预防的目的。
但这种方式有一个问题,就是每个操作都强制用户输入验证码,因此用户体验并不好,所以并不常用,只能作为一种辅助的预防手段。
检测HTTP Referer字段
即然我们知道CSRF攻击者,是自来其他的站点,比如在上面的示意图中,我们看到的是Web B攻击Web A,那么我们可以通过检测请求来源来避免遭受CSRF攻击。
在HTTP请求中,Referer字段的数据为上一次请求的地址,因此我们通过获取Referer字段,检测该字段是否为我们自己的站点地址,这样就可以避免CSRF攻击。
但是这种方式有自己的局限性,我们很多时候是取不到Referer字段的值。
- 用户出于隐私考虑,禁止发送
Referer字段信息。 - 从
HTTPS跳到HTTP,出于安全的考虑,浏览器不会发送Referer字段。 - 有些插件允许自定义
Referer字段的信息,因此可以伪造。
虽然通过检测HTTP中的Referer字段,并不能够有效预防CSRF攻击,但却可以作为一种监测CSRF攻击的方式。
CSRF Token
无论是使用验证码还是检测HTTP Referer,似乎都不能很好地解决CSRF攻击的问题。
CSRF攻击的本质是攻击者可以猜测到构造一个请求所需要的参数,那么,如果要防御,其方法就是让参数变得不可猜测,目前,比较有效和通用的方法是增加一个随机不可预测token,这个token可以放在session或客户端的cookie中,在提交请求时带上,因此攻击都无法得知token,因此也无法伪造请求。
在使用csrf token防御CSRF攻击时,有以下注意事项:
token保密且随机,使其不可预测。- 使用
token时,需要用表单post提示,而不能跟在url之中,避免暴露。
小结
在这篇文章中,我们对CRSF进行全面讲解,同时也介绍了几种防御CSRF攻击方法,在实际应用中,我们可能根据自己的实际情况选择合适的方式。
文章首发于公众号【程序员读书】,欢迎关注。
