【问题标题】:Protect against CSRF attack in PHP for multiple browser tabs在 PHP 中针对多个浏览器选项卡防止 CSRF 攻击
【发布时间】:2017-08-30 18:58:52
【问题描述】:

我知道,针对 CSRF 攻击有两种主要的解决方案。

  • 每个会话一个令牌
  • 所有独特形式的令牌

我选择了第二个,但是有问题。如果访问者在两个选项卡中打开表单,则第二个选项卡上的表单标记会覆盖之前的标记。我写了一个代码来解决这个问题。我的问题是:这是一个好的解决方案,还是我必须努力解决? (示例中只有最重要的部分。)

##### CONFIG & FUNCTION.PHP #####
// INITIALIZING - RUN ONLY ONCE
$_SESSION["csrf_tokens"]["postcomment"]     = array ();
$_SESSION["csrf_tokens"]["postcommentedit"] = array ();
// etc, etc.
function makearandomtoken ()
{
   // a simple but secure way
   return bin2hex (openssl_random_pseudo_bytes (32));
}

##### POSTCOMMENT_FORM.PHP #####
// new form for comment under a post, so create a new token
$created_token = makearandomtoken ();
array_push ( $_SESSION["csrf_tokens"]["postcomment"], $created_token );
// the form (only with important parts)
print "<form>\n";
print "<input type=\"hidden\" name=\"token\" value=\"$created_token\">\n";
print "</form>\n";

##### POSTCOMMENT_EXECUTE.PHP #####
// get the token from POST variable
$received_token = filter_input (INPUT_POST, 'token', FILTER_UNSAFE_RAW);
// check it
if ( in_array($received_token, $_SESSION["csrf_tokens"]["postcomment"]) )
{
   // VALID token, disable it
   $token_index = array_search($received_token, $_SESSION["csrf_tokens"]["postcomment"]);
   unset ($_SESSION["csrf_tokens"]["postcomment"][$token_index]);
}
else
{
   // INVALID token -> CSRF attempt
   die (); // or do anything
}

【问题讨论】:

  • 如果您的应用需要打开 2 个选项卡,则每次登录时执行一个 CSRF 令牌,如果不是很好,则用户不应打开多个选项卡。也仅在您以这种方式呈现表单时设置标记,它们可以为非基于表单的页面提供多个选项卡。
  • 看起来不错。唯一缺少的是清除旧未使用令牌的策略和/或限制每个用户的有效令牌数量。
  • 您必须限制令牌的数量,否则攻击者可以使用它来填充会话。并且由于会话大小仅受 PHP 脚本内存限制的限制,它可以使用多个帐户对服务器进行 DoS。

标签: php security csrf


【解决方案1】:

如果您希望每个表单实例都有一个新令牌,我认为您的实现没有问题。这两个选项卡都是由用户合法打开的,因此这两个令牌都被接受是有道理的。

至于 CSRF 保护,我认为它是完整的。第三个站点无法在没有令牌的情况下冒充用户,而拥有两个或三个有效令牌的用户不会使攻击者的任务变得更容易。

如果您编写前端代码,您可以向document onUnload event 注册一个事件处理程序,并让该处理程序发出一个 POST 请求,告诉服务器正在卸载哪个令牌。这样后端可以从会话中删除令牌。这可能比它的价值更麻烦,因为如果用户点击浏览器的返回按钮,她将重新加载一个无效的令牌,并且在她提交表单时会因错误而感到沮丧。

【讨论】:

    猜你喜欢
    • 2014-11-29
    • 1970-01-01
    • 2018-01-08
    • 2018-08-08
    • 2012-08-20
    • 2016-09-12
    • 2021-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多