Verify hashed passwords using PHP from a MySQL database [closed] - php

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I'm trying to develop a login form using HTML, PHP, and SQL. I'm scratching my head on trying to figure out what my issue is and how to fix it as I'm relatively new to PHP, so I'd appreciate some help. What I want to do is to check if the user's input on the HTML login form (in this case the password) matches the hashed password that is stored inside the database.
However, I'm currently having an issue where it doesn't do that. The code should verify the password and if it is correct, it should echo "password and username match" else it should echo "incorrect password" however the code does not echo anything.
Here is what I've tried:
get password using username
I am using PHP's password_hash plugin to hash and verify the user's password.
So my question is, how do I securely verify the user's input (the password) with the hashed password that is stored inside the database?
Here is the PHP code:
if($_SERVER["REQUEST_METHOD"] == "POST") {
//declare variables and set values to null
$username = $pass = "";
$username = $_POST['username'];
$pass = $_POST['pass'];
//check if username exists
$stmt = $conn->prepare("SELECT userName FROM userDetails WHERE userName=?");
$stmt->bind_param("s", $prepname);
$prepname = $username;
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
//if username exists, check if password is linked to user
echo "user exists";
$stmt = "SELECT userPass FROM userDetails WHERE userName=?";
$stmt->bind_param("s", $prepname);
$prepname = $username;
$hashpass = $stmt->execute();
$stmt->bind_result($hashpass);
$stmt->fetch();
if (password_verify($pass, $hashpass)) {
echo "password and username match";
}
else {
echo "incorrect password";
}
}
else {
echo "That user does not exist!";
return false;
}
}
EDIT: Thanks to #Jovi, I have fixed the previous error however I am now recieving a new error:
Warning: Illegal string offset 'userPass' in /home/toeaimc2/public_html/php/pages/login.php on line 75
EDIT:
#Jovi has now solved the problem! Thank you to everyone for their help!

You are calling the bind_param method on a string, it should be a statement object.
You are missing the method call to create the prepared statement object for the query that extracts the password:
$stmt = $conn->prepare("SELECT userPass FROM userDetails WHERE userName=?");
$stmt->bind_param("s", $prepname);

Related

Unhashed password in PHP [duplicate]

