2013年5月27日星期一

浅谈CSRF攻击方式

浅谈CSRF攻击方式

来源:hyddd
一.CSRF是什么?
CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。
二.CSRF可以做什么?
你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账……造成的问题包括:个人隐私泄露以及财产安全。
三.CSRF漏洞现状
CSRF这种攻击方式在2000年已经被国外的安全人员提出,但在国内,直到06年才开始被关注,08年,国内外的多个大型社区和交互网站分别爆出 CSRF漏洞,如:NYTimes.com(纽约时报)、Metafilter(一个大型的BLOG网站),YouTube和百度HI……而现在,互联网 上的许多站点仍对此毫无防备,以至于安全业界称CSRF为“沉睡的巨人”。
四.CSRF的原理
下图简单阐述了CSRF攻击的思想:
浅谈CSRF攻击方式从上图可以看出,要完成一次CSRF攻击,受害者必须依次完成两个步骤:
1.登录受信任网站A,并在本地生成Cookie。
2.在不登出A的情况下,访问危险网站B。
看到这里,你也许会说:“如果我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:
1.你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站。
2.你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了……)
3.上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。
上面大概地讲了一下CSRF攻击的思想,下面我将用几个例子详细说说具体的CSRF攻击,这里我以一个银行转账的操作作为例子(仅仅是例子,真实的银行网站没这么傻:>)
示例1:
银行网站A,它以GET请求来完成银行转账的操作,如:http://www.mybank.com/Transfer.php?toBankId=11&money=1000
危险网站B,它里面有一段HTML的代码如下:
1
<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
首先,你登录了银行网站A,然后访问危险网站B,噢,这时你会发现你的银行账户少了1000块…
为什么会这样呢?原因是银行网站A违反了HTTP规范,使用GET请求更新资源。在访问危险网站B的之前,你已经登录了银行网站A,而B中 的<img>以GET的方式请求第三方资源(这里的第三方就是指银行网站了,原本这是一个合法的请求,但这里被不法分子利用了),所以你的浏 览器会带上你的银行网站A的Cookie发出Get请求,去获取资源“http://www.mybank.com /Transfer.php?toBankId=11&money=1000”,结果银行网站服务器收到请求后,认为这是一个更新资源操作(转账 操作),所以就立刻进行转账操作……
示例2:
为了杜绝上面的问题,银行决定改用POST请求完成转账操作。
银行网站A的WEB表单如下:
1
2
3
4
5
<form action="Transfer.php" method="POST">
    <p>ToBankId: <input type="text" name="toBankId" /></p>
    <p>Money: <input type="text" name="money" /></p>
    <p><input type="submit" value="Transfer" /></p>
  </form>
后台处理页面Transfer.php如下:
1
2
3
4
5
6
7
<?php
    session_start();
    if (isset($_REQUEST['toBankId'] && isset($_REQUEST['money']))
    {
        buy_stocks($_REQUEST['toBankId'], $_REQUEST['money']);
    }
  ?>
危险网站B,仍然只是包含那句HTML代码:
1
<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
和示例1中的操作一样,你首先登录了银行网站A,然后访问危险网站B,结果…..和示例1一样,你再次没了1000块~T_T,这次事故的原因是: 银行后台使用了$_REQUEST去获取请求的数据,而$_REQUEST既可以获取GET请求的数据,也可以获取POST请求的数据,这就造成了在后台 处理程序无法区分这到底是GET请求的数据还是POST请求的数据。在PHP中,可以使用$_GET和$_POST分别获取GET请求和POST请求的数 据。在JAVA中,用于获取请求数据request一样存在不能区分GET请求数据和POST数据的问题。
示例3:
经过前面2个惨痛的教训,银行决定把获取请求数据的方法也改了,改用$_POST,只获取POST请求的数据,后台处理页面Transfer.php代码如下:
1
2
3
4
5
6
7
<?php
    session_start();
    if (isset($_POST['toBankId'] && isset($_POST['money']))
    {
        buy_stocks($_POST['toBankId'], $_POST['money']);
    }
?>
然而,危险网站B与时俱进,它改了一下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<html>
  <head>
    <script type="text/javascript">
      function steal()
      {
               iframe = document.frames["steal"];
               iframe.document.Submit("transfer");
      }
    </script>
  </head>
 
  <body onload="steal()">
    <iframe name="steal" display="none">
      <form method="POST" name="transfer" action="http://www.myBank.com/Transfer.php">
        <input type="hidden" name="toBankId" value="11">
        <input type="hidden" name="money" value="1000">
      </form>
    </iframe>
  </body>
</html>
如果用户仍是继续上面的操作,很不幸,结果将会是再次不见1000块……因为这里危险网站B暗地里发送了POST请求到银行!
总结一下上面3个例子,CSRF主要的攻击模式基本上是以上的3种,其中以第1,2种最为严重,因为触发条件很简单,一个<img>就 可以了,而第3种比较麻烦,需要使用JavaScript,所以使用的机会会比前面的少很多,但无论是哪种情况,只要触发了CSRF攻击,后果都有可能很 严重。
理解上面的3种攻击模式,其实可以看出,CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的!
五.CSRF的防御
我总结了一下看到的资料,CSRF的防御可以从服务端和客户端两方面着手,防御效果是从服务端着手效果比较好,现在一般的CSRF防御也都在服务端进行。
1.服务端进行CSRF防御
服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数。
(1).Cookie Hashing(所有表单都包含同一个伪随机值):
这可能是最简单的解决方案了,因为攻击者不能获得第三方的Cookie(理论上),所以表单中的数据也就构造失败了:>
1
2
3
4
5
<?php
    //构造加密的Cookie信息
    $value = “DefenseSCRF”;
    setcookie(”cookie”, $value, time()+3600);
?>
在表单里增加Hash值,以认证这确实是用户发送的请求。
1
2
3
4
5
6
7
8
9
<?php
    $hash = md5($_COOKIE['cookie']);
  ?>
  <form method=”POST” action=”transfer.php”>
    <input type=”text” name=”toBankId”>
    <input type=”text” name=”money”>
    <input type=”hidden” name=”hash” value=”<?=$hash;?>”>
    <input type=”submit” name=”submit” value=”Submit”>
  </form>
然后在服务器端进行Hash值验证
1
2
3
4
5
6
7
8
9
10
11
12
<?php
        if(isset($_POST['check'])) {
             $hash = md5($_COOKIE['cookie']);
             if($_POST['check'] == $hash) {
                  doJob();
             } else {
        //...
             }
        } else {
      //...
        }
      ?>
这个方法个人觉得已经可以杜绝99%的CSRF攻击了,那还有1%呢….由于用户的Cookie很容易由于网站的XSS漏洞而被盗取,这就另外的1%。一般的攻击者看到有需要算Hash值,基本都会放弃了,某些除外,所以如果需要100%的杜绝,这个不是最好的方法。
(2).验证码
这个方案的思路是:每次的用户提交都需要用户在表单中填写一个图片上的随机字符串,厄….这个方案可以完全解决CSRF,但个人觉得在易用性方面似乎不是太好,还有听闻是验证码图片的使用涉及了一个被称为MHTML的Bug,可能在某些版本的微软IE中受影响。
(3).One-Time Tokens(不同的表单包含一个不同的伪随机值)
在实现One-Time Tokens时,需要注意一点:就是“并行会话的兼容”。如果用户在一个站点上同时打开了两个不同的表单,CSRF保护措施不应该影响到他对任何表单的提 交。考虑一下如果每次表单被装入时站点生成一个伪随机值来覆盖以前的伪随机值将会发生什么情况:用户只能成功地提交他最后打开的表单,因为所有其他的表单 都含有非法的伪随机值。必须小心操作以确保CSRF保护措施不会影响选项卡式的浏览或者利用多个浏览器窗口浏览一个站点。
以下我的实现:
1).先是令牌生成函数(gen_token()):
1
2
3
4
5
6
7
<?php
     function gen_token() {
    //这里我是贪方便,实际上单使用Rand()得出的随机数作为令牌,也是不安全的。
    //这个可以参考我写的Findbugs笔记中的《Random object created and used only once》
          $token = md5(uniqid(rand(), true));
          return $token;
     }
2).然后是Session令牌生成函数(gen_stoken()):
1
2
3
4
5
6
7
8
9
10
11
12
<?php
       function gen_stoken() {
      $pToken = "";
      if($_SESSION[STOKEN_NAME]  == $pToken){
        //没有值,赋新值
        $_SESSION[STOKEN_NAME] = gen_token();
      }   
      else{
        //继续使用旧的值
      }
       }
     ?>
