我已经根据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';
答案 0 :(得分:1)
你要做的事情从根本上是有缺陷的。攻击者仍然可以使用JavaScript函数创建的哈希值执行重放攻击。此外,您只保护未经过修改的密码(但我仍然可以在彩虹表中查找)而不是帐户。攻击者可以使用哈希值作为用户进行身份验证。这是因为哈希值是密码。
要实际制作安全表单,您需要使用HTTPS和某种跨站点请求伪造令牌。
以下是一个例子,我的名字是Alice,我正在观看Bob的网络流量。
我(作为Alice)看到Bob提交您的表单,然后我看到您的Web服务器回复Bob说#34;谢谢,密码已更新"
我(作为Alice)现在知道Bob的密码,更糟糕的是我现在可以发送Bob刚刚发送给你的相同HTTP请求但现在因为我知道Bob的密码我可以更改更新请求密码再次,我想要的任何东西。
您的表单不比发送未经哈希的密码更安全。
答案 1 :(得分:1)
您的脚本设置为转发到home.php?msg=2
许多条件,包括查询成功的时间。
if (! $insert_stmt->execute()) {
header('Location: ../home.php?msg=1');
}
如果查询无法执行,这会将其发送到home.php?msg=1
,请注意!
。由于查询不会失败,脚本会继续,下一个函数是......
header('Location: ../home.php?msg=2');
"它似乎无法工作,它继续回家.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');
。