繁体   English   中英

PHP-安全更改密码表格/方法

[英]PHP - Secure Change Password Form/Method

我已经根据Wikihow文章制作了自己的登录系统,并且想输入一个更改密码字段,但是我不知道该怎么做。 这是我现在所拥有的:

的JavaScript

function formchange(form, current, newpass) {
    // Create a new element input, this will be our hashed password field. 
    var p = document.createElement("input");
    var p2 = document.createElement("input");

    // Add the new element to our form. 
    form.appendChild(p);
    p.name = "p";
    p.type = "hidden";
    p.value = hex_sha512(current.value);

    form.appendChild(p2);
    p.name = "p2";
    p.type = "hidden";
    p.value = hex_sha512(newpass.value);

    // Make sure the plaintext password doesn't get sent. 
    current.value = "";
    newpass.value = "";

    // Finally submit the form. 
    form.submit();
}

的PHP

if (isset($_POST['cpass'], $_POST['npass'])) {
    $cpass = $_POST['cpass'];
    $npass = $_POST['npass']; // The hashed password.

    echo "Here";

    $un = getUser();

    if ($cpass == $npass) {
        echo "If";
        $random_salt = hash('sha512', uniqid(mt_rand(1, mt_getrandmax()), true));
        $password = hash('sha512', $npass . $random_salt);

        // Insert the new user into the database 
                if ($insert_stmt = $mysqli->prepare("MYSQL UPDATE STATEMENT")) {
                    $insert_stmt->bind_param('p', $password);
                    $insert_stmt->bind_param('s', $random_salt);
                    echo "Binded";
                    // Execute the prepared query.
                    if (! $insert_stmt->execute()) {
                        header('Location: ../home.php?msg=1');
                    }
                }

        header('Location: ../home.php?msg=2');
    } else {
        // Failed
        header('Location: ../?error=1');
    }
} else {
    // The correct POST variables were not sent to this page. 
    echo 'Invalid Request';
}

它似乎不起作用,它一直运行到home.php?msg = 2,但是数据库未更新。 我对所有这些都是新手,这是我的项目之一,因此请您为糟糕的代码道歉。 我的MySQL语句是这样的:

UPDATE user_data SET user_data.password = 'p', user_data.salt = 's' WHERE username = '$un';

您尝试执行的操作从根本上来说是有缺陷的。 攻击者仍然可以使用您的JavaScript函数创建的哈希值执行重播攻击。 另外,您只保护未隐藏的密码(但是我仍然可以在彩虹表中查找它)而不是帐户。 攻击者可以使用哈希值验证用户身份。 这是因为哈希值是密码。

要真正制作安全表格,您将需要使用HTTPS和某种跨站点请求伪造令牌。

这是一个例子,说我的名字叫爱丽丝,我正在看鲍勃的网络流量。

我(作为爱丽丝)看到鲍勃提交您的表单,然后看到您的Web服务器回复鲍勃说“谢谢,密码已更新”

我(作为爱丽丝)现在知道鲍勃的密码,更糟糕的是,我现在可以发送鲍勃刚刚发送给您的同一个HTTP请求,但是由于我知道鲍勃的密码,因此我可以将请求更改为再次更新密码,以更改为我想要的任何内容。

您的表单比发送未隐藏的密码更安全。

在许多情况下,包括在查询成功时,都将脚本设置为转发到home.php?msg=2

if (! $insert_stmt->execute()) {
    header('Location: ../home.php?msg=1');
}

如果查询执行失败,它将把它发送到home.php?msg=1 ,注意! 由于查询不会失败,因此脚本继续执行,下一个功能是...

header('Location: ../home.php?msg=2');

“它似乎没有用,它一直到home.php?msg = 2。”

那么,您希望脚本执行什么操作? 您是如何设计的,应该做到这一点。


更新新内容

您应该避免使用这样的标头位置,否则您将永远找不到错误。 您应该避免在开发期间完全使用标头位置,尤其是在查询失败时。

我将附加更多标题位置并抓住错误以查看语句失败的原因。 我从来没有使用过mysqli,因为我认为pdo更好,但是我认为这应该可行。

           if ($insert_stmt = $mysqli->prepare("MYSQL UPDATE STATEMENT")) {
                $insert_stmt->bind_param('p', $password);
                $insert_stmt->bind_param('s', $random_salt);
                echo "Binded";
                // Execute the prepared query.
                if (! $insert_stmt->execute()) {
                    die($mysqli->error);
                    // header('Location: ../home.php?msg=1');
                }
                else {
                    // Success, forward
                    header('Location: ../home.php?msg=2');
                }
            }
            else {
                die($mysqli->error);
            }

删除header('Location: ../home.php?msg=2'); 在原始脚本中此部分的底部。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM