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.

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

报告相同问题?

悬赏问题

  • ¥30 python代码,帮调试
  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条