【问题标题】:Preventing Spoofed Forms防止欺骗形式
【发布时间】:2012-11-29 18:40:32
【问题描述】:

我有一个向自身提交表单的 php 页面。
我想添加一个可以阻止基本跨站点伪造的检查。

我的代码:

<?php
session_start();

(...) //some code

$secret = substr(md5(uniqid(rand(), true)), 1, 2);
$_SESSION["secret"] = $secret;
$auth = $secret;

?>

(...)

<form id="form" name="form" action="<?php echo htmlentities($_SERVER[PHP_SELF]); ?>" method="post">

(...)

<input type="hidden" name="id" value="<? echo $auth; ?>" />

(...)

<?php

(...)

//as a debug I just tried to display
echo $_POST["id"];
echo "=";
echo $_SESSION["secret"];

(...)

?>
<div>
</body>
</html>

但是idsecret 永远不会返回相同的值。
这是为什么?我错过了什么?


更新

所以,我在这里尝试了 Samuel Cook 的回答,正如 Jon Stirling 的评论所建议的那样:

if(!isset($_SESSION["secret"])){
    $secret = substr(md5(uniqid(rand(), true)), 1, 2);
    $_SESSION["secret"] = $secret;
    $auth = $secret;
}

但是现在如果没有$_SESSION["secret"]
页面返回:

<input type="hidden" name="id" value="" />

我明白为什么,因为只有在会话变量存在时才会设置秘密。
有什么建议吗?


更新

在生成新会话密钥之前移动了检查,仅检查是否有 id 的帖子。 现在运行良好谢谢。

【问题讨论】:

  • 是不是因为你在页面顶部重新生成了$secret并分配给了session?

标签: php security


【解决方案1】:

在你调试代码执行的时候,秘密已经改变了:

echo $_POST["id"]; // previous secret
echo "=";
echo $_SESSION["secret"]; // new secret

只要您在脚本开头(在生成下一个秘密之前)检查是否匹配就可以了。

【讨论】:

    【解决方案2】:

    一旦你打开一个页面 $auth 将生成,提交后我将在隐藏字段中 $_SESSION["secret"] 将更改,因为 $secret 将生成新密钥但 $_POST['id'] 是旧密钥来自 Post 方法。

    【讨论】:

    • 啊,我想我应该只在 ID 不存在的情况下生成一个新的会话密钥?
    • 是 if(empty($_POST['id'])){ //生成新密钥 }
    【解决方案3】:

    您总是在生成一个新的$secret,因此它总是不同的。您可以检查$_SESSION['secret'] 是否存在,如果不存在则创建一个新变量。比如:

    if(!isset($_SESSION["secret"])){
        $secret = substr(md5(uniqid(rand(), true)), 1, 2);
        $_SESSION["secret"] = $secret;
        $auth = $secret;
    }
    

    【讨论】:

      猜你喜欢
      • 2017-01-12
      • 2017-05-14
      • 2017-01-08
      • 1970-01-01
      • 2011-03-03
      • 2017-11-21
      • 2017-01-19
      • 2012-11-01
      • 1970-01-01
      相关资源
      最近更新 更多