3).WEB表单生成隐藏输入域的函数:
1
2
3
4
5
6
7
<?php
       function gen_input() {
            gen_stoken();
            echo “<input type=\”hidden\” name=\”" . FTOKEN_NAME . “\”
                 value=\”" . $_SESSION[STOKEN_NAME] . “\”> “;
       }
     ?>
4).WEB表单结构:
1
2
3
4
5
6
7
8
9
10
<?php
          session_start();
          include(”functions.php”);
     ?>
     <form method=”POST” action=”transfer.php”>
          <input type=”text” name=”toBankId”>
          <input type=”text” name=”money”>
          <? gen_input(); ?>
          <input type=”submit” name=”submit” value=”Submit”>
     </FORM>
5).服务端核对令牌:
这个很简单,这里就不再啰嗦了。
上面这个其实不完全符合“并行会话的兼容”的规则,大家可以在此基础上修改。

其实还有很多想写,无奈精力有限,暂且打住,日后补充,如果错漏,请指出:>
PS:今天下午写这篇文档的时候FF崩溃了一次,写了一半文章的全没了,郁闷好久T_T…….
转载请说明出处,谢谢[hyddd(http://www.cnblogs.com/hyddd/)]
六.参考文献
[1].Preventing CSRF
[2].Security Corner: Cross-Site Request Forgeries
[3].《深入解析跨站请求伪造漏洞:原理剖析》
[4].《Web安全测试之跨站请求伪造(CSRF)》
[5].《深入解析跨站请求伪造漏洞:实例讲解》
[6].http://baike.baidu.com/view/1609487.htm

浅谈CSRF

一、什么是CSRF
先看看CSRF的原文说明,如下:
Cross Site Reference Forgery works by including malicious code or a link in a page that accesses a web application that the user is believed to have authenticated. If the session for that web application has not timed out, an attacker may execute unauthorized commands.

二、CSRF案例说明和分析
自然,这里拿Rails程序来举例子说明这些问题,大家知道Rails2之 前是把session放在服务器端(文件或者DB或者缓存中),客户端在cookie中保存sessionid;而到了Rails2后,还有一种方式是把 session放在基于cookie的客户端中。当然这两样都各有道理,各有优劣。当我们向一个域名发送一个请求的时候,如果存在这个域名的 cookie,浏览器会自动把cookie附带上。这样本来没有啥问题,也是我们为了解决http无状态记录的解决方案,但是有个问题出现了,如果出现一 个到其他域名的请求,浏览器在加载的时候,也把cookie给带上了,会有什么问题?我们举个简单的也很常见的例子来说明这个问题。
1、Bob在自己的电脑上刚刚查看完自己的银行A账户余额,然后比较无聊就跑到一个公开的BBS上灌水,当他看到一篇“银行A的内部照片”的帖子,很有兴趣的打开这个帖子想看看自己信任的银行A的内部图片是啥样子的,殊不知,这其实是一个attacker精心设计的骗局。
2、在这个帖子中确实有几个图片,看上去真的像是银行A的照片,但是其中有个图片没显示出来,Bob以为是自己网速太慢,导致这个图片没有加载进来,也没在意。只是对这些并不是十分满意的照片摇摇头,就关了这个帖子。
3、几天后,Bob猛然发现自己在银行A的账户上少了1000元,到底是怎么了?
分析:
为什么钱少了呢?我们得分析一下上面这个案例,还记得当时Bob说有个图片没显示么,是的,我们来看看这个图片的地址,惊奇的发现是:<img .src="http://www.banka.com/transfer?account=myself&amount=1000&destination=attacker">,这是一个什么地址?聪明的您一定很快就能明白,这个地址是邪恶的,看上去,他的意思是打开这个地址的人,给attacker转了1000元。
这 怎么可能?你肯定急了,我怎么能随便给一个人转1000元呢,而且我都不知道呀!但是,注意了,这其实是完全有可能的。还记得当时Bob刚刚查看完帐号信 息,基于银行A的cookie并不过期,当出现如上链接出现在src的时候(note that .src is meant to be src),浏览器尝试着按照本地的cookie去加载上面这个URL,而银行A验证了来源请求的cookie是可以的,所以就这样事情就悄悄的发生了。
ok, 看明白了么,这就是CSRF,一句话给他下个定义就是:借你的cookie在你不知道的时候悄悄的做了一些你不愿意做的事情。这里有个更要命的是,这个包 含上述URL的图片或者链接,并不需要一定是放在银行A的服务器上,相反可以在任一地方,比如blog,公开的BBS,或者一些群发的Mail中等等,如 此多的场合下,这些都有可能存在陷阱。

三、CSRF的预防看上去很恐怖吧,是的,确实恐怖,意识到恐怖是个好事情,这样会促使你接着往下看如何改进和防止类似的漏洞出现。
总体来说,预防CSRF主要从2个方面入手,分别是:
1、正确使用GET,POST和Cookie;
2、在non-GET请求中使用Security token;
一般,大家知道的浏览器发送请求的方式有GET或者POST,但是还有一种比较常用的是Cookie,至于其他的HTTP协议请求方式,你可以google,一般按照W3C的规范:
1、GET常用在查看,列举,展示的时候;
2、POST常用在下达订单,改变一个资源的属性或者做其他一些事情;
ok,我们这里拿Rails按照前面列举的2种预防手段做说明,首先,我们可以在Rails的控制器中(controller)将一些方法(action)限定(verify)为只能使用POST或者GET,例如:
Ruby代码  收藏代码
  1. verify :method => :post:only => [ :transfer ], :redirect_to => { :action => :list }   

恩,很好,这样做下限制以后,前面案例中的方法就失效了,因为这里我们限定了transfer必须使用POST来提交请求,当GET请求来的时候并不会被响应。
万事大吉了?NO!因为POST的请求也是可以被构造出来后自动发送的,如何实现,看下面吧,你肯定会吃惊的。
Html代码  收藏代码
  1. <a .href="http://www.1sters.com/" onclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = 'http://www.example.com/account/destroy'; f.submit();return false;">点我试试</a>   

是的,这就是一个活生生的例子(.href is meant to be href),使用link的href或者img的src都可以,再想想一个Attacher放了一个图片,然后写了一个onmouseover方法,执行上述的那段JS,如下,或者使用AJAX。
Html代码  收藏代码
  1. <img .src="http://www.harmless.com/img" width="400" height="400" onmouseover="…" />  

所以,限定为POST后还不是非常的保险,怎么办?不急,我们还有第二步,给non-GET的请求设置security token,如何实现,在Rails2以后非常简单(也是默认的),我们只需要在environment.rb中添加如下代码:
Ruby代码  收藏代码
  1. config.action_controller.session = {     
  2.   :session_key => '_csrf_session',     
  3.   :secret      => 'ae4b43dda38ff78bb50898b2935da76d1e224061ab72a9399d34cea4c6178eee6dae815fff920a20642f27abda83b793da4e9b6cf20c4838805e80abf53e318a'     
  4. }  
 然后在application controller中包含如下security token设置:
Ruby代码  收藏代码
  1. protect_from_forgery  :secret => 'ae4b43dda38ff78bb50898b2935da76d1e224061ab72a9399d34cea4c6178eee6dae815fff920a20642f27abda83b793da4e9b6cf20c4838805e80abf53e318a'   

ok,基本上安全了,如果这时POST请求过去,但是security token和session计算出来的secret和服务端的secret匹配不上的话,就会返回一个 ActionController::InvalidAuthenticityToken错误,防止该类缺陷的出现。
安全了,也许你要说,那我如果能破解出protect_from_forgery,不就OK了么,按照理论上是,但是实际破解是基本上不可能的,因为有人曾计算过,暴力破解该串大概需要2的11次方时间。
分享到:

CSRF

CSRF

百科名片

CSRF  
CSRF
CSRF(Cross-site request forgery跨站请求伪造,也被称成为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS), 但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击 相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。

编辑本段示例特性

攻 击通过在授权用户访问的页面中包含链接或者脚本的方式工作。例如:一个网站用户Bob可能正在浏览聊天论坛,而同时另一个用户Alice也在此论坛中,并 且后者刚刚发布了一个具有Bob银行链接的图片消息。设想一下,Alice编写了一个在Bob的银行站点上进行取款的form提交的链接,并将此链接作为 图片tag。如果Bob的银行在cookie中保存他的授权信息,并且此cookie没有过期,那么当Bob的浏览器尝试装载图片时将提交这个取款 form和他的cookie,这样在没经Bob同意的情况下便授权了这次事务。
CSRF
CSRF(17张)
CSRF是一种依赖web浏览器的、被混淆过的代理人攻击(deputy attack)。在上面银行示例中的代理人是Bob的web浏览器,它被混淆后误将Bob的授权直接交给了Alice使用。
下面是CSRF的常见特性:
依靠用户标识危害网站
利用网站对用户标识的信任
欺骗用户的浏览器发送HTTP请求给目标站点
另外可以通过IMG标签会触发一个GET请求,可以利用它来实现CSRF攻击。

编辑本段风险提示

风险在于那些通过基于受信任的输入form和对特定行为无需授权的已认证的用户来执行某些行为的web应用。已经通过被保存在用户浏览器中的cookie进行认证的用户将在完全无知的情况下发送HTTP请求到那个信任他的站点,进而进行用户不愿做的行为。
使用图片的CSRF攻击常常出现在网络论坛中,因为那里允许用户发布图片而不能使用JavaScript。

编辑本段相关威胁

贴图只是GET的方式,很多时候我们需要伪造POST的请求。一个办法是利用跨站,当然目标站点可能不存在跨站,这个时候我们可以从第三方网站发动攻击。
比如我要攻击一个存在问题的blog,那就先去目标blog留言,留下一个网址,诱其主人点击过来(这个就要看你的忽悠本事咯:p),然后构造个HTML表单提交些数据过去。
多窗口浏览器就帮了一点忙。
多窗口浏览器(firefox、遨游、MyIE……)便捷的同时也带来了一些问题,因为多窗口浏览器新开的窗口是具 有当前所有会话的。即我用IE登陆了我的Blog,然后我想看新闻了,又运行一个IE进程,这个时候两个IE窗口的会话是彼此独立的,从看新闻的IE发送 请求到Blog不会有我登录的cookie;但是多窗口浏览器永远都只有一个进程,各窗口的会话是通用的,即看新闻的窗口发请求到Blog是会带上我在 blog登录的cookie。
想一想,当我们用鼠标在Blog/BBS/WebMail点击别人留下的链接的时候,说不定一场精心准备的CSRF攻击正等着我们。flash文件(ActionScript3.0),在默认的图层上点右键选动作,然后把以下代码添加进去。

编辑本段防范措施

对于web站点,将持久化的授权方法(例如cookie或者HTTP授权)切换为瞬时的授权方法(在每个form中提供隐藏field),这将帮助网站防止这些攻击。一种类似的方式是在form中包含秘密信息、用户指定的代号作为cookie之外的验证。
另一个可选的方法是“双提交”cookie。此方法只工作于Ajax请求,但它能够作为无需改变大量form的全局 修正方法。如果某个授权的cookie在form post之前正被JavaScript代码读取,那么限制跨域规则将被应用。如果服务器需要在Post请求体或者URL中包含授权cookie的请求,那 么这个请求必须来自于受信任的域,因为其它域是不能从信任域读取cookie的。
与通常的信任想法相反,使用Post代替Get方法并不能提供卓有成效的保护。因为JavaScript能使用伪造 的POST请求。尽管如此,那些导致对安全产生“副作用”的请求应该总使用Post方式发送。Post方式不会在web服务器和代理服务器日志中留下数据 尾巴,然而Get方式却会留下数据尾巴。
尽管CSRF是web应用的基本问题,而不是用户的问题,但用户能够在缺乏安全设计的网站上保护他们的帐户:通过在浏览其它站点前登出站点或者在浏览器会话结束后清理浏览器的cookie。

编辑本段影响因素

CSRF攻击依赖下面的假定:
攻击者了解受害者所在的站点
攻击者的目标站点具有持久化授权cookie或者受害者具有当前会话cookie
目标站点没有对用户在网站行为的第二授权

浅谈CSRF攻击方式


浅谈CSRF攻击方式

2009-04-09 22:44 by hyddd, 21102 阅读, 40 评论, 收藏, 编辑 一.CSRF是什么?
  CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。
二.CSRF可以做什么?
  你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账......造成的问题包括:个人隐私泄露以及财产安全。
三.CSRF漏洞现状
  CSRF这种攻击方式在2000年已经被国外的安全人员提出,但在国内,直到06年才开始被关注,08年,国内外的多个大型社区和交互网站分别 爆出CSRF漏洞,如:NYTimes.com(纽约时报)、Metafilter(一个大型的BLOG网站),YouTube和百度HI......而 现在,互联网上的许多站点仍对此毫无防备,以至于安全业界称CSRF为“沉睡的巨人”。
四.CSRF的原理
  下图简单阐述了CSRF攻击的思想:
  
  从上图可以看出,要完成一次CSRF攻击,受害者必须依次完成两个步骤
  1.登录受信任网站A,并在本地生成Cookie
  2.在不登出A的情况下,访问危险网站B
  看到这里,你也许会说:“如果我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:
  1.你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站。
  2.你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了......)
  3.上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。

  上面大概地讲了一下CSRF攻击的思想,下面我将用几个例子详细说说具体的CSRF攻击,这里我以一个银行转账的操作作为例子(仅仅是例子,真实的银行网站没这么傻:>)
  示例1:
  银行网站A,它以GET请求来完成银行转账的操作,如:http://www.mybank.com/Transfer.php?toBankId=11&money=1000
  危险网站B,它里面有一段HTML的代码如下:
  <img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
首先,你登录了银行网站A,然后访问危险网站B,噢,这时你会发现你的银行账户少了1000块......
  为什么会这样呢?原因是银行网站A违反了HTTP规范,使用GET请求更新资源。在访问危险网站B的之前,你已经登录了银行网站A,而B中 的<img>以GET的方式请求第三方资源(这里的第三方就是指银行网站了,原本这是一个合法的请求,但这里被不法分子利用了),所以你的浏 览器会带上你的银行网站A的Cookie发出Get请求,去获取资源“http://www.mybank.com /Transfer.php?toBankId=11&money=1000”,结果银行网站服务器收到请求后,认为这是一个更新资源操作(转账 操作),所以就立刻进行转账操作......
  示例2:
  为了杜绝上面的问题,银行决定改用POST请求完成转账操作。
  银行网站A的WEB表单如下:  
  <form action="Transfer.php" method="POST">
    <p>ToBankId: <input type="text" name="toBankId" /></p>
    <p>Money: <input type="text" name="money" /></p>
    <p><input type="submit" value="Transfer" /></p>
  </form>
后台处理页面Transfer.php如下:
复制代码
  <?php    session_start();    if (isset($_REQUEST['toBankId'&& isset($_REQUEST['money']))
    {
        buy_stocks(
$_REQUEST['toBankId'], $_REQUEST['money']);
    }
  ?>
复制代码
危险网站B,仍然只是包含那句HTML代码:
  <img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
和示例1中的操作一样,你首先登录了银行网站A,然后访问危险网站B,结果.....和示例1一样,你再次没了1000块~T_T,这次事故的 原因是:银行后台使用了$_REQUEST去获取请求的数据,而$_REQUEST既可以获取GET请求的数据,也可以获取POST请求的数据,这就造成 了在后台处理程序无法区分这到底是GET请求的数据还是POST请求的数据。在PHP中,可以使用$_GET和$_POST分别获取GET请求和POST 请求的数据。在JAVA中,用于获取请求数据request一样存在不能区分GET请求数据和POST数据的问题。
  示例3:
  经过前面2个惨痛的教训,银行决定把获取请求数据的方法也改了,改用$_POST,只获取POST请求的数据,后台处理页面Transfer.php代码如下:
复制代码
  <?php
    
session_start();
    
if (isset($_POST['toBankId'&& isset($_POST['money']))
    {
        buy_stocks(
$_POST['toBankId'], $_POST['money']);
    }
  
?>
复制代码
然而,危险网站B与时俱进,它改了一下代码:
复制代码
<html>
  <head>
    <script type="text/javascript">
      function steal()
      {
               iframe 
= document.frames["steal"];
               iframe.document.Submit(
"transfer");
      }
    </script>
  </head>

  
<body onload="steal()">
    <iframe name="steal" display="none">
      <form method="POST" name="transfer" action="http://www.myBank.com/Transfer.php">
        
<input type="hidden" name="toBankId" value="11">
        
<input type="hidden" name="money" value="1000">
      
</form>
    </iframe>
  </body>
</html>
复制代码
如果用户仍是继续上面的操作,很不幸,结果将会是再次不见1000块......因为这里危险网站B暗地里发送了POST请求到银行!
  总结一下上面3个例子,CSRF主要的攻击模式基本上是以上的3种,其中以第1,2种最为严重,因为触发条件很简单,一 个<img>就可以了,而第3种比较麻烦,需要使用JavaScript,所以使用的机会会比前面的少很多,但无论是哪种情况,只要触发了 CSRF攻击,后果都有可能很严重。
  理解上面的3种攻击模式,其实可以看出,CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的
五.CSRF的防御
  我总结了一下看到的资料,CSRF的防御可以从服务端客户端两方面着手,防御效果是从服务端着手效果比较好,现在一般的CSRF防御也都在服务端进行。
  1.服务端进行CSRF防御
  服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数
  (1).Cookie Hashing(所有表单都包含同一个伪随机值):
  这可能是最简单的解决方案了,因为攻击者不能获得第三方的Cookie(理论上),所以表单中的数据也就构造失败了:>
  <?php    //构造加密的Cookie信息
    $value = “DefenseSCRF”;    setcookie(”cookie”, $value, time()+3600);  ?>
在表单里增加Hash值,以认证这确实是用户发送的请求。
复制代码
  <?php
    $hash = md5($_COOKIE['cookie']);  ?>
  <form method=”POST” action=”transfer.php”>
    <input type=”text” name=”toBankId”>
    <input type=”text” name=”money”>
    <input type=”hidden” name=”hash” value=<?=$hash;?>>
    <input type=”submit” name=”submit” value=”Submit”>
  </form>
复制代码
然后在服务器端进行Hash值验证
复制代码
      <?php        if(isset($_POST['check'])) {
            
$hash = md5($_COOKIE['cookie']);
             if($_POST['check'== $hash) {
                  doJob();
             } 
else {
        //...

             }
        } 
else {
      //...

        }
      
?>
复制代码
这个方法个人觉得已经可以杜绝99%的CSRF攻击了,那还有1%呢....由于用户的Cookie很容易由于网站的XSS漏洞而被盗取,这就 另外的1%。一般的攻击者看到有需要算Hash值,基本都会放弃了,某些除外,所以如果需要100%的杜绝,这个不是最好的方法。
  (2).验证码
  这个方案的思路是:每次的用户提交都需要用户在表单中填写一个图片上的随机字符串,厄....这个方案可以完全解决CSRF,但个人觉得在易用性方面似乎不是太好,还有听闻是验证码图片的使用涉及了一个被称为MHTML的Bug,可能在某些版本的微软IE中受影响。
  (3).One-Time Tokens(不同的表单包含一个不同的伪随机值)
  在实现One-Time Tokens时,需要注意一点:就是“并行会话的兼容”。如果用户在一个站点上同时打开了两个不同的表单,CSRF保护措施不应该影响到他对任何表单的提 交。考虑一下如果每次表单被装入时站点生成一个伪随机值来覆盖以前的伪随机值将会发生什么情况:用户只能成功地提交他最后打开的表单,因为所有其他的表单 都含有非法的伪随机值。必须小心操作以确保CSRF保护措施不会影响选项卡式的浏览或者利用多个浏览器窗口浏览一个站点。
  以下我的实现:
  1).先是令牌生成函数(gen_token()):
复制代码
     <?php
     function gen_token() {     //这里我是贪方便,实际上单使用Rand()得出的随机数作为令牌,也是不安全的。
    //这个可以参考我写的Findbugs笔记中的《Random object created and used only once》
          $token = md5(uniqid(rand(), true));
          
return $token;
     }
复制代码
2).然后是Session令牌生成函数(gen_stoken()):
复制代码
     <?php
     
  function gen_stoken() {      $pToken = "";
      if($_SESSION[STOKEN_NAME]  == $pToken){
        //没有值,赋新值
      
  $_SESSION[STOKEN_NAME] = gen_token();
      }   
      else{
        //继续使用旧的值
      }

       }
     
?>
复制代码
3).WEB表单生成隐藏输入域的函数:  
复制代码
     <?php
       function gen_input() {
            gen_stoken();
            echo “<input type=\”hidden\” name=\”" . FTOKEN_NAME . “\”
                 value=\”" . $_SESSION[STOKEN_NAME] . “\”> “;
       }
     ?>
复制代码
4).WEB表单结构:
复制代码
     <?php
          
session_start();
          
include(”functions.php”);
     
?>
     
<form method=”POST” action=”transfer.php”>
          
<input type=”text” name=”toBankId”>
          
<input type=”text” name=”money”>
          
<? gen_input(); ?>
          
<input type=”submit” name=”submit” value=”Submit”>
     
</FORM>
复制代码
5).服务端核对令牌:
  这个很简单,这里就不再啰嗦了。
  上面这个其实不完全符合“并行会话的兼容”的规则,大家可以在此基础上修改。

  其实还有很多想写,无奈精力有限,暂且打住,日后补充,如果错漏,请指出:>
  PS:今天下午写这篇文档的时候FF崩溃了一次,写了一半文章的全没了,郁闷好久T_T.......
  转载请说明出处,谢谢[hyddd(http://www.cnblogs.com/hyddd/)]

跨站请求伪造(CSRF)接触

跨站请求伪造(CSRF)接触

(2012-01-19 12:02:47)
标签:

it

分类: web
     跨站请求伪造(即CSRF)被WEB安全界称为诸多漏洞中“沉睡的巨人”,其威胁程度由此“美誉”便可见一般。本文将简单介绍该漏洞,并详细说明造成这种漏洞的原因所在,以及针对该漏洞的黑盒测试与灰盒子测试具体方法和示例。 一、CSRF概述
    跨站请求伪造(CSRF)是一种挟制终端用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。攻击者只要借助少许的社会工程诡计,例如通过电 子邮件或者是聊天软件发送的链接,攻击者就能迫使一个Web应用程序的用户去执行攻击者选择的操作。例如,如果用户登录网络银行去查看其存款余额,他没有退出网络银行系统就去了自己喜欢的论坛去灌水,如果攻击者在论坛中精心构造了一个恶意的链接并诱使该用户点击了该链接,那么该用户在网络银行帐户中的资金就有可能被转移到攻击者指定的帐户中。
   当CSRF针对普通用户发动攻击时,将对终端用户的数据和操作指令构成严重的威胁;当受攻击的终端用户具有管理员帐户的时候,CSRF攻击将危及整个Web应用程序。
二、造成CSRF的原因
    跨站请求伪造能否得逞,与以下几个方面密不可分,分别是浏览器对会话的处理,攻击者对Web应用有关URL的了解,应用程序赖以管理会话的信息对浏览器的透明性以及各种能够引发资源请求HTML标签等。下面分别加以解释。
    首先,我们来了解一些Web浏览器对于Cookie和HTTP身份验证信息之类的会话信息的处理方式。目前,浏览器会自动地发送标识用户对话的信息,而无 需用户干预,换句话说,当浏览器发送这些身份信息的时候,用户根本感觉不到。假设站点A上有一个Web应用程序,并且受害者正好已经在该站点上通过了身份 认证,这时,站点会向受害者发送一个cookie作为响应,这个cookie的作用是什么呢?主要是被站点作为用户会话的标志,即如果站点收到了带有受害 者的cookie的请求,那么它就会把这个请求看作是已登录的受害者发来的。一般情况下,浏览器收到站点设置的cookie之后,每当向该站点发送请求的时候,浏览器都会“自动地”连同该cookie一起发出。
     然后,我们再来讨论一下攻击者对Web应用程序URL的了解。如果应用程序没有在URL中使用跟会话有关的信息的话,那么通过代码分析或者通过访问该应用程序并查看嵌入HTML/JavaScript中的URL以及表单来了解应用程序有关的URL、参数和容许值。
     接下来,讨论一下应用程序赖以管理会话的信息对浏览器的透明性问题。我们知道,为了提高Web应用的便利性,用来管理会话的信息,例如Cookie或者基 于HTTP的身份验证(例如HTTP基本认证、非基于表单的认证)等敏感信息,都是由浏览器来存放的,并在每当向需要身份验证的应用程序发送请求时自动捎 带上这些信息。也就是说,浏览器可以访问会话管理信息,如果Web应用程序完全依赖于这类信息来识别一个用户会话,这就为跨站请求伪造创造了条件。
      上面所说的三个因素,是跨站请求伪造攻击的必要的条件,而下面所说的,是一个“锦上添花”的因素,即没有它也能发动跨站请求伪造攻击,但是有了它能使该攻击更加容易。这就是存在多种HTML标签,如果页面内出现这些标签,会立刻引起浏览器对http[s]资源的访问,例如图像标签img便是其中之一。
      GET方式的URL(不过这里讨论的内容同样适用于POST请求)。如果受害者已经通过身份验证,那么当他提交其它请求时,该cookie也会自动地随之发送。 
      那么,什么情况下会引起发送这个GET请求呢?这可就有多种可能了,首先当用户正常使用该Web应用程序的过程中有可能引发这个GET请求;其次,当用户 直接在浏览器地址栏中键入该URL时也会引发该GET请求;再者,用户单击了指向该URL的链接,即使该链接位于该应用程序外部,也会引发该GET请求。
    对于应用程序来说,它是无法区分上面的这些差别的。特别是第三种可能是非常危险的。有许多技术(和漏洞)可以隐藏一个链接的真实属性。链接可以嵌入电子邮件消息中,也可以出现在存心不良的Web站点,然后引诱用户浏览该站点,例如链接出现在位于其他主机上(其它Web 站点、HTML格式的电子邮件消息,等等)的内容中,并且指向应用程序的资源。如果用户单击了该链接,由于他已经通过了站点上Web 应用程序的认证,所以浏览器就会发出一个GET请求给该Web 应用程序,同时将验证信息(包含会话id的cookie)一并发过去。这样会导致在Web 应用程序上执行一个有效操作——该操作可能不是该用户所想要的,例如一个引起在网络银行上进行转帐恶意的链接,等等。
     如前所述,通过使用诸如img之类的标签,甚至不需要用户点击具体的链接就能发动攻势。假设攻击者向用户发送了一封电子邮件,诱骗用户访问一个URL,而该URL则指向一个包含下列HTML内容的页面:
[html][body]
...
(img src=”https://www.company.example/action” width=”0” height=”0”)
...
[/body][/html]用时将[]换成<>
     当浏览器显示该页面时,它也将设法显示这个指定宽度为0的图像,即该图像是不可见的——这会导致自动向站点中的Web 应用程序发送一个请求。要紧的是,浏览器不管该图像URL实际是否指向一个图片,只要src字段中规定了URL,就会按照该地址触发一个请求。当然,这里有一个前提,那就是浏览器没有禁止下载图像——实际上浏览器都配置成允许下载图像,因为禁用图像后大多数Web应用程序的可用性就会大打折扣。与跨站请求伪造有关的HTML标签问题是总结如下:
    页面中有许多标签会导致自动发出HTTP请求(img标签便是其中之一);
    浏览器无法断定img标签所引用的资源到底是不是图像以及是否是有害的;
当加载图像时,根本就不考虑所涉及的图像所在的位置,即表单和图像不必位于同一个主机上,甚至可以不再同一个域内。虽然这是一个非常便利的特性,但是却给应用程序的隔离制造的障碍。正是由于与Web 应用程序无关的HTML内容可以引用应用程序中的各种组件,以及浏览器可以自动为该应用程序构造一个有效的请求这两个事实才导致了这种攻击的出现。这意味着,正确的URL必须包含用户会话有关的信息,而攻击者却无法得知这些信息,因此不可能识别这样的URL。
     对于集成了邮件/浏览器功能的工作平台,跨站请求伪造问题可能更为严重,因为,仅仅显示一封包含该图像的电子邮件就会导致请求及有关浏览器cookie一起向Web应用程序发去。
      另外,攻击者还可以对这些东西进行伪装,例如引用貌似合法的图像URLs,例如:
    (img src=”https://[attacker]/picture.gif” width=”0” height=”0”)用时将()换成<>
     这里,[attacker]是攻击者控制下的站点,并通过重定向机制将http://[attacker ]/picture. gif转向http://[thirdparty ]/action。
     如果Web应用程序的会话信息完全靠浏览器来提供的话,那么这样的Web应用程序也都易于受到攻击,其中包括那些仅依赖于HTTP身份验证机制的那些应用 程序,因为浏览器知道这些验证信息,并会在发送每个请求的时候自动附带这些验证信息。当然,这不包括基于表单的认证,它只发出一次,并且生成了有关会话信 息的表单——当然,如果这样的信息就像cookie那样进行简单的传递的话,这就有回到了之前的情形。

三、跨站请求伪造情景分析
    假如受害者已经登录到一个防火墙的Web管理应用程序上。我们知道,当用户登录时,Web应用会进行身份验证,通常是要求用户提供其用户名和密码,如果用户名和密码正确则会通过身份认证;随后,Web应用会在客户端存放一个小文本文件,即cookie来存放会话信息。
     假设防火墙有一个基于Web的管理接口,我们称之为防火墙Web管理程序,其中具有一个这样功能或者说一个页面,即允许认证的用户通过规则编号删除指定的 规则,或者通过输入“*”删除全部已配置的规则——这的确是一个非常危险的功能。该删除页面显示如下。假如该表单(我们已经对其进行了简化)引起一个 GET请求,那么该请求将如下所示
 https://[target]/fwmgt/delete?rule=1
(删除一号规则)
https://[target]/fwmgt/delete?rule=*
(删除全部规则)。
     该范例是故意十分天真的,这是为了便于说明CSRF的危险性。
     因此,如果我们键入值“*”,并按下删除按钮,就会提交下列GET请求:
     https://www.company.example/fwmgt/delete?rule=* 
   其结果就是删除所有防火墙规则
    实际上,这并非唯一可能的情形。用户也可以手动提交URLhttps://[target ]/fwmgt /delete ?Rule =*来达到相同的效果。或者通过单击一个直接指向以上URL的链接或通过重定向到达以上URL的链接。或者同样也可访问一个嵌入了指向相同的URL的img标签的HTML页面。在这些情况下,如果用户当前已经登录到防火墙管理程序,那么该请求将得逞并会修改防火墙的配置。
     此外,我们还可以设想攻击是针对敏感的应用程序、进行自动的拍卖投标、转帐、订货、改变关键软件组件的配置等等。
    更有趣的是,这些漏洞都可以在防火墙之后进行利用,即只要被攻击的链接是受害者所能访问的即可,而不必非得攻击者能够直接访问才行。
   尤其是,它可以是任何内部网Web服务器,例如,之前提到的防火墙管理工作站,它大不可能暴露于国际互联网。 对于那些既可以用作攻击矢量,有是攻击目标的应用程序(例如web邮件应用程序),情况就更糟了:如果这样的应用程序是易受攻击的,那么用户阅读包含 CSRF攻击的信件时很明显已经登录到程序了,它会以web邮件应用程序为目标,并让邮件应用程序执行删除信件、发送消息等动作,而这些动作看起来将像是 用户本身所做的。
四、黑盒子测试
    为了进行黑盒测试,需要知道受限制的(认证的)区域的URL。如果您具有有效证书,那么就可以扮演攻击者和受害者这两种角色了。在这种情况下,仅仅通过浏 览应用程序您能获悉受测试的有关URLs。否则,如果没有有效的证书可用的话,必须组织一个实际的攻击,以引诱一个合法的已登录的用户来点击某个适当的链 接,这可以通过社会工程来进行。
   不管怎样,测试案例可以如下构造:
   把u改成受测的URL,例如u=http://www.example.com/action
   构造一个HTML页面,让它包含引用url u(规定全部相关参数;使用GET方式的时候很简单,如果使用的是POST请求,则需要诉诸于一些JavaScript代码)的HTTP请求;
   确保合法的用户已经登录该应用程序;引诱他点击一个链接,而该链接指向受测试的URL(如果你无法冒充用户的话,则需要借助于社会工程);
观察结果,如检测Web服务器是否执行了该请求。
五、灰盒子测试
    对应用程序进行安全评估的时候,要调查其会话管理是否是易受攻击的。如果会话管理完全依赖于客户端的值(即对于浏览器来说也是可用的),那么该应用程序是 易受攻击的。通过这些客户端的值,我们就弄明白了Cookie和HTTP认证证书(基本认证及其他形式的HTTP认证;不是基于表单的认证,即应用程序级 别的认证)。对于没有此弱点的应用程序来说,它在URL中必须包括跟会话session有关信息,并且要采取一种令用户无法辨认或者不可预见的形式 ([3]使用术语secret来表示这种信息单元)。
     可以经由HTTP的GET请求访问的资源很容易受弱点的影响,但是POST请求可以通过JavaScript实行自动化,并且也易于受到攻击;因此,单独使用POST不足以防止CSRF漏洞的发生。
六、跨站请求伪造对策
    跨站请求伪造的危害非常之大,所以无论是用户还是开发人员都应该引起足够的重视,下面是给Web应用程序终端用户和Web应用程序开发人员的一些有用的建议。
用户
   因为CSRF漏洞有流行之趋势,所以建议用户遵循最佳实践来降低风险,可以降低风险的习惯包括:
   使用Web应用程序之后立即登出
    不要让浏览器保存用户名/口令,也不要让站点“记住”您不要使用同一个浏览器同时访问敏感的应用程序和随意冲浪;如果必须同时做多件事情的话,最好单独使用不同的浏览器。
    对于支持HTM格式邮件/浏览器集成是式软件以及集成了新闻阅读程序/浏览器的软件都会带来额外的风险,因为只要查看邮件或者新闻就有可能被迫执行一次攻击,所以使用这类软件时格外小心。
开发人员
     开发人员应当向URL添加跟会话有关信息。该攻击类型之所以得逞,是因为会话是由cookie唯一标识的,并且该cookie是由浏览器自动发送的。
    如果我们在URL级别为会话生成其它相关信息,那么就会给攻击者为发动攻击而了解URL的结构造成更多的障碍。
    至于其它的对策,虽然也无法解决该问题,但是能够使得利用该漏洞更加困难,例如使用POST而不是GET。虽然POST请求可以通过JavaScript 进行模仿,但是它提高了发动这种攻击的难度。使用中间确认页也能带来相同的效果,比如“您确信要这样做吗?”之类的页面。虽然攻击者可以绕过这些措施,但 是这些措施提供了实施攻击的难度。因此,不能完全依赖这些手段来保护您的应用程序。自动登出机制也能减轻这种攻击带来的危害,但这最终依赖于具体情况(一 个整天跟有这种漏洞的网络银行程序打交道的用户所面临的风险要远远大于临时使用同一网络银行的用户所面临的风险)。
七、小结
   跨站请求伪造,即CSRF,是一种非常危险的Web安全威胁,它被Web安全界称为“沉睡的巨人”,其威胁程度由此“美誉”便可见一斑。本文不仅对跨站请 求伪造本身进行了简单介绍,还详细说明造成这种漏洞的原因所在,以及针对该漏洞的黑盒测试与灰盒子测试具体方法和示例,最后提提了一些防范该攻击的建议, 希望本文对读者的安全测试能够有所启发。

CSRF | XSRF 跨站请求伪造

今天我们谈谈“跨站请求伪造”(CSRF / XSRF)(Cross Site Request Forgery)。而这种脆弱性在网络上是十分的普遍,许可证是通过一个受害者在发送一个HTTP请求到网站,然后以这种方式记录和信任该用户。
以这种方式攻击须要构造一些恶意的HTML和JAVASCRIPT代码。用途是一个受害者访问了这个网站后会做到我们之前所放置的一些行为。而这种形为就是一种复杂性证明的CSRF攻击!
而这种会话传输能够很轻易的被Html的行为和标记语言所接受,BBcode也是如此。
关于认证:
通常,当一个用户登陆到一个受信任的站点,验证系统将用“标识符”来表记这个用户,告诉网站系统当前的用户是经过验证的可以访问一些保留的页面和服务。
这些“标识符”是实现和创建 Cookies和Sessions,通常所生成的是一些HASH和经过编码的号码,会严格确定每一个用户。
随时这个用户都会用他自己的证书登陆到这个WEB站点,这标志着一个新的Sessions将产生。与次同时一位攻击将容易地去做一切越权的性为在WEB站点的 “Ward” 里。J
这看来并不是一件危险的事情,因为只有一个白痴用户才会接受任何种类的请求,千万不要低估这种可爱Cookies的威力。
对于大多数的XSS来说Cookies是最好的攻击目标,因为许可证是一个立即访问到任何 种类的机密和专用服务,一个用户拥有这样的特权在:对于CSRF来说这是更有力的,因为disfruts当前Sessions不能容易的避免掉,设想这个 站点不提供临时的Cookies。
异处:XSS和CSRF之间
实际上,XSS和CSRF到低有什么实际上的差异呢?这看起来非常的相似。
实事上它们两个颇为相似,但是有一个核心的差异使这两个弱点区分开来。
在XSS漏洞里用户是完全信任该站点的,并会提交一些受骗的信息给攻击者(以抓取Cookies信息为例)。
在CSRF漏洞里站点是信任某个用户的请求和完成任何种类的行为,这样一来所提交的一些表单中的“认证标记”将有利用攻击者。这标志一种以经登陆并拥有相应的权限。
关于CSRF的一个简单形式图如下:
                    trusted <-----flag-----.
     .--------. .-------. .-----|--------.
     | ATTACKER |_____| USER |_____| WEBSITE |
     `----------`  tricks  `------` (request) `---------`
      |                     "_ _ _ _ _ _ _ _/                          |
      |                                                                        |
            `---------------------------------------------`
          the website accomplishes the request
像我们所看到的这种形式是一种反方向的XSS,(该站点信任该用户的身份并授权给该用户。)公平的完成了这个用户的请求,这是一种模糊的认证。
重点是在于,这次的攻击请求是由该用户发送给WEB站点的,而不是攻击者,这使得该漏洞更具危险性!
深入了解CSRF
好吧,现在我们要了解一下什么是CSRF。让我们从一些小的例子开始。
保证这个例子是一个用户赞成该WEB站点所提供的一些特殊项目。也许是提供一些金钱的交易:当这个用户以登录,这时该服务器将创建一个Cookies和Sessions标志着这个用户可以访问一些他自己的私人页面。
此外还要保证,这个WEB站点也许是一个“电子银行服务”,它提供了一种以HTML方式执行金钱交易。那么这段代码看起来将会像:
 1<!-- scratch of a form -->
 2<form method="POST" action="sendmoney.php" name="sendmoney">
 3     <div>How much: <input type="text" name="cash"></div>
 4     <div>To: <input type="text" name="toname"></div>
 5     <div>ABI: <input type="text" name="toabi"></div>
 6     <div>CAB: <input type="text" name="tocab"></div>
 7     <div>CIN: <input type="text" name="tocin"></div>
 8     <div><input type="submit" name="submit" value="Buy"></div>
 9</form>
10<!-- EOF -->
通过这种方式,用户将转移一些金钱到目标的账户里。
OK,这是一种非常愚蠢的事情,和完全不可能找到正确的那部分,但是只有它能够让你更清楚的了解这些事情,:P 请不要抱怨。Sorry!
OK,当这个用户将提交这些值到脚本。sendmoney.php将执行查询,使这个电子银行系统,完成他的转移请求。也许这个脚本看起来想:
 1     /* sendmoney.php */
 2     <?
 3     session_start();
 4     if(isset($_REQUEST['cash']))
 5          $cash = $_REQUEST['cash'];
 6     else
 7          die("Specify the amount of money");
 8     if(isset($_REQUEST['toname']))
 9          $toname = $_REQUEST['toname'];
10     else
11          die("Specify a recipient");
12     if(isset($_REQUEST['toabi']))
13          $toabi = $_REQUEST['toabi'];
14     else
15          die("Specify the ABI");
16     if(isset($_REQUEST['tocab']))
17          $tocab = $_REQUEST['tocab'];
18     else
19          die("Specify the CAB");
20     if(isset($_REQUEST['tocin']))
21          $tocin = $_REQUEST['tocin'];
22     else
23          die("Specify the CIN");
24     
25     // This function safely send the money to the target
26     send_money($cash$toname$toabi$tocab$tocin);
27     
28     ?>
29     /* EOF */
在这个脚本中的变量Send_meney()将有效的将值传给目标,完成这次的转移工作。
在这个特定的情况下,使用全球变量REQUEST允许一个攻击者disfrut在表单中使用GET方法,偷去用户的金钱。
如果这个用户是鉴别的,正如我以前所说的,一个攻击者将提供给这个用户网页或一个图片,看起来就像是这样的。
1     <!-- coolthing.html -->
2     <html>
3     <head><title>Cool Thing</title></head>
4     <body>
5     <img src="http://bankhost.com/sendmoney.php?cash=ALL&toname=ME&toabi=
6      123456&tocab=123456&tocin=X">
7     </body>
8     </html>
9     <!-- EOF -->
其实,如果这个用户应邀访问了这个页面并同时登录到“backhost.com”站点,这个图片载入将发送一个HTTP请求到这个WEB站点,询问他完成这个处理。这实际上是用户自己以前所发起的转移命令。
OK,这是不是一个很好的方法管理交易呢,这个全球的REQUEST不是安全的。或许更多的脚本将使用POST变量代替发送sendmoney,因为他们可能认为这将是更安全的。
显然是不是想像的那样。
考虑用coolthing.html这个文件代替前面那个:
<!-- coolthing.html -->
<html>
<head>
<title>Cool Thing</title>
<script type="text/javascript">
function stealMoney()
{
           iframe = document.frames["stealmoney"];
           iframe.document.Submit("steal");
}
</script>
   </head>
   <body onload="stealMoney()">
   <div><img src="it.jpg"></div>
    <iframe name="stealmoney" display="none">
        <form method="POST" name="steal"
action="http://localhost:88/sendmoney.php">
        <input type="hidden" name="cash" value="ALL">
        <input type="hidden" name="toname" value="ME">
        <input type="hidden" name="toabi" value="123456">
        <input type="hidden" name="tocab" value="123456">
        <input type="hidden" name="tocin" value="X">
    </form>
</iframe>
</body>
</html>
<!-- EOF -->
我们可以看到这个页面组成只是加载了一个it的图片,但是这是以一种隐藏的形式存放在iframe “stealMoney”将执行一个请求到“bankhost.com”网站,请求这个用户Sessions交易的Money到目标的信息。
这只是一个愚蠢的例子,但是通过这个例子你可以想象什么种类的实体漏洞可以采取。
攻击要点
让我们总结一下在什么情况下发起CSRF攻击:
a).攻击者找到一个不懂得什么是用户注册的人,利用这种方式发起CSRF攻击。
b).攻击者创建一个HTML的页面其中将会自动的发送一些请求到脆弱的WEB站点。
c).受害者登录到一个WEB站点并提交了一个开放的Sessions.
d).攻击者提供一个精心构造的页面给受害者。
e).受害者访问这个页面。
f).所发送的请求完成了一个恶意的行为。
    我认为,其实这是十分简单能够理解更多危险的漏洞,一个聪明而又恶毒的攻击者基本以经知道如何向他发起攻击的步骤。
    防御CSRF:
