Search code examples
phpsqlpassword-hash

Updating SQL password with default password hash prevents logins


I followed this tutorial to create a login system for my website, which has worked fine until now. I followed the steps exactly, creating all of the files needed etc. Users, when logged in as themself, are able to change their password no problem.

However, I've now created a protected directory which allows other users to reset the passwords of other users (in case they have forgotten them). This code is below:

(I've included all of the code for that page, except some of my styling elements (e.g. menu bar that sits above the rest of this code). While I understand this may not be the best way, I wanted to ensure I was giving you all as much information as possible.)

<?php
// Initialize the session
session_start();
 
// Check if user is logged in. If N, return to /login/
if(!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true){
    header("location: /login/");
    exit;
} ?>



<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>DAT Room Bookings</title>
<meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Scales to mobile -->
<link rel="stylesheet" type="text/css" href="style.css"> <!-- System style -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> <!-- Icons -->
<link href="https://fonts.googleapis.com/css?family=Lato&display=swap" rel="stylesheet"> <!-- System font -->
<link rel="stylesheet" href="scripts/lightbox2-2.11.1/src/css/lightbox.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script> <!-- Drop Down Images -->
<script src="scripts/lightbox2-2.11.1/src/js/lightbox.js"></script> <!-- Lightbox Images -->
</head>
<?php

/*

EDIT.PHP

Allows user to edit specific entry in database

*/

// creates the edit record form

// since this form is used multiple times in this file, I have made it a function that is easily reusable

function renderForm($id, $username, $password, $error)

{

?>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>

<head>

<title>Edit Record</title>

</head>

<body>

<?php

// if there are any errors, display them

if ($error != '')

{

echo '<div style="padding:4px; border:1px solid red; color:red;">'.$error.'</div>';

}

?>


<form action="" method="post">

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

<div style="padding-left:25%; padding-right:25%; padding-top:10px">

<p><strong>User ID:</strong> <?php echo $id; ?></p>

<strong>Username:</strong> <input type="text" name="username" value="<?php echo $username; ?>" readonly /><br/>

<strong>Enter New Password: *</strong> <input type="text" name="password" value=""/><br/>

<p>* Required</p>

<input type="submit" name="submit" value="Submit">

</div>

</form>

</body>

</html>

<?php

}


// connect to the database

include('connect-db.php');

// check if the form has been submitted. If it has, process the form and save it to the database

if (isset($_POST['submit']))

{

// confirm that the 'id' value is a valid integer before getting the form data

if (is_numeric($_POST['id']))

{

// get form data, making sure it is valid

$id = $_POST['id'];

$username = mysql_real_escape_string(htmlspecialchars($_POST['username']));

$password = mysql_real_escape_string(htmlspecialchars($_POST['password']));

$hashed = password_hash('$password', PASSWORD_DEFAULT);

// check that password fields are both filled in

if ($password == '')

{

// generate error message

$error = 'ERROR: Please fill in all required fields!';


//error, display form

renderForm($id, $username, $password, $error);

}

else

{

// save the data to the database

mysql_query("UPDATE users SET username='$username', password='$hashed' WHERE id='$id'")

or die(mysql_error());


// once saved, redirect back to the view page

header("Location: view.php");

}

}

else

{

// if the 'id' isn't valid, display an error

echo 'Error!';

}

}

else

// if the form hasn't been submitted, get the data from the db and display the form

{


// get the 'id' value from the URL (if it exists), making sure that it is valid (checing that it is numeric/larger than 0)

if (isset($_GET['id']) && is_numeric($_GET['id']) && $_GET['id'] > 0)

{

// query db

$id = $_GET['id'];

$result = mysql_query("SELECT * FROM users WHERE id=$id")

or die(mysql_error());

$row = mysql_fetch_array($result);



// check that the 'id' matches up with a row in the databse

if($row)

{


// get data from db

$username = $row['username'];

$password = $row['password'];


// show form

renderForm($id, $username, $password, '');

}

else

// if no match, display result

{

echo "No results!";

}

}

else

// if the 'id' in the URL isn't valid, or if there is no 'id' value, display an error

{

echo 'Error!';

}

}

?>

The form displays correctly and pulls through the ID and username of the user. I set up the password hash the same as I can see it in the change password function of my site (using the default values). When I try to reset another user's password, I can see in phpmyadmin that the hash has changed, which would therefore mean the changes have gone through correctly.

However, and this is the issue, when said user then tries to log in again using the new password, they are told that the password is incorrect. I've looked at the codes side by side, but I must admit, being a newcomer to PHP, I have very little idea what most of the code in the tutorial is doing, which is why for this function I've tried to create myself a simplified version to just perform this function.

Apologies if this is a straightforward error, but I really can't understand it.


Solution

  • You are saving password here as

    $hashed = password_hash('$password', PASSWORD_DEFAULT);
    

    You don't need single quotes around $password here. Additionally, are you sure that in the login page, while validating the credentials, a similar kind of logic is used?. May be like

    $user['password'] == password_hash($_POST['password'],PASSWORD_DEFAULT)
    

    where $user is retrieved from the database.