This question already has an answer here:
Verifying password_hash() in PDO prepared statements
(1 answer)
Closed 7 months ago.
how I can put my variable $passHash from register function to login function
I need that cause I try to use password_verify() method which required my hash
I try additional got my hashe password from database and put to the password_verify() but it not working.
public function register($uname, $email, $pass) {
$passHash = password_hash($pass, PASSWORD_DEFAULT);
$sqlQuery="INSERT INTO UserData (userName, userEmail, userPassword) VALUES (:userName,:userEmail,:userPassword)";
$stmt = $this->db->prepare($sqlQuery);
$stmt->bindparam(':userName', $uname);
$stmt->bindparam(':userEmail', $email);
$stmt->bindparam(':userPassword', $passHash);
if($stmt->execute()) {
return true;
} else {
return $stmt->error;
}
}
public function login($emailUser,$passUser){
$sqlQuery= "SELECT * FROM UserData WHERE userEmail=? AND userPassword=? ";
// $sqlQuery.Id;
$stmt = $this->db->prepare($sqlQuery);
$stmt->execute([$emailUser, $passUser]);
$result = $stmt->fetch(PDO::FETCH_ASSOC); <-- NOT WORKING SO I try get hash variable from register function
$checkPassword=password_verify($passUser,$result["userPassword"]);
if($checkPassword==true){
if($stmt->rowCount()==0){
echo "err";
}else{
echo "success";
}
}else{
echo 'bad pass';
}
}
Steps to run a successful login attempt:
Collect the username/identifier from the login client.
$emailUser = $_POST['email'];
$passUser = $_POST['password'];
Send only that to the MySQL to retrieve only that row, including the hashed password and the row identifier.
SELECT UserId, userPassword FROM UserData WHERE userEmail=?
Using PHP check the hashed password from the database matches the value given by the user
if(password_verify($passUser, $result['userPassword']){
...
allow access....
NEVER send the password to MySQL, it's worthless.
Use $stmt->fetchAll(); to retrieve the data row
It is bad practise to do SELECT * instead you should select the columns you actually want to use.
your $stmt->rowCount()==0 clause will always fail, because it is after the password has been tested and passed, so remove this whole section.
It is bad practise to tell people specifically their password has failed, as this can be used to fish for if someone has an email on this system. Instead state "Your email OR password are incorrect" so it can't so easily be established by 3rd parties if a certain persons email is on a system.

Why are my variables coming up as undefined, des?

User registration works fine. After registration, this login page is opened and the message comes up that password, username and hash are undefined variables on my select line and when I echo the hash.
When trying to login "Invalid login credentials" error pops up, but also "Password is valid", and the hash is printed as well.
if (isset($_POST['username']) and isset($_POST['password'])){
// Assigning posted values to variables.
$username = cleanData($_POST['username']);
$password = cleanData($_POST['password']);
$hash = password_hash($password, PASSWORD_DEFAULT);
$verify = password_verify($password, $hash);
if(password_verify($password, $hash)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}
}
// Checking if the values exist in the database or not
$query = "SELECT * FROM `user` WHERE (username='$username') AND (password='$password')";
echo $hash;
$result = mysqli_query($connection, $query) or die(mysqli_error($connection));
$count = mysqli_num_rows($result);
// If the posted values are equal to the database values, then session
is created for the user.
if ($count == 1){
$_SESSION["loggedIn"] = true;
$_SESSION['username'] = $username;
}else{
// error for not matching credentials
$fmsg = "Invalid Login Credentials.";
I suspect that I have done something horribly wrong with the placement and requirements of my SELECT statement , but it still does not explain why these variables are coming up as undefined. Perhaps I can move the SELECT statement to replace the "password is valid" message and go from there?
CleanData is a function to sanitise input.
So, the issue is you're kind of doing this:
if (username and password are set) {
username = xxx
password = xxx
hash password
verify password
display results
}
do sql query based on username and password
So, you've got code outside of your original IF trying to utilize variables that might not have been created.
Your SQL query and all code after that will be called even if you did not pass username and password to the php page.
You might be better off doing something like this at the beginning of your script:
if (username and password are not both set in post vars)
display error
exit
}
username = xxx
password = xxx
Then you can be sure that those vars definitely are defined without having to check over and over in the page.
Also, the pseudocode is on purpose. Trying to get my message across in layman's terms :)
With this code, you will always receive the "password is valid" message, because you are verifying the password that the user entered against the hash that you just generated from that same password!
<!-- Incorrect code: This always determines the password is valid! -->
$hash = password_hash($password, PASSWORD_DEFAULT);
if (password_verify($password, $hash)) {
echo 'Password is valid!';
}
You are supposed to use password_hash when you are first inserting the password into the database (that way, you aren't storing the actual password, just a hash). Then, when your user logs in with their username, look in the database for a user with that username. If you find a user with that username, then you use password_verify to check that the $password variable matches the hash that was stored in the database with that user.
Check out this answer to a similar question to see a fleshed out example of login code.

Trying to verify a hashed password from database with password from login form

I am making a registration and login form, which asks for the user's email and password. In my registration file I hashed the password provided by the user, and stored it in the database, with the function password_hash. In my login form I tried to verify the password provided by the user with the stored hashed password in the database, but it fails. I used the password_verify function. Here is a snippet of the registration code:
Registration file snippet
if(!isset($error)){
//hash the password
$hashedpassword = password_hash($_POST['password'], PASSWORD_DEFAULT);
echo $hashedpassword;
try {
$sql = "INSERT INTO users (mail, password, province) VALUES (:mail, :password, :province)";
$stmt = $db->prepare($sql);
//Bind variables
$stmt->bindValue(':mail', $mail);
$stmt->bindValue(':password', $hashedpassword);
$stmt->bindValue(':province', $province);
//Execute the statement and insert the new account.
$result = $stmt->execute();
//If the signup process is successful.
if($result){
echo $hashedpassword;
exit;
}
}
catch(PDOException $e) {
$error[] = $e->getMessage();
}
}
Hashed passwords in database
For these passwords I get the following hashed passwords, which are stored in the database:
football:
$2y$10$q0Y8Mfdl75Dt8op7WaqQM.t5y4LMO6gfYwmbycL1xRMiUUQu8dtWm$2y$10$q0Y8Mfdl75Dt8op7WaqQM.t5y4LMO6gfYwmbycL1xRMiUUQu8dtWm
cricket:
$2y$10$Pyoz1XC0skRjHLjxHdrYYeYplY98w4uOp23QpZb/VNN0y41/6YPJC$2y$10$Pyoz1XC0skRjHLjxHdrYYeYplY98w4uOp23QpZb/VNN0y41/6YPJC
The type for the password row is varchar(255) and the collation is utf8mb4_general_ci The passwords are stored like this:
$2y$10$q0Y8Mfdl75Dt8op7WaqQM.t5y4LMO6gfYwmbycL1xRM...
$2y$10$Pyoz1XC0skRjHLjxHdrYYeYplY98w4uOp23QpZb/VNN...
When I hover over the passwords it says 'Original length 60'.
Login file snippet
This is a snippet of my login file code:
$mail = htmlspecialchars_decode($_POST['mail'], ENT_QUOTES);
if(!filter_var($mail, FILTER_VALIDATE_EMAIL) and !empty($_POST['mail'])) {
$error[] = 'Please enter a valid email address';
}
$stmt = $db->prepare('SELECT mail, password FROM users WHERE mail = :mail');
$stmt->execute(array(':mail' => $mail));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if(!empty($row['mail'])){
$error[] = 'Email provided is good.';
}
$password = $_POST['password'];
$stmt = $db->prepare('SELECT password FROM users WHERE password = :password');
$stmt->execute(array(':password' => $password));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$checkpass = $row['password'];
echo $checkpass;
if(password_verify($password, $row['password'])) {
$error[] = 'Password provided is good.';
}
Checking whether the email can be found in the database works fine, as it gives me the error message (which I need to change to a normal message).
But I can't get the password verification working. I tried to see what the code pulls out the database with $checkpass = $row['password']; and
echo $checkpass;
But it doesn't return anything (maybe because it only returns a 0 or 1 value?).
Maybe it has to do something with the way I try to select the hashed password out of the database? Or the way I insert them in the database, or the MySQL table options? It may be a simple fix but I tried many different things and I couldn't get it to work.. Hope you guys can help!
The second query seems to be useless since in the first query you already select the mail and password fields. So you should just need to execute the first query, check if the user is valid and then check the password with the password_verify method.
Your second query fails (probably) because in the condition you pass the cleartext but in the DB there is the hashed password so you will never find anything. To check print the second query before the execution.
Before executing query for password check in login you should create hashed password for the input password and that hashed password need to be compared

How to select a hashed password from mysql db [duplicate]

This question already has answers here:
How do I use password hashing with PDO to make my code more secure? [closed]
(3 answers)
Closed 5 years ago.
Okay, so I'm trying to make a register/login code for my personal website.
I had no troubles making the registration form but I'm having some difficulties with the login.
Here's a part of my code:
$stmt = $pdo->prepare("SELECT password FROM members where username = ? ");
$stmt->bindValue(1, $username);
$stmt->execute();
Now to my understanding i need to fetch the first row from my table convert it to a string and then using password_verify to compare that string to whatever the users inputs in the form i created. The problem i have is that it fetches an array and can't really use password_verify to compare a string to an array.
Am I doing something wrong? how should I do this?
tl; dr How do I actually select a hashed password from DB, convert it to a string and then compare that string with the password my user will input.
Thanks.
This library works on
PHP 5.5+: use password_hash
$sql = "SELECT * FROM members WHERE username = ?";
$stmt = $pdo->prepare($sql);
$result = $stmt->execute([$_POST['username']]);
$users = $result->fetchAll();
if (isset($users[0]) {
if (password_verify($_POST['password'], $users[0]->password) {
// valid login
} else {
// invalid password
}
} else {
// invalid username
}

How Can I Make This Login System More Secure

I have created this php login script. I was wondering weather it was secure and if not how could I improve it.
PHP Script
<?php
include_once ("ConnectToMySql.php");
session_start();
$username = $_POST['username'];
$username = mysql_real_escape_string($username);
$password = $_POST['password'];
$password = sha1($password);
$query = "SELECT password FROM users WHERE username = '$username';";
$result = mysql_query($query);
if(mysql_num_rows($result) < 1)
{
echo "This Username Is Not Registered!";
exit;
}
if(mysql_num_rows($result) == 1)
{
if ($password == $result)
{
echo "Logged In!";
}
else echo "Wrong Password!";
}
?>
Thanks
A first tip could be to show a common error for both invalid login cases: invalid username or password. That way an eventual attacker wouldn't know if the username is valid or not.
You could also make a single query matching both username and password. You would probably need more user information (to store in session?), so it would be a good idea to select those fields instead of the password (e.g. id, name).
Regarding the hashed password stored in the database, you could add a SALT to improve security.
http://en.wikipedia.org/wiki/Salt_%28cryptography%29
What I would do is change the query to the following:
"SELECT COUNT(*) FROM users WHERE username = '$username' AND password='$password';"
That way, you don't have to check if the password is correct afterwards (and you don't have to pass the sensitive data as well), you only have to check if the numbers of rows returned equal 1 and you can produce a single error message for both username/password.

Categories