【问题标题】:Anti-CSRF implementation posting an old token发布旧令牌的反 CSRF 实现
【发布时间】:2012-07-08 00:40:59
【问题描述】:

我在登录表单上实施 CSRF 保护时遇到了一些问题。这是登录的一般流程:

这包含在登录页面的顶部:

// Create CSRF token
$token = $auth->random(64); // 64 psuedorandom characters from /dev/urandom
$_SESSION['token'] = $token;

登录表单:

<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
<input type="text" name="username" />
<input type="password" name="password" />
<input type="hidden" name="token" value="<?php echo $token; ?>" />
<input type="submit" name="login" value="Login" />
</form>

最后,当表单提交到页面下方时:

if (isset($_POST['login'])) {

    // Bind input to variables
    $username = isset($_POST['username']) ? $_POST['username'] : '';
    $password = isset($_POST['password']) ? $_POST['password'] : '';
    $posttoken = isset($_POST['token']) ? $_POST['token'] : '';

    // Attempt to login
    $auth->login($username, $password, $posttoken);

}

问题在 $auth->login 收到输入时开始。 $_SESSION 令牌等于生成的令牌,但 $_POST 令牌等于 $_SESSION 令牌在上次提交期间的值。

$auth->login 中的 var_dump 示例:

首先提交var_dump:

$_SESSION Array
[token] => 00a28586a1a89b30149ef130ca6f3c01a25435ad1b0ad1a19326205c75b80d79

$_POST Array
[username] => 
[password] => 
[token] => 2200bb8663f19d66639a7f4791ddb53c9d510802d0ed76c42ac8b3f6d9e1589a
[login] => Login

第二次提交var_dump:

$_SESSION Array
[token] => e093e312b379d766d46083d616fa8655f1565dc19ed6b1f73108546cb5f43fce

$_POST Array
[username] => 
[password] => 
[token] => 00a28586a1a89b30149ef130ca6f3c01a25435ad1b0ad1a19326205c75b80d79
[login] => Login

第三次提交var_dump:

$_SESSION Array
[token] => 8be7ecbdae6274d1ba5ce9e8ace0af7c76e3e7d181c507d3da9b8c35652865cc

$_POST Array
[username] => 
[password] => 
[token] => e093e312b379d766d46083d616fa8655f1565dc19ed6b1f73108546cb5f43fce
[login] => Login

如果您仔细观察,您会发现 $_POST 令牌只是向下移动——变成了上次提交期间的 $_SESSION。

这让我很困惑,因为$token$_SESSION['token'] 只在页面顶部设置了一次——当用户点击提交时它们不应该不同。

总而言之,$_SESSION 包含当前生成的令牌,$_POST 包含之前生成的令牌。

有什么想法吗?谢谢!

【问题讨论】:

    标签: php http-post csrf


    【解决方案1】:

    问题是会话令牌在登录处理代码之前被更改,您需要将令牌生成位移动到登录处理代码之后。

    【讨论】:

    • 似乎是这个问题:&lt;form action="&lt;?php echo $_SERVER['PHP_SELF']; ?&gt;" method="post"&gt;提交页面时,会生成一个新令牌并添加到$_SESSION,而旧令牌则传入$_POST,导致匹配失败。我还没有找到解决方法,同时仍然使用每个请求令牌并保持表单和 PHP 在同一页面上处理它。
    • 我收回了!解决方案是将登录处理代码放在页面顶部,将令牌生成代码放在页面下方,最后将表单放在底部。最初您的解决方案不起作用,因为处理程序仍在表单下方。接受!
    • 很高兴它成功了,我很难回答这个问题,因为我在 iPad 上。否则会提供更多信息。
    猜你喜欢
    • 2018-06-05
    • 1970-01-01
    • 2017-01-15
    • 2011-04-09
    • 2019-06-01
    • 2013-05-21
    • 2016-01-02
    • 1970-01-01
    • 2017-12-19
    相关资源
    最近更新 更多