Passwords not matching - php

I'm switching over to PDO and trying to make my passwords in the MySQL database a little bit more secure, but unfortunately I've run into a little bit of a problem.
When a user registers, their password is treated as follows:
$pass = sha1($_POST['pass']);
And when a user logs in, the password they provide is treated exactly the same ($pass = sha1($_POST['pass'];)
The idea is then that I compare the two, and if they match, the user is logged in. The difficulty is, even if I enter the same password - "password", for instance - the encrypted password put into the database on registration does not match the encryption of the password when the user attempts to log in.
Does anyone know what the issue might be?
Full code:
$user = $_POST['user'];
$pass = sha1($_POST['pass']);
echo $pass; // This was just to check the two passwords
$db = new PDO('this is all correct');
$query = $db->prepare('SELECT pass, id FROM users WHERE user=:user');
$query->bindParam(':user',$user);
$query->execute();
$result = $query->fetch();
$storedpass = $result['pass'];
$storedid = $result['id'];
if($storedpass === $pass) {
header("Location: index.php");
}
else {
echo "Something went wrong";
}

sha1 should not be used to hash passwords. See the notice in the docs. You should use the new password_hash function instead, and the matching will be handled for you by password_verify.
Switching to the new hashing functions would likely solve your password validation issue while at the same time making your app much, much more secure.
If your version of PHP is less than 5.5, the new functions aren't available. A version for PHP 5.3.7+ is available on Github https://github.com/ircmaxell/password_compat.

You'd actually be much better off doing something like this:
$user = $_POST['user'];
$pass = sha1($_POST['pass']);
echo $pass; // This was just to check the two passwords
$db = new PDO('this is all correct');
$query= $db->prepare("SELECT id FROM users where user=:user AND pass=:pass");
$query->execute(array(':user' => $user, ':pass' => $pass));
if ($query->rowcount() == 1){
// authenticated
}else{
// not authenticated
}
Don't know if this will solve your problem though.

Related

About hashing passwords with argon2i

I set up a dev server and I installed nginx with php-fpm and 7.2 php (I installed all the necessary php packages).
The time has come to upgrade the security of all logins, using the argon2i algo.
So, I tried this (test code in dev enviroment. The security in the code, will come later):
require('connector.php');
$usr_u = $_POST['username'];
$psw_u = $_POST['password'];
$usr = mysqli_real_escape_string($conn, $usr_u);
$psw = mysqli_real_escape_string($conn, $psw_u);
$f_pass = password_hash($psw, PASSWORD_ARGON2I);
$result = "SELECT `username` FROM `users` WHERE username = '$usr'";
$tbl = mysqli_query($conn, $result);
$table = $tbl->fetch_assoc();
$m_user = $table['username'];
if ($m_user == $usr)
{
//correct username
echo 'Correct username!<br>';
$result = "SELECT `password` FROM `users` WHERE username = '$m_user'";
$tbl = mysqli_query($conn, $result);
$table = $tbl->fetch_assoc();
$m_pass = $table['password'];
if (password_verify($m_pass,$f_pass)) //always returns false
{
echo 'Password correct!<br>';
}
else
{
echo 'Wrong password!<br>';
}
}
else
{
echo 'Wrong username!<br>';
}
//close connection
mysqli_close($conn);
I always get "Correct username!" and "Wrong password!". I used echo on hashed password from the DB and from the input and I see that every time the hashed password is different. I assume that the hashing process, include using random salt and there is my issue.
As far as I understand, the random salt is necessary in order to retain the security of the hashing.
Can you please point me to the right direction, on how to solve this? I have the hashed password in my DB and I can't figure out a way to check the input password against the one in my DB (using password_verify and hash_equals).
Thank everyone in advance for the help.
Look at the documentation for password_verify:
bool password_verify ( string $password , string $hash )
The first argument is the password but you are passing it the hash you want to compare it to.
The second argument is the hash you want to compare it to but you are passing it a new hash created from user input.
password_verify($_POST['password'], $m_pass)

PHP password_verify not working need to get result DOMAIN SPECIFIC

So in my function I have the connection, the query which will result in 1 row and 1 column displayed. I then want to run the password_verify() This is where I am struggling. As the first parameter I have placed $pass which is user entered but then I need to get the result from the database to place in the 2nd parameter.
How would I do this?
function login($user, $pass){
$conn = connect();
$query = "SELECT password FROM account WHERE username = '$user' AND password = '$pass'";
$result = mysqli_query($conn, $query);
if (mysqli_num_rows($result)=== 1){
password_verify($pass, "$row[password]");
session_start();
If you do everything right your password field in a account table stores hashed password.
And argument $pass of a function is a plain password, I suppose.
So, your query
SELECT password FROM account WHERE username = '$user' AND password = '$pass'
will NEVER find any user, as you try to find user by plain password.
In addition - your $row variable is not defined.
What's the solution:
function login($user, $pass){
$conn = connect();
// do not add password to query
$query = "SELECT password FROM account WHERE username = '$user'";
$result = mysqli_query($conn, $query);
if (mysqli_num_rows($result) === 1){
// define $row
$row = mysqli_fetch_assoc($result);
// set proper quotes and compare password
// from db with password input by user
if (password_verify($pass, $row["password"])) {
// do something if password is correct
session_start();
And of course, instead of passing values directly to query, start using prepared statements.
When someone registers on your website, you have to use de built-in PHP function password_hash(). Also, I suggest naming it "password_hash" in your database and not "password" as to avoid confusion.
When someone tries to log in on your website, you have to use the built-in PHP password_verify() to compare the hashed password with the password.
// Login function
function login($user, $pass)
{
// Search the user by username
$conn = connect();
$query = "SELECT password_hashed FROM account WHERE username = '$user'";
$result = mysqli_query($conn, $query);
if (mysqli_fetch_row($result))
{
// We found the user, check if password is correct
if(password_verify($pass, $result["password_hashed"]))
{
return true;
}
else
{
return false;
}
}
else
{
// We didn't find the user
return false;
}
}
-Why should you hash the password when you store it into the database? Because when you store the password without hashing, the password in the database is exactly the same like what the user types in when registering. So when a hacker gets into the database, he sees the passwords of every user. If you hash the password, PHP makes the password into something completely else, that way when a hacker gets into the database he doesn't see the password but something completely else.
-The password_verify function is definitely the way to go when a user logs in. Just don't forget to add extra security when you enter data you receive from a user (through $_POST, $_GET, $_SESSION, ...) because when a user types in the follow name: my name" DROP TABLES account; they will delete all account informations.

Authentication failed, even password is correct, using bcrypt hash method

I am having problem with bcrypt hash method and mysql. I'm using the Bcrypt class from this answer.
I am creating login script and checking, if password is
correct. I am comparing password from input and hashed
password from DB.
$username= $_POST['username']; //username from input
$pass= $_POST['pass']; //username from input
$query= mysql_query("SELECT pass FROM users WHERE username='$username'");
$row= mysql_fetch_row($query);
$row[0];// hashed password, I echo $row[0] and it shows correct hashed password
$bcrypt = new Bcrypt(15);
$isGood = $bcrypt->verify($pass, $row[0]);
if ($isGood){
echo "Authentication succeeded";
}
else {
echo"Authentication failed";
}
Even $pass is correct, I always get 'Authentication failed'.
Any ideas, what can be wrong?
Thank you in advance.
The pass column in your users table is not wide enough to store the complete hash; it should be at least 60 characters wide, i.e. VARCHAR(60).
Btw, you should check out PasswordLib as well, written and maintained by ircmaxell, which also supports Bcrypt quite well.
Try something like this:
$bcrypt = new Bcrypt(15);
$hash = $bcrypt->hash($pass);
echo $hash.' =? '.$row[0];
And look if it's equal
if yes, try something like this:
var_dump($hash);
var_dump($row[0]);
Must be equal

Password look up

Need a bit of help with a form. I have created a form which require log in. Once a person has logged in they complete the form and then someone else checks the form and enters there password before the form is submitted.
I have set up some rules which checks the fields are completed correctly and I want to write some code that will check the password field is completed and then check it against the stored passwords in the database.
So far I have got this.
if (!empty($_POST['password']))
{
/*connect to database to check password is valid*/
$user_name = "contains username for database";
$pass_word = "contains password";
$database = "name of database";
$server = "localhost";
$db_handle = mysql_connect($server, $user_name, $pass_word);
$db_found = mysql_select_db($database, $db_handle);
if ($db_found) {
$uname = quote_smart($uname, $db_handle);
$pword = quote_smart($pword, $db_handle);
$SQL = "SELECT * FROM masterpass WHERE password = $password";
$result = mysql_query($SQL);
$num_rows = mysql_num_rows($result);
if ($result) {
if ($num_rows > 0) {
continue;
}
else {
$error = true;
}
Not sure if I am going about this the right way so any help would be great.
Thanks in advance
Matt
for starters, first you create $pword:
$pword = quote_smart($pword, $db_handle);
and in your query you use $password.
$SQL = "SELECT * FROM masterpass WHERE password = $password";
This can't work.
Secondly, you should ask for username AND password in your query.
Last but not least: never save a password in clear text in your database. Generate a MD5 hash!
I have set up some rules which checks the fields are completed correctly and I want to write some code that will check the password field is completed and then check it against the stored passwords in the database.
No, you don't. Checking to see if the password is already in the database is not a very smart thing to do, as that opens your application to brute-forcing attacks. I could use your form to determine which passwords are used, and if I can get a list of your users, I can try each of those passwords to each of those users and get access.
Secondly, quote_smart is probably not smarter than mysql_real_escape_string. Use that instead.
Thirdly, as Sascha already mentions, please generate a hash. I wouldn't use MD5, but sha1 instead, but even using MD5 without salt already increases the security in your form dramatically.
My mantra on validating passwords is: make sure it's longer than 7 characters, that's it. Don't make assumptions on what password people should use. I hate it if I type in a password and some validation routine tells me I can't use {^ in my password.

Need help making login page with salts

Alright, I'm trying to make a login page. It seems that all of the pages worked pretty good- until I added salts. I don't really understand them, but doing something as basic as I am shouldn't be to hard to figure out. Here's "loginusr.php":
<html>
<body>
<?php
//form action = index.php
session_start();
include("mainmenu.php");
$usrname = mysql_real_escape_string($_POST['usrname']);
$pass = $_POST['password'];
$salt = $pass;
$password = sha1($salt.$pass);
$con = mysql_connect("localhost", "root", "g00dfor#boy");
if(!$con)
{
die("Unable to establish connection with host. We apologize for any inconvienience.");
}
mysql_select_db("users", $con) or die("Can't connect to database.");
$select = "SELECT * FROM data WHERE usrname='$usrname' and password='$password'";
$query = mysql_query($select);
$verify = mysql_num_rows($query);
if($verify==1)
{
$_SESSION["valid_user"] = $usrname;
header("location:index.php");
}
else
{
echo "Wrong username or password. Please check that CAPS LOCK is off.";
echo "<br/>";
echo "Back to login";
}
mysql_close($con);
?>
</body>
</html>
I used the command echo $password; to show me if the password in the database matched with the script. They did. What am I doing wrong?
It seems like you've misunderstood salts, since you're setting $salt to be the password.
A salt should be a completely random string that's stored in a user record along with the password hash. A new unique salt should be generated for every user. So you need to add a new column to your database, called "password_salt" or similar.
Rather than trying to use the password in the SELECT query and see if you get any records, you actually need to just SELECT using the username/user_id in order to get the password hash and salt so that you can then use those to determine if the user entered the correct password.
When you sign up new users you should add the fields with values like this,
<?php
// This is registeruser.php
$salt = substr(sha1(uniqid(rand(), true)), 0, 20);
$pass = $_POST['password'];
$pass_to_store = hash("sha256", $salt.$pass);
// Then issue a DB query to store the $salt and $pass_to_store in the user record.
// Do not store $pass, you don't need it.
// e.g. INSERT INTO users ('username', 'password_salt', 'password_hash') VALUES (:username, :salt, :pass_to_store);
?>
Then to check the password is the same when logging in, you do something like this,
<?php
// This is loginuser.php
$user = // result from SQL query to retrieve user record
// e.g. SELECT password_hash, password_salt FROM users WHERE username='from_user'
$salt_from_db = $user['password_salt'];
$pass_from_db = $user['password_hash'];
if ($pass_from_db == hash("sha256", $salt_from_db.$_POST['password'])
{
// Password matches!
}
?>
Don't forget to sanitize user inputs and anything you're putting into your database. You might want to look into using prepared statements instead of having to remember to use mysql_real_escape_string all the time.
It looks like you're salting with the same password? Normally a salt would be a random key that is specific to your site that you prepend to the password input, which it looks like you're doing fine. Just make sure you're using that same salt for checking that you use when the password is created.
Also, to use sessions properly you need to have session_start before anything is output to the page:
<?php
session_start();
?>
<html>
<body>
...
A salt is a random value to prevent an attacker from just looking up the source of a hash in table generated based on common passwords. (Using the username as salt is obviously not a good idea as it only adds very little entropy).
So you need to store the salt in the database and read it from the database in order to calculate the salted password hash for comparison with the stored value.
You misspelled username a couple of times, is it misspelled in the database, too?

Categories