【问题标题】:How does this CSRF protection work?这个 CSRF 保护是如何工作的?
【发布时间】:2011-07-12 04:43:44
【问题描述】:

以下是取自 Facebook 身份验证页面的示例。将数据添加到会话然后使用 javascript 重定向到 URL 背后的想法是什么?还有为什么要对 uniqid 进行 md5 哈希?

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

 ?>

【问题讨论】:

    标签: php security csrf-protection


    【解决方案1】:

    我知道这可能会因为它是一个 wikipedia 链接而被淘汰,但您可以在 http://en.wikipedia.org/wiki/Cross-site_request_forgery 找到对 csrf 的完整解释,一旦您完全了解它是什么,您就会明白每个用户拥有一个唯一令牌可以如何保护反对。预防部分列出了使用每用户令牌作为预防方法。

    【讨论】:

    • 好的,所以 csrf 是关于捎带用户访问网站的。正确的?我可以理解有关经过身份验证的用户访问页面并在不知不觉中触发 url 的情况。但是,是否应该在每个标题中插入上面的代码?好像有点重。
    • 基本上,如果您有一个基于帖子或获取请求启动操作的网站,您应该始终验证请求的来源/方式。
    【解决方案2】:

    它确保您仅在响应站点​​发起的操作时被重定向到此处。在 https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29 阅读 CSRF。

    【讨论】:

    • 我明白了。因此,这将是一种在 B 点(到达)验证呼叫来自 A 点(起点)的方法。你认为这可以在内部使用 PHP 解决吗?如果我要检查呼叫来自哪里,应该可以在服务器变量中看到这一点,如果被伪造,则提供一个可以从一个页面传递到另一个页面的唯一 id。
    • 关键是它必须是一个不能轻易复制的值(因此 md5/uniqid 调用)。如果它是一个固定值,那么专门的攻击者将能够推断出它并制作一个包含它的跨站点请求。SESSION 调用确保它是一个无法预期的值。
    【解决方案3】:

    通过生成一个难以(不可能)猜测的值并将其存储在会话中以及将其与请求一起发送,此脚本可以验证它是否被自己调用而不是在其他地方调用。在其他地方,难以猜测的值将是未知的,因此无法提供。

    【讨论】:

    • 所以从你所说的来看,这是一种验证请求是否来自预期页面的方法。这将用于每个页面还是仅用于特定情况?
    • 这取决于您的应用程序。这是安全性和开销之间的权衡。您可能不在乎是否有人从外部提交您的联系表格,直到有人认为他很有趣并用它向您发送垃圾邮件。你可以做的是在围绕表单的抽象中修复这种想法,所以你只需要修复一次。一般来说,我认为您不希望人们从您的域之外的某个地方提交您域中的表单。
    猜你喜欢
    • 2012-07-21
    • 2017-04-06
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 2019-11-02
    • 2012-07-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多