douyanlu7380 2011-09-08 20:31
浏览 45
已采纳

Facebook身份验证示例CSRF

The Facebook authentication example given at http://developers.facebook.com/docs/authentication/ tries to prevent CSRF by inserting a random grouping of information into the status part of the auth_request. When that auth_request returns, the code checks to make sure that same random group has been returned with the request. How does that precent CSRF?

The code:

<?php 

   $app_id = "YOUR_APP_ID";
   $app_secret = "YOUR_APP_SECRET";
   $my_url = "YOUR_URL";

   session_start();
   $code = $_REQUEST["code"];

   if(empty($code)) {
     $_SESSION['state'] = md5(uniqid(rand(), TRUE)); //CSRF protection
     $dialog_url = "http://www.facebook.com/dialog/oauth?client_id=" 
       . $app_id . "&redirect_uri=" . urlencode($my_url) . "&state="
       . $_SESSION['state'];

     echo("<script> top.location.href='" . $dialog_url . "'</script>");
   }

   if($_REQUEST['state'] == $_SESSION['state']) {
     $token_url = "https://graph.facebook.com/oauth/access_token?"
       . "client_id=" . $app_id . "&redirect_uri=" . urlencode($my_url)
       . "&client_secret=" . $app_secret . "&code=" . $code;

     $response = file_get_contents($token_url);
     $params = null;
     parse_str($response, $params);

     $graph_url = "https://graph.facebook.com/me?access_token=" 
       . $params['access_token'];

     $user = json_decode(file_get_contents($graph_url));
     echo("Hello " . $user->name);
   }
   else {
     echo("The state does not match. You may be a victim of CSRF.");
   }

 ?>

The bit of information is added to the request here:

 if(empty($code)) {
     $_SESSION['state'] = md5(uniqid(rand(), TRUE)); //CSRF protection
     $dialog_url = "http://www.facebook.com/dialog/oauth?client_id=" 
       . $app_id . "&redirect_uri=" . urlencode($my_url) . "&state="
       . $_SESSION['state'];

     echo("<script> top.location.href='" . $dialog_url . "'</script>");
   }

And checked here:

 if($_REQUEST['state'] == $_SESSION['state'])

How does ensuring they have the same "state" ensure no CSRF?

Thanks

  • 写回答

1条回答 默认 最新

  • dongyu2764 2011-09-08 21:25
    关注

    The hash (or state) is generated by you for each request to the web service (Facebook) and stored in the session on your server. This hash is sent with the request to Facebook from your website. Facebook sends the exact same hash back as a parameter on the response.

    All you do is check if the hash generated before the request matches the one in the response.

       MyWebsite   |    Facebook
    ---------------+-----------------
                   |
    Generate $hash |
      Store $hash  |
                   |
                 $hash
        ----------------------->
                   |
                 $hash
        <-----------------------
                   |
      Check $hash  |
    

    This prevents CSRF because the hash is different for each request. Obviously, if you use the same string for each request, anyone who knows (or guesses) it will be able to forge a response.

    Once the request is complete, check the hash from the session and the hash in the response both match. If they don't match, it's likely to be a forged response. After you check, clear the value from the session as you won't be needing it again.

    In general cases (not just Facebook's implementation), it's often wise to also store a timeout for the hash. This will prevent a hash from an incomplete request being used/exploited at a later date. There is no single time that will fit all applications and cases, but in the case of a secondary request/action like this, 30s-1 minute would do.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 关于#lua#的问题,请各位专家解答!
  • ¥15 什么设备可以研究OFDM的60GHz毫米波信道模型
  • ¥15 不知道是该怎么引用多个函数片段
  • ¥30 关于用python写支付宝扫码付异步通知收不到的问题
  • ¥50 vue组件中无法正确接收并处理axios请求
  • ¥15 隐藏系统界面pdf的打印、下载按钮
  • ¥15 基于pso参数优化的LightGBM分类模型
  • ¥15 安装Paddleocr时报错无法解决
  • ¥15 python中transformers可以正常下载,但是没有办法使用pipeline
  • ¥50 分布式追踪trace异常问题