2011-09-08 83 views
0

的Facebook验证在http://developers.facebook.com/docs/authentication/尝试给定的例子,以防止跨站请求伪造通过插入的信息的随机分组到auth_request的status一部分。当auth_request返回时,代码将检查以确保随请求返回了相同的随机组。 CSRF如何诞生?Facebook验证实施例CSRF

代码:

<?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."); 
    } 

?> 

的信息,该位被加入到这里的要求:

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']) 

如何确保它们具有相同的“国家”确保没有CSRF?

感谢

回答

4

哈希(或状态)是由你产生为每个请求的web服务(脸谱)和存储在会话服务器上。这个散列与请求一起从您的网站发送到Facebook。 Facebook发送与响应参数完全相同的散列。

您所做的只是检查请求之前生成的哈希值是否与响应中生成的哈希值相匹配。

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

这可以防止CSRF,因为散列对于每个请求都是不同的。显然,如果每个请求使用相同的字符串,任何知道(或猜测)它的人都可以伪造一个响应。

请求完成后,检查会话中的散列和响应中的散列是否匹配。如果他们不匹配,这可能是一个伪造的回应。检查完成后,请清除会话中的值,因为您将不再需要它。

在一般情况下(不仅仅是Facebook的实现),通常还需要存储散列超时值。这将防止来自未完成请求的哈希在以后被使用/利用。没有适合所有应用和案例的单一时间,但是对于像这样的二次请求/操作,30秒-1分钟就可以。

+0

你可以提供一个这种攻击如何工作的场景吗? – Roman

+0

@罗曼互联网上有很多攻击和预防的例子。 [OWASP](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)#Examples),[Wikipedia](http://en.wikipedia.org/wiki/Cross-site_request_forgery#Example_and_characteristics) ,[杰夫的博客](http://www.codinghorror.com/blog/2008/10/preventing-csrf-and-xsrf-attacks.html) – adlawson

+0

谢谢,我已经看过那些,但仍然无法找出问题如果我们忽略交易所的状态,攻击如何与facebook一起工作。 – Roman