【问题标题】:cURL CSRF TokencURL CSRF 令牌
【发布时间】:2015-02-28 18:58:44
【问题描述】:

几个月前,我的同事通过获取工作时间表创建了一个日历订阅。我相信他是通过 cURL 做到这一点的。

现在我正在建立一个网站来概述今天应该完成的任务。

我想检索时间表,以便可以使用它来显示在特定日期工作的人员的姓名。

我在网上找到了一个教程,该教程解释了我如何在登录后获取数据。 我所做的是我复制了登录表单中输入字段的名称,以及一个名为 signin[_csrf_token]

的隐藏字段的名称

使用这些名称,我创建了以下代码:

<?php

$username = "myusername";
$password = "mypassword";
$url = "http://planner.a-mac.nl/employeeSchedule";
$cookie= "koekje.txt";
$token = "2e4c16f2b664f3ed01827dd38dc11d22";
$ch = curl_init();


                        curl_setopt($ch, CURLOPT_POST, true);
                        curl_setopt($ch, CURLOPT_URL, $url);
                        curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/'.$cookie);
                        curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/'.$cookie);


                        curl_setopt($ch, CURLOPT_POSTFIELDS, "signin[username]=" . $username ."&signin[password]=" . $password . "&signin[_csrf_token]=" . $token);
                        //stuur de gegevens uit het formulier door naar de link

                        curl_exec($ch);
                        //Zet de output op het scherm

                        if (curl_errno($ch))
                            {
                                   print curl_error($ch);
                                   //Als er een fout is geef deze dan
                            }
                        else
                            {
                                curl_close($ch);
                                //Sluit de link met de website
                            }
?>

当我用上面的代码加载我的页面时,我得到带有错误消息的登录表单:

检测到 CSRF 攻击

有人可以帮我解决这个问题,以便我可以从网站获得哪些数据?

我联系了我的老同事,但他说“他不知道了”...

【问题讨论】:

  • 永远不要手动构建 POST 数据字符串。为此目的有特殊功能:http_build_query

标签: php curl


【解决方案1】:

CSRF 令牌字段值不是固定的,而是为新创建的会话随机生成的值。您需要首先对网页进行“干净”调用以获取 CSRF 令牌值,然后才能将用户名/密码与 CSRF 令牌一起发布,如下所示:

<?php

  $username = "myusername";
  $password = "mypassword";
  $url = "http://planner.a-mac.nl/employeeSchedule";
  $cookie= "koekje.txt";
  $ch = curl_init();

  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/'.$cookie);
  curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/'.$cookie);

  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  $response = curl_exec($ch);
  if (curl_errno($ch)) die(curl_error($ch));

  $doc = new DOMDocument();
  $doc->loadHTML($response);
  $token = $doc->getElementById("signin__csrf_token")->attributes->getNamedItem("value")->value;

  curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
  curl_setopt($ch, CURLOPT_POST, true);

  $params = array(
    'signin[username]' => $username,
    'signin[password]' => $password,
    'signin[_csrf_token]' => $token
  );
  curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));

  curl_exec($ch);

  if (curl_errno($ch)) print curl_error($ch);
  curl_close($ch);
?>

【讨论】:

  • 我不断收到错误消息“csrf 令牌:必需”??登录表单中的隐藏输入字段的 id 为 signing__csrf_token ...
  • 现在添加了完整的代码;这(显然)呈现给 The username and/or password is invalid. 而不是我之前的 csrf token: Required
  • 奇怪的是,当我将 $url 更改为登录屏幕时,我被重定向到该站点,当我将 url 更改为 ../login 或 ../employeeSchedule 时,我看到一个空白页面, 你知道出了什么问题吗?
【解决方案2】:

CSRF 防御背后的理念是为每个页面加载生成一个唯一令牌,您必须通过表单传递该令牌。

您必须使用表单加载页面,从页面中提取令牌并将其与 POST 请求一起传递。通常,在任何尝试之后,令牌都会失效,您必须再次请求表单以获取新令牌。

CSRF 令牌存储在会话中,因此服务器可以查看表单上生成的令牌是否与发送表单的请求提供的令牌相匹配。

【讨论】:

    【解决方案3】:

    我觉得你应该像这样添加令牌:

    $headers[] = 'X-CSRF-Token:' .  $token;
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    

    【讨论】:

    • 我的问题已通过联系管理员解决,因此我可以访问数据库。我现在直接使用数据库中的数据,但感谢您的建议!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-14
    • 2016-05-07
    • 1970-01-01
    • 2019-01-01
    • 2014-05-17
    • 2011-09-24
    • 2014-04-29
    相关资源
    最近更新 更多