[关闭]
@1kbfree 2018-03-14T11:09:57.000000Z 字数 5104 阅读 1120

Csrf跨站请求伪造攻击

在网上找的资料并写下的笔记,写的不好大佬多多包涵

概念

Csrf是一种网络的攻击方式,它在 2007 年曾被列为互联网 20 大安全隐患之一,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用也就是人们所知道的钓鱼网站。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性

简要攻击流程

攻击者盗用了你的身份,伪装成你发送恶意请求

Csrf的攻击案例

CSRF 攻击可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击站点,从而在并未授权的情况下执行在权限保护之下的操作。

比如说,受害者 Bob在银行有一笔存款,通过对银行的网站发送请求:

http://bank.example/withdraw?account=bob&amount=1000000&for=bob2可以使 Bob 把 1000000 的存款转到bob2的账号下。通常情况下,该请求发送到网站后,服务器会先验证该请求是否来自一个合法的 session,并且该 session 的用户 Bob已经成功登陆。黑客Mallory自己在该银行也有账户,他知道上文中的 URL可以把钱进行转帐操作。Mallory可以自己发送一个请求给银行:
http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory。但是这个请求来自Mallory而非Bob,他不能通过安全认证,因此该请求不会起作用。这时,Mallory 想到使用 CSRF 的攻击方式,他先自己做一个网站,放入如下代码:
<img src="http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory">并且通过广告等诱使 Bob 来访问他的网站。当 Bob 访问该网站时,上述url就会从Bob的浏览器发向银行,而这个请求会附带 Bob 浏览器中的 cookie一起发向银行服务器。大多数情况下,该请求会失败,因为他要求 Bob的认证信息。但是,如果Bob当时恰巧刚访问他的银行后不久,他的浏览器与银行网站之间的session尚未过期,浏览器的cookie之中含有Bob的认证信息。这时,悲剧发生了,这个 url 请求就会得到响应,钱将从 Bob 的账号转移到 Mallory 的账号,而 Bob 当时毫不知情。等以后Bob发现账户钱少了,即使他去银行查询日志,他也只能发现确实有一个来自于他本人的合法请求转移了资金,没有任何被攻击的痕迹。而 Mallory 则可以拿到钱后逍遥法外。

攻击原理

登录受信任网站A,并在本地生成Cookie。
在不登出A的情况下,访问危险网站B。
看到这里,你也许会说:“如果我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:
1. 你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站。
2. 你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了......)
3. 上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。

几种常见的攻击类型

  1. GET类型的Csrf
    这种类型的CSRF一般是由于程序员安全意识不强造成的。GET类型的CSRF利用非常简单,只需要一个HTTP请求,所以,一般会这样利用:

    1. <img src=http://xxx.xxx/del?id=1 /> 大概就是打开这个此代码的网站那个目标网站id为1的数据就可能被删除了,前提是你必须登录了那个目标网站

    在访问含有这个img的页面后,成功向http://xxx.xxx/del?id=1 发出了一次HTTP请求。所以,如果将该网址替换为存在GET型CSRF的地址,就能完成攻击了

  2. POST类型的Csrf
    这种类型的CSRF危害没有GET型的大,利用起来通常使用的是一个自动提交的表单,如:

    1. <form action=http://xxx.xxx/del.php method=POST>
    2. <input type="text" name="id" value="1" />
    3. </form>
    4. <script> document.forms[0].submit(); </script>

    访问该页面后,表单会自动提交,相当于模拟用户完成了一次POST操作。


防御Csrf(跨站请求伪造)的策略

验证 HTTP Referer 字段

根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,比如需要访问: http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory
用户必须先登陆 bank.example,然后通过点击页面上的按钮来触发转账事件。因此,要防御 CSRF 攻击,网站只需要对于每一个转账请求验证其 Referer 值,如果是以 bank.example 开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求。
这种方法的显而易见的好处就是简单易行,网站的普通开发人员不需要操心 CSRF 的漏洞,只需要在最后给所有安全敏感的请求统一增加一个拦截器来检查 Referer 的值就可以

然而,这种方法并非万无一失。Referer 的值是由浏览器提供的,虽然 HTTP 协议上有明确的要求,但是每个浏览器对于 Referer 的具体实现可能有差别,并不能保证浏览器自身没有安全漏洞。使用验证 Referer 值的方法,就是把安全性都依赖于第三方(即浏览器)来保障,从理论上来讲,这样并不安全。事实上,对于某些浏览器,比如IE6 或 FF2,目前已经有一些方法可以篡改 Referer 值。如果 网站支持IE6 浏览器,黑客完全可以把用户浏览器的 Referer 值设为以 bank.example 域名开头的地址,这样就可以通过验证,从而进行 CSRF 攻击。
即便是使用最新的浏览器,黑客无法篡改 Referer 值,这种方法仍然有问题。因为 Referer 值会记录下用户的访问来源,有些用户认为这样会侵犯到他们自己的隐私权,特别是有些组织担心 Referer 值会把组织内网中的某些信息泄露到外网中。因此,用户自己可以设置浏览器使其在发送请求时不再提供 Referer。当他们正常访问银行网站时,网站会因为请求没有 Referer 值而认为是 CSRF 攻击,拒绝合法用户的访问。

在请求地址中添加 token 并验证

在 HTTP 头中自定义属性并验证

防御实例

Sailajs框架中的JavaScript 代码示例

  1. 验证 Referer

    1. // 从 HTTP 头中取得 Referer 值 var
    2. referer=req.headers.Referer;
    3. //判断Referer是否以test.example 开头
    4. if((referer!=null) && (_.startsWith(referer, test.example ”))
    5. {
    6. // 验证通过
    7. }
    8. else{
    9. // 验证失败,返回错误
    10. }
  2. 验证请求中的 token

    1. var session = req.session;
    2. // 从 session 中得到 csrftoken 属性
    3. var token = session.csrftoken;
    4. if(token == null){
    5. token = generateToken();
    6. token.csrftoken = token;
    7. return ....
    8. }
    9. else{
    10. // 从 HTTP 头中取得 csrftoken
    11. var token = req.headers.csrftoken;
    12. // 从请求参数中取得 csrftoken
    13. var xhrToken = req.param('csrftoken');
    14. if(token!=null&&xhrToken!=null&&token.equals(xhrToken)){
    15. return ...
    16. }
    17. else{
    18. return ... // ERROR
    19. }
    20. }

总结

CSRF 是一种危害非常大的攻击,又很难以防范。目前几种防御策略虽然可以很大程度上抵御 CSRF 的攻击,但并没有一种完美的解决方案。一些新的方案正在研究之中,比如对于每次请求都使用不同的动态口令,把 Referer 和 token 方案结合起来,甚至尝试修改 HTTP 规范,但是这些新的方案尚不成熟,要正式投入使用并被业界广为接受还需时日。在这之前,我们只有充分重视 CSRF,根据系统的实际情况选择最合适的策略,这样才能把 CSRF 的危害降到最低

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注