1

I have used PHP in the past a small amount for projects and such however am trying something new with attempting to hash passwords.

On a separate page there is a web form that redirects on submit to a checkRegistration.php form which then connects to the database, takes the users values, verifies them and enters them into their respective columns.

So far all the values are being passed across are entering correctly except the ones being passed by the password_hash function which are being entered as "0" or empty. I think as it's 0 its not being handled correctly and was wondering what I'm doing wrong.

<?php
$con = mysqli_connect("127.0.0.1","root","","projectdatabase");


if (mysqli_connect_errno())
 {
  echo "Failed to connect to MySQL: " . mysqli_connect_error();
 }

 $password_user_input = $_POST['password'];
 $options = array('cost' => 10);


$sql="INSERT INTO user_information (firstName, lastName, userName, password, email, contactNum)
VALUES
('$_POST[firstname]','$_POST[lastname]','$_POST[uname]','password_hash($password_user_input, PASSWORD_BCRYPT, $options)','$_POST[email]','$_POST[number]')";

if (!mysqli_query($con,$sql))
{
  die('Error: ' . mysqli_error($con));
}
  header("location:login.php");

mysqli_close($con);

?>

Stuart_M65
  • 17
  • 7
  • 2
    You really should use [prepared statements](http://en.wikipedia.org/wiki/Prepared_statement). It is likely because you're not sending anything to the `password_hash()` function. Add error reporting to the top of your file(s) right after your opening ` – Jay Blanchard May 01 '15 at 21:38
  • If `password_hash` fails, it returns false, which is probably saved as `0`, as noted by Jay above, turn on error reporting to see what fails, and it wouldn't really matter that the password is secure as you're wide open to SQL injection by inserting the POST values directly in the query. – adeneo May 01 '15 at 21:40
  • 1
    The reason it's not working is because the `password_hash` function is inside a string. You should probably hash the password and save this as a variable. And as @JayBlanchard said, use prepared statements. – Mike May 01 '15 at 21:40
  • Also, what is the MySQL column type of `password`? – Mike May 01 '15 at 21:41
  • Mike, the column type is integer. – Stuart_M65 May 01 '15 at 21:43
  • Remember to ping people by putting an @ sign and typing their name without spaces so they get notified of your reply. Like this: @JayBlanchard – Mike May 01 '15 at 21:43
  • 1
    That's one of your problems. Set it to varchar(255), not integer. – Mike May 01 '15 at 21:44
  • Apologies @Mike I'm new so just coming to terms with the site, I switched the DB column to VarChar which in hindsight makes perfect sense and the entry is blank so it most definitely seems to be not sending. – Stuart_M65 May 01 '15 at 22:04
  • @JayBlanchard, thanks for the tip on prepared statements, there new to me but I'm looking into them now. – Stuart_M65 May 01 '15 at 22:05
  • *"I have a previous web form handling user registration which then POSTS..."* - I'm not grasping the question. Is it working or is it not? – Funk Forty Niner May 01 '15 at 22:48
  • @Fred-ii- the form is working no problem and when I pass the data through without hashing it enters flawlessly. I was attempting to say the forms POSTS to the check_registration form. The problem I was having is when I try introduce the password_hash() function is that it was not entering null values which then doesn't work. – Stuart_M65 May 01 '15 at 23:01
  • I've posted an answer below to explain was happening with your code. – Funk Forty Niner May 01 '15 at 23:05
  • Is the question still open? By the way, your comment above had no bearing on what I posted. I didn't see your comment till only after I posted my answer. If it did solve it, the question can be closed by accepting my answer. You're under no obligation, but this will inform the community that is has been solved. Otherwise, your question will remain in the unanswered category. – Funk Forty Niner May 02 '15 at 00:10
  • @Fred-ii- Apologies, I have been in work and unable to reply. Yes, that solved my problem, thank you for the very thorough answer. I am working on the verify side now but with your post below it will be far easier to get working. Thanks again. – Stuart_M65 May 02 '15 at 13:26
  • Not a problem Stuart and you're very much welcome and glad to know that it has been resolved. I wasn't sure if you had seen my answer or that you had already solved it. *Cheers* – Funk Forty Niner May 02 '15 at 13:29

1 Answers1

5

You're not using the password_hash() function correctly, and you can't pass a function in your VALUES.

You would have, or should have received an error telling you about it being an undefined function, or the password column would contain password_hash(hashed_password_string, PASSWORD_BCRYPT, Array) as a string. Those are two results that I received when testing.

Here's what you need to do.

You need to pre-defined the variable and passing it to the function.

$password_user_input = $_POST['password'];
$options = array('cost' => 10);

$pass = password_hash($password_user_input, PASSWORD_BCRYPT, $options);

$sql="INSERT INTO user_information (firstName, lastName, userName, password, email, contactNum) 
VALUES 
('$_POST[firstname]','$_POST[lastname]','$_POST[uname]','$pass','$_POST[email]','$_POST[number]')";

However, using this method leaves you open to SQL injection.

Use prepared statements, or PDO with prepared statements, they're much safer.


Here is a method pulled from ircmaxell's answer https://stackoverflow.com/a/29778421/ using PDO with prepared statements.

Just use a library. Seriously. They exist for a reason.

Don't do it yourself. If you're creating your own salt, YOU'RE DOING IT WRONG. You should be using a library that handles that for you.

$dbh = new PDO(...);

$username = $_POST["username"];
$email = $_POST["email"];
$password = $_POST["password"];
$hash = password_hash($password, PASSWORD_DEFAULT);

$stmt = $dbh->prepare("insert into users set username=?, email=?, password=?");
$stmt->execute([$username, $email, $hash]);

And on login:

$sql = "SELECT * FROM users WHERE username = ?";
$stmt = $dbh->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
}
Community
  • 1
  • 1
Funk Forty Niner
  • 74,450
  • 15
  • 68
  • 141
  • Very thorough, nice work – scrowler May 01 '15 at 23:20
  • Just a note, I don't know how much *other* code is in the OP's website, but he's currently using mysqli, not PDO, so it might be better to give an example using mysqli prepared statements. Great answer though, +1. – Mike May 02 '15 at 00:51
  • @Mike Thanks Mike. I like using ircmaxell's PDO example as a generic method for prepared statements. However, I do agree that there should be a `mysqli_` with prepared statements example, but TBH, I haven't made one up yet. Soon as I do, I will make it part of my future examples, and possibly in this answer soon as I get to my coding machine. I'm not on it right now, but I will be either later tonight, or sometime tomorrow. *Cheers* – Funk Forty Niner May 02 '15 at 00:54
  • @Mike Matter of fact, I think all that needs to be changed from the PDO example are the `new PDO(...)` and `$users = $result->fetchAll();`. Everything else uses the same syntax as `mysqli_`, being prepare and execute. – Funk Forty Niner May 02 '15 at 00:59
  • @Fred-ii- Ah, I misread you wrote the example yourself. No soup for you! – Mike May 02 '15 at 01:04
  • @Mike Hahaha! That's ok, I'll just make my own ;-) Hm... beef barley, or chicken and rice, what to choose, what to choose. – Funk Forty Niner May 02 '15 at 01:13