add by zhj: 在看Django开发的应用时,看到了CSRF,然后搜到了这篇文章,讲的不错。其实CSRF

攻击也蛮简单的。当你登陆网站A后,会在本地存有cookie,在cookie没有过期的情况下,你又去访问

网站B,而网站B的js中包含发给A的http请求(即http的域名是A),因为这个请求的域名是A,所以会

携带你的对于A域名的cookie,这样就在你不知情的情况下完成了一次操作。

原文:http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html   作者: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攻击,受害者必须依次完成两个步骤:

  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()+);
  ?>

  在表单里增加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/)]

六.参考文献

[1].Preventing CSRF

[2].Security Corner: Cross-Site Request Forgeries

[3].《深入解析跨站请求伪造漏洞:原理剖析》

[4].《Web安全测试之跨站请求伪造(CSRF)》

[5].《深入解析跨站请求伪造漏洞:实例讲解》

[6].http://baike.baidu.com/view/1609487.htm

浅谈CSRF攻击方式(转)的更多相关文章

  1. [转]浅谈CSRF攻击方式

    在CSDN中看到对CSRF攻击的原理及防护文章,讲解浅显易懂,特转之: 来源:http://blog.csdn.net/fationyyk/article/details/50833620 一.CSR ...

  2. 浅谈CSRF攻击方式

    一.CSRF是什么? CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSR ...

  3. 浅谈CSRF攻击方式(转)

    引自:http://www.cnblogs.com/hyddd/一.CSRF是什么? CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one cli ...

  4. 咱妈说别乱点链接之浅谈CSRF攻击

    平时经常听到人们说别乱点链接,小心有病毒.还有长辈们转发的“天呐~XXX的阴谋,全是病毒”.“XXX惊天大病毒,点了苹果手机就要爆炸!”.“现在转发热门连接会乱扣费!千万别点!”. 到底长辈们说的这些 ...

  5. 浅谈 DDoS 攻击与防御

    浅谈 DDoS 攻击与防御 原创: iMike 运维之美  什么是 DDoS DDoS 是英文 Distributed Denial of Service 的缩写,中文译作分布式拒绝服务.那什么又是拒 ...

  6. django 浅谈CSRF(Cross-site request forgery)跨站请求伪造

    浅谈CSRF(Cross-site request forgery)跨站请求伪造(写的非常好) 本文目录 一 CSRF是什么 二 CSRF攻击原理 三 CSRF攻击防范 回到目录 一 CSRF是什么 ...

  7. 浅谈CSRF(Cross-site request forgery)跨站请求伪造

    目录 浅谈CSRF(Cross-site request forgery)跨站请求伪造 CSRF是什么 CSRF攻击原理 CSRF攻击防范 浅谈CSRF(Cross-site request forg ...

  8. 浅谈Ddos攻击攻击与防御

    EMail: jianxin#80sec.comSite: http://www.80sec.comDate: 2011-2-10From: http://www.80sec.com/ [ 目录 ]一 ...

  9. 转载-浅谈Ddos攻击攻击与防御

    EMail: jianxin#80sec.comSite: http://www.80sec.comDate: 2011-2-10From: http://www.80sec.com/ [ 目录 ]一 ...

随机推荐

  1. 【RF库XML测试】测试的XML文件说明

    文件存放路径:C:\workspace\robotframework\test_rf_api\testdata\XML.xml 文件内容: <example> <first id=& ...

  2. Redis /etc/redis.conf 常用配置

    Redis 基础配置: daemonize yes // 设置以daemon方式启动 logfile "/var/log/redis.log" // 设置日志文件路径 dir /d ...

  3. linux 开机自启

    cd /home/dpf 1.vi startup.sh #!/bin/shecho "hello world" >> /home/dpf/test.txt vi mq ...

  4. java Web 启动时自动执行代码的几种方式

    Web容器启动后执行代码的几种方式,其执行顺序为:4===>5===>1===>2===>3,即指定init-method的Bean开始执行,接着实现spring的Bean后置 ...

  5. Kindeditor问题

    1.初始的时候,拿到切图,kindeditor不知道为什么就是显示不出来,只出来个文本框一样的东西 原因:样式未加载,这个是因为美工那边样式重调了,而且新项目并没有将整个插件拷贝过来,而只是拿了kin ...

  6. 【MySQL】 Cannot load from mysql.proc. The table is probably corrupted

    解决办法 在 mysql 这张表里边.执行sql ALTER TABLE `proc` MODIFY COLUMN `comment` text CHARACTER SET utf8 COLLATE ...

  7. 【贪心】PAT 1033. To Fill or Not to Fill (25)

    1033. To Fill or Not to Fill (25) 时间限制 10 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 ZHANG, Gu ...

  8. 【多线程系列】AQS CAS简单介绍

    一.什么是CAS CAS(Compare And Swap),即比较并交换.是解决多线程并行情况下使用锁造成性能损耗的一种机制,CAS操作包含三个操作数——内存位置(V).预期原值(A)和新值(B). ...

  9. JavaScript怎样学

    嘿,我最近接到一个 Web 项目,不过老实说,我这两年没怎么接触 Web 编程,听说 Web 技术已经发生了一些变化.听说你是这里对新技术最了解的 Web 开发工程师? 准确地说,我是一名「前端工程师 ...

  10. 2333: [SCOI2011]棘手的操作[离线线段树]

    2333: [SCOI2011]棘手的操作 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2325  Solved: 909[Submit][Stat ...