I want to reset user password using php. i got user's current and new password from html form . here's php script to reset password. But it always executes else part even if user enters correct password. how?any solution? i know there might be a simple error but i'm new at this and couldnt find any error.
$uid = $_SESSION['uid'];
$current_pass = $_POST['org_pass'];
$new_pass = $_POST['new_pass'];
if(isset($_POST['submit']))
{
$act_pass = $db_con->prepare("SELECT password FROM user WHERE u_id= ?");
$act_pass->bindParam(1,$uid);
$act_pass->execute();
$actual_pass = $act_pass->fetchColumn();
define('SALT', 'flyingrabbit');
$typed_pass = md5(SALT.$actual_pass);
if ($typed_pass == $current_pass)
{
$new_pass1 = md5(SALT . $new_pass);
$res = $db_con->prepare("UPDATE user SET password= ? WHERE u_id=?");
$res->bindParam(1,$new_pass1);
$res->bindParam(2,$uid);
$res->execute();
header("Location: profile.php");
exit;
}
else
{
echo "<script type=\"text/javascript\">window.alert(\"You entered wrong password.\");window.location.href = 'profile.php';</script>";
}
}
This looks wrong:
$actual_pass = $act_pass->fetchColumn();
// ...
$typed_pass = md5(SALT.$actual_pass);
if ($typed_pass == $current_pass)
You are hashing the information you got from the database which - I assume - is already hashed.
You probably want:
$actual_pass = $act_pass->fetchColumn();
// ...
$typed_pass = md5(SALT.$current_pass);
if ($typed_pass == $actual_pass)
Note that md5 is not recommended to hash passwords.
You should compare hashed $current_pass and **$actual_pas**s.
Replace
$typed_pass = md5(SALT.$actual_pass); with $typed_pass = md5(SALT.$current_pass);
$typed_pass == $current_pass with $typed_pass == $actual_pass
It goes to the else statement because you compare $typed_pass == $current_pass but on the previous line you do this $typed_pass = md5(SALT.$actual_pass) you compare a hashed, salted password to a plain text password
Related
I have added the password_hash PHP function to my registration page, where users create accounts and store passwords. I applied the same password_hash line of code in the registration form. The data is saved in the database, but when I try to log in, the password submitted isn't matching the password stored. I also tried the password_verify function, which I read in the PHP manual, but nothing works. I really don't know what else to do, after trying and trying, so if anybody has an advice, I'd appreciated it.
P.S. I'm currently using PHP version 5.6.25.
Here's the code:
<?php
// AJAX CALLS THIS LOGIN CODE TO EXECUTE
if(isset($_POST["e"])){
// CONNECT TO THE DATABASE
include_once("PHP_Includes/db.php");
// GATHER THE POSTED DATA INTO LOCAL VARIABLES AND SANITIZE
$e = mysqli_real_escape_string($db, $_POST['e']);
$p = password_hash($_POST['p'], PASSWORD_DEFAULT,['cost' => 15]);
// FORM DATA ERROR HANDLING
if($e == "" || $p == ""){
echo "login_failed";
exit();
} else {
// END FORM DATA ERROR HANDLING
$sql = "SELECT id, username, password FROM users WHERE email='$e' AND activated='1' LIMIT 1";
$query = mysqli_query($db, $sql);
$row = mysqli_fetch_row($query);
$db_id = $row[0];
$db_username = $row[1];
$db_pass_str = $row[2];
if($p != $db_pass_str){
echo "login_failed";
exit();
} else {
// CREATE THEIR SESSIONS
$_SESSION['userid'] = $db_id;
$_SESSION['username'] = $db_username;
$_SESSION['password'] = $db_pass_str;
}
}
exit();
}
?>
login() function:
function login(){
var e = _("email").value;
var p = _("password").value;
if(e == "" || p == ""){
_("status").innerHTML = "Fill out all of the form data";
} else {
_("loginbtn").style.display = "none";
_("status").innerHTML = 'please wait ...';
var ajax = ajaxObj("POST", "index.php");
ajax.onreadystatechange = function() {
if(ajaxReturn(ajax) == true) {
if(ajax.responseText == "login_failed"){
_("status").innerHTML = "Login unsuccessful, please try again.";
_("loginbtn").style.display = "block";
} else {
window.location = "user.php?u="+ajax.responseText;
}
}
}
ajax.send("e="+e+"&p="+p);
}
}
Your understanding of how password_hash() works is a bit off. Unlike using sha1() or md5() (both of which you should avoid for storing passwords!), the password_hash() doesn't return the same string for every time it's called, even for the same string.
For example:
var_dump(password_hash("hello_world", PASSWORD_DEFAULT));
var_dump(password_hash("hello_world", PASSWORD_DEFAULT));
would output (for example, the strings returned by password_hash() varies for each time its called)
string(60) "$2y$10$Da2HG0dcvfI.3qBivR8Mpu9U5S06PBZ3415lDEh3EcDZ/fELZzHgC"
string(60) "$2y$10$zL6745UkPEvZWS5w1Keco.IKi7ssl.PqldGxucDYHaJW3vgCc366a"
Notice that they are different, even when the function is called twice on the same value? This means, that you cannot compare the stored password against $p = password_hash($_POST['p'], PASSWORD_DEFAULT,['cost' => 15]); like you are currently doing, because the password_hash() function returns a different string every time - you need to use the function password_verify() to verify the password, like below
$p = $_POST['p'];
if (password_verify($p, $fromDataBase)) {
// Valid password!
}
So instead of...
$p = password_hash($_POST['p'], PASSWORD_DEFAULT,['cost' => 15]);
you want
$p = $_POST['p'];
and instead of...
if($p != $db_pass_str){
you want
if (!password_verify($p, $db_pass_str)) {
And two notes on security:
You are not using prepared statements, which you REALLY should! See a link for mysqli_prepare() below. You should treat all your user-input as dangerous, and therefor use prepared statements for all SQL queries that accepts user-input. (When using prepared statements, you don't want to use mysqli_real_escape_string() - use one or the other, most preferably prepared statements!)
You are storing a password in a session - this is highly discouraged, as sessions can be "hijacked".
Readingmaterial:
http://php.net/manual/en/function.password-verify.php
http://php.net/manual/en/mysqli.prepare.php
How can I prevent SQL injection in PHP?
I'm writing log in code for the only user in my db.
But the password_verify function doesn't seem to work. When I echo both the hash from the db and the password written in the form, I see them, so there's no problem with the query or the $_POST.
Here's my code:
the log in:
$passwordFromForm = htmlspecialchars($_POST['password']);
$nmbr = 12; // it's the user's id.
$sql = "SELECT * FROM user WHERE iduser = $nmbr";
$res = mysqli_query($conn, $sql);
// $row = mysqli_fetch_assoc($res);
while($row = $res->fetch_assoc()) {
$hashFromDB = $row['hash'];
}
if(password_verify($passwordFromForm, $hashFromDB)) {
echo "success";
header("Location: ../admin.php");
}
else {
echo "The hash is:" . $hashFromDB . "and the pass is:" . $passwordFromForm;
//this echoes the correct hash and string
}
Thanks in advance.
The function password_verify() is dependent with password_hash(), you can check the algorithm password_hash() used whether the same with password_verify(), check the res with password_get_info($hash)
You should not do any escaping of the password, before feeding it to the password_hash() / password_verify() function. So remove the call to htmlspecialchars() and make sure that your database field holding the hash, is of type varchar(255).
I've a problem when updating the old password with the new one password_hash, it always said Old password is wrong.
The table: pegawai
Field: nokom, nama, uol1
Here's my code:
<?php session_start();
require "config.php";
$nokom = $_POST['nokom'];
$pswlama = password_hash($_POST['pswlama'], PASSWORD_DEFAULT);
$pswbaru = password_hash($_POST['pswbaru'], PASSWORD_DEFAULT);
$cari = "SELECT * FROM pegawai WHERE nokom ='".$nokom."'";
$result = mysqli_query($conn,$cari);
if (mysqli_num_rows($result) > 0)
{
while ($data = mysqli_fetch_array($result))
{
if(password_verify($pswlama, $data['uol1']))
{
$perintah = "UPDATE pegawai SET uol1 = '$pswbaru' WHERE nokom = '$nokom' ";
if (mysqli_query($conn, $perintah))
{
echo "<script>alert('Success');location.replace('home.php')</script>";
}
else
{
echo "Error updating record: " . mysqli_error($conn);
}
}
else
{
echo "<li>Old password is wrong!</li>";
}
}
}
else
{
echo "Data not found";
}
?>
Any help will be great, thanks.
You are putting a hash in both arguments of password_verify. Read the manual of password_verify and you'll see that the first argument is not supposed to be a hash, but the password itself to compare against the hashed password (argument 2) that is stored in your database.
You are hashing the password before you pass it to password_verify here:
$pswlama = password_hash($_POST['pswlama'], PASSWORD_DEFAULT);
...
if(password_verify($pswlama, $data['uol1']))
You should be passing $_POST['pswlama'] directly to password_verify.
change this
$pswlama = password_hash($_POST['pswlama'], PASSWORD_DEFAULT);
to this. password_verify will handle the rest.
$pswlama = $_POST['pswlama'];
keep the rest of your code the same.
When a user creates a account on my website then their password is stored using SHA512. My problem is when the user tries to login with their password, i believe i am verifying the password incorrectly however i cannot see what i have done wrong.
Here is my register script which works :
$uname = mysql_real_escape_string($_POST['uname']);
$sname = mysql_real_escape_string($_POST['sname']);
$email = mysql_real_escape_string($_POST['email']);
$upass = mysql_real_escape_string($_POST['pass']);
$upass = hash('SHA512', $upass);
The password 'Test' is stored in the database as:
ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f88
Here is my login script:
if($row['password']==hash('SHA512', $upass))
{
$_SESSION['user'] = $row['user_id'];
header("Location: account.php");
If any body could please edit my login code so that it can retrieve and verify the SHA512 string then it would be greatly appreciated.
I am not worried about totally changing my login system to make it more secure, it is a very simple system which is only used to store a users preferences for the site, please could we just sick to using SHA512.
Here is the hash_equals() for php version >= 5.6.0 If you are using lower version then you can use code from below.
if(!function_exists('hash_equals')) {
function hash_equals($str1, $str2) {
if(strlen($str1) != strlen($str2)) {
return false;
} else {
$res = $str1 ^ $str2;
$ret = 0;
for($i = strlen($res) - 1; $i >= 0; $i--) $ret |= ord($res[$i]);
return !$ret;
}
}
}
Matching hash.
$expected = crypt('Test', '$2a$07$addsomecustomstring$');
$correct = crypt('Test', '$2a$07$addsomecustomstring$');
$wrong = crypt('tets', '$2a$07$addsomecustomstring$');
var_dump(hash_equals($expected, $correct)); //true
var_dump(hash_equals($expected, $wrong)); //false
Since you already calculated hash above you no longer need to call hash function again in comparison:
if($row['password']==$upass)
instead of:
if($row['password']==hash('SHA512', $upass))
I create a function to edit user password here the function code.
function updateUser ()
{
$current = md5($_POST['cpassword']);
$new = md5($_POST['npassword']);
$newc = md5($_POST['npasswordc']);
$name = $_POST['username'];
connectDB();
$check = mysql_query("SELECT password FROM user WHERE user_name = '$name'")
or die(mysql_error());
if ($check != $current) {
?> <div id="error">
<?php die('Current password is wrong. Press back to try again.'); ?>
</div> <?php
}
if ($new == $newc) :
$sql = "UPDATE user SET password = '$new' WHERE user_name = '$name'";
execute($sql);
?> <div id="error">
<?php die('Password Successfully Updated. Back to dashboard');
?> </div> <?php
else : ?> <div id="error">
<?php die('New Password did not match. Press back to try again');
?> </div> <?php
endif;
}
the value will be pass by the form on different page, everything seem to work fine. When I try to change password, it say successful, and when I check in the database, the md5 value is changing that mean the password was change.
But when I try to change password of same username, I still need to enter the old password for current password, even though in database it already changed?
What seem to be the problem?
Thank you
$check is a mysql resource, not a value. You might do
if($check && (mysql_num_rows($check) > 0))
{
$res = mysql_fetch_assoc($check);
if($res['password'] != $current) {
Be careful of SQL injections, you should do at least
$name = mysql_real_escape_string($_POST['username']);
before entering it into the query.
Also, md5 is a week hashing algorithm, I strongly suggest you use a SALT, and better hash algos like at the very least sha1() or better go for the sha2 family (sha256, sha512, for ex) or bcrypt
I have changed your code... maybe it works. also watch the comments it explains something maybe it helps:
function updateUser ()
{
$current = md5($_POST['cpassword']);
$new = md5($_POST['npassword']);
$newc = md5($_POST['npasswordc']);
// first check if the passwords matches if not why waist the connection
if ($new == $newc) {
$name = $_POST['username'];
connectDB();
// why not checking your pass in the query
// when a result is zero it means there is no match found
$check = mysql_query("SELECT password FROM user WHERE user_name = '{$name}' AND password = '{$current}'") or die(mysql_error());
$result = mysql_fetch_assoc($check);
// You where checking a resource with a string(MD5)?
if (mysql_num_rows($check) == 0) {
?><div id="error">
<?php die('Current password is wrong. Press back to try again.'); ?>
</div><?php
return false;
} else {
// update the query with the ID you got from the check..
// why? because a ID is always unique
$sql = "UPDATE user SET password = '{$new}' WHERE user_id = '{$result['user_id']}'";
execute($sql);
?><div id="error">
<?php echo 'Password Successfully Updated. Back to dashboard';
?></div><?php
return true;
}
} else {
?><div id="error">
<?php echo 'New Password did not match. Press back to try again';
?></div><?php
return false;
}
}