防止伪造跨站请求的小招式

伪造跨站请求介绍

伪造跨站请求比较难以防范,而且危害巨大,攻击者可以通过这种方式恶作剧,发spam信息,删除数据等等。这种攻击常见的表现形式有:

  • 伪造链接,引诱用户点击,或是让用户在不知情的情况下访问
  • 伪造表单,引诱用户提交。表单可以是隐藏的,用图片或链接的形式伪装。

比较常见而且也很廉价的防范手段是在所有可能涉及用户写操作的表单中加入一个随机且变换频繁的字符串,然后在处理表单的时候对这个字符串进行检查。这个随机字符串如果和当前用户身份相关联的话,那么攻击者伪造请求会比较麻烦。

yahoo对付伪造跨站请求的办法是在表单里加入一个叫.crumb的随机串;而facebook也有类似的解决办法,它的表单里常常会有post_form_idfb_dtsg

随机串代码实现

咱们按照这个思路,山寨一个crumb的实现,代码如下:

代码中的$uid表示用户唯一标识,而$ttl表示这个随机串的有效时间。

应用示例

构造表单
在表单中插入一个隐藏的随机串crumb

处理表单 demo.php
对crumb进行检查


19 Replies to “防止伪造跨站请求的小招式”

  1. 有时候站内也能构建危险的链接,比如攻击者在论坛中张贴了一张图片,图片的src是删除帖子的链接,或者是退出登录的url,如果管理员不小心进入了这个这个帖子,那么他就毫无知觉的做了个操作,类似的操作虽然说应尽量采用post方式提交,但是难保有新手程序员不这么办。

    另外,referer是可以伪造的。

  2. 可惜这个不能对ajax提交做过滤。

    在zend里,做个controller plugin,对每个form增加个hidden input verifycode,但我纠结的是

    对于ajax有好的全局处理方法吗?

  3. @henson 如果是ajax,也可以应用crumb,以jquery的ajax提交为例:

    
    $.ajax({
       type: "POST",
       url: "some.php",
       data: "name=blah&crumb=< ?php echo Crumb::issueCrumb($uid)?>",
       success: function(msg){
         alert( "Data Saved: " + msg );
       }
    });
    

    同理,crumb也可以在get方式的ajax请求中应用

  4. 学习了,
    例子里用hash(time()/ttl 与salt),保证 每个用户生成的值,在不同时间段内都是不重复的,很安全了,
    ttl 和salt的取值和算法保密也是重要的哦,呵呵

  5. 匿名提交的,因为无法确定用户身份,谁都能干,我想一般的伪造跨站请求攻击没必要这么干吧?它自己提交上去就完事了。这种情况下多是防机器人spam

  6. if(md5($uid.ceil(time()/7200).’sdfser’)==$_POST['crumb'] || md5($uid.(ceil(time()/7200)-1).’sdfser’)==$_POST['crumb'] ){
    
    }else{
    exit;
    }
  7. 这样是不是容易阅读很多呢

    if(Crumb::verifyCrumb($uid, $_POST['crumb'])) {
    } else {
        exit;
    }
  8. 类和方法的形式写出来的代码至少还具有一定的语意,在阅读性方面一定比直接md5强。

  9. 我是洞悉 于 2011-07-27 @ 17:04:30 留言 :
    容易个鸟,你那个别人还要去看看那个类才知道是干什么用的。

    /****************/
    还有这种鸟人,比人好心分享,还在这里唧唧歪歪,你的那条
    if(md5($uid.ceil(time()/7200).’sdfser’)==$_POST[‘crumb’] || md5($uid.(ceil(time()/7200)-1).’sdfser’)==$_POST[‘crumb’] ),都写死在里面了,改下密码还要改两次,

  10. 我在想那个生成Token的算法能不能不唯一呢
    就是类里有好几个方法 然后在生成Token的时候随机选择一种生成方法 选择完了记录一下用了哪个方法
    大家觉得可行吗?

  11. 假如应用于不需要登录的地方,自然没有会员UID,那应该怎么做?

Leave a Reply

Your email address will not be published.