现在,我们以经知道了什么是CSRF攻击所采取的行动,让我尝试分析一下如何防御在这类的Flaws上保护自己。
在这里我们将广泛的讨论如何防御这种漏洞,但是一般无法统一这样的种类。稳定函数的结论。
以经讨论过了关于独一无二的“代号”、验证码和其他的,
但是我仍然认为他们是不能够这么简单灵活的运用的。
等待更好的结果,我建意你至少要求这个用户的密码至少重试一次在敏感页面(如电子商贸形式和内容),
为了确让这个Sessions不能劫持(实事上..如果这个攻击者不知道这个用户的密码,将不能做任何危险事情,和一些其他的方法,如果他真正知道这个密码,他将不请求任何的CSRF J)。
它真正容易实现的是Security misure,在表格中增添了新的域:
1      <!-- new scratch of the form -->
2      <form method="POST" action="sendmoney.php" name="sendmoney">
3           <div>How much: <input type="text" name="cash"></div>
4           <div>To: <input type="text" name="toname"></div>
5           <div>ABI: <input type="text" name="toabi"></div>
6           <div>CAB: <input type="text" name="tocab"></div>
7           <div>CIN: <input type="text" name="tocin"></div>
8           <div>Your passord: <input type="password" name="pass"></div>
9           <div><input type="submit" name="submit" value="Buy"></div>
10      </form>
11      <!-- EOF -->
接下来我们将核对一下'sendmoney.php'文件。
1      /* scratch from sendmoney.php */
2      if(isset($_POST['pass']) && md5($_POST['pass']) == $mysql_row['pass']) {
3           
4      } else {
5           die("You must specify a correct password!");
6      }
7      /* EOF */
这样,CSRF攻击企图将无效,如果攻击者不是公认的机密性信息像密码这样的例子。
其他的解决方法如独一无二的“标记”在PHP 的 Sessions 的基础上建立,也许可以避免,因为攻击者能够绕开他们。
总结
到这里关于这个的讨论就以经结束了:我希望你能够一如既往的希欢这个,就像我一样希欢这样的主题