Secure form handling using stmt prepare - php

The prepare function is not recognizing members that already exist in the DB and as a result, always calls the function NewUser() when it is supposed to go through the else statement? I believe this is because when I ask it to verify the password, it encounters an error, but I have no idea what I am doing wrong?
function NewUser(){
global $dbh;
$fullname = trim($_POST['fullname']); //at a minimus clear whitespace.
$username = trim($_POST['username']);
$email = trim($_POST['email']);
$user_password = trim($_POST['password']);
$options = [
'cost' => 12, //higher = more lower= less. you want it to take around 0.4 seconds for security reasons!
];
$hashed_password = password_hash($user_password, PASSWORD_DEFAULT, $options); // hashed password for storage!
$stmt = $dbh->prepare("INSERT INTO USERS(fullname, username, email, password) VALUES('$fullname', '$username', '$email', '$hashed_password')");
$stmt->bindValue(1,$fullname,PDO::PARAM_STR);
$stmt->bindValue(2,$username,PDO::PARAM_STR);
$stmt->bindValue(3,$email,PDO::PARAM_STR);
$stmt->bindValue(4,$user_password,PDO::PARAM_STR);
if($stmt->execute()){
echo "<div class= container>","<div class = \" col-md-2 connout slideInTop\">"," <span class = \"username_text\">$username</span>, <br> welcome to <br> the <br> <span class = \"vibecourt_text\">VIBECOURT</span> family! <br><br> You may <br> now sign in <br> below","</div>","</div>";
}
}
function SignUp(){
global $dbh;
//checking the 'user' name which is from index.php, is it empty or have some text
if(!empty($_POST['username'])){
$username = trim($_POST['username']);
$password = trim($_POST['password']);
$stmt = $dbh->prepare("SELECT * FROM USERS WHERE (username = ? AND password = ?)");
$stmt->bindValue(1, $_POST['username'],PDO::PARAM_STR);
$stmt->bindValue(2, $_POST['password'],PDO::PARAM_STR);
$stmt->execute();
$selected_row = $stmt->fetch(PDO::FETCH_ASSOC);
//check password agaisnt stored hash
if(!password_verify($password, $selected_row['password'])) {
NewUser();
}
else{
echo("<script>location.href = 'pages/home/home.php'</script>");
}
}
}
SignUp();

Updated Answer
In light of what transpired in comments... it appears the issue is further rooted far above where you are originally storing the hashed password into the database.
You say you are using a varchar(50), for a password_hash value. This is too short, and mysql is no doubt clipping the INSERT. This will result in hashes that can never be matched.
You should have a varchar(60) at the very minimum, but PHP.net states that this hash can grow over time, and using a varchar(255) is recommended.
In this bit:
$stmt = $dbh->prepare("SELECT * FROM USERS WHERE (username = ? AND password = ?)");
$stmt->bindValue(1, $_POST['username'],PDO::PARAM_STR);
$stmt->bindValue(2, $_POST['password'],PDO::PARAM_STR);
You are trying to match the hashed value in the database, with a user inputted password (which is not hashed).
You should simply remove the AND password = ? and bindValue for it. That way it pulls a matching username entry from the db, and THEN does password_verify to determine if the user inputted password, matches:
$username = trim($_POST['username']);
$password = trim($_POST['password']);
$stmt = $dbh->prepare("SELECT * FROM USERS WHERE username = ?");
$stmt->bindValue(1, $username, PDO::PARAM_STR);
$stmt->execute();
$selected_row = $stmt->fetch(PDO::FETCH_ASSOC);
if(!password_verify($password, $selected_row['password'])) {
NewUser();
}
Side note: Although I'm not sure you really WANT to make a new user if they simply typed in the wrong password??? Surely you would handle that differently. Telling them they entered a wrong password and should try again.
EDIT
Also in your NewUser function you have this:
$stmt = $dbh->prepare("INSERT INTO USERS(fullname, username, email, password)
VALUES('$fullname', '$username', '$email', '$hashed_password')");
It should be this:
$stmt = $dbh->prepare("INSERT INTO USERS(fullname, username, email, password)
VALUES(?, ?, ?, ?)");
// ...
$stmt->bindValue(4,$hashed_password,PDO::PARAM_STR);// <- use $hashed_password

Related

PHP password_verify

I am working on making a login section for my project website using PHP, but for some reason, verify_password won't return true, even when I am giving the correct password. No idea what I am doing wrong here.
Here is the code that I use to add the user to the MySQL table:
$password= $_POST['password'];
$hash = password_hash('$password', PASSWORD_DEFAULT);
// I know this isn't inject proof
$res = $conn->prepare('INSERT INTO login (SSN, UserName, passhash) VALUES (:SSN, :UserName, :passhash)');
$res->bindValue(':SSN', $_POST['UserName']);
$res->bindValue(':UserName', $_POST['UserName']);
$res->bindValue(':passhash', $hash);
$res->execute();
It stores the hash in a varchar(60)
Here is the code that takes the password, and verifies it against the hash:
$userName = $_POST['UserName'];
$password= $_POST['password'];
// I doubt this is inject proof
$res = $conn->prepare("select passhash from login where UserName='$userName'");
//$res->bindValue(':SSN', $_POST['UserName']);
//$res->bindValue(':UserName', $_POST['UserName']);
//$res->bindValue(':hash', $hash);
$res->execute();
$result = $res->fetch();
if(!empty($result) && password_verify($password, $result['passhash']))
What can I try next?
Single quotes prevent variable interpolation, so this encodes the literal string $password as the password:
$hash = password_hash('$password', PASSWORD_DEFAULT);
Just use the variable directly:
$hash = password_hash($password, PASSWORD_DEFAULT);

Login page keeps showing error PHP and MySQL

I am having issues getting some simple (or it seems simple) coding to cooperate. I've tried stripping it completely and typing everything out. Here is the code:
<?php
session_start();
if(isset($_POST['login'])) {
$username = trim($_POST['username']);
$password = md5(trim($_POST['password']));
include('includes/admin.php');
$sql = "SELECT * FROM users WHERE username='$username' AND password='$password'";
$result = mysqli_query($con, $sql);
if(mysqli_num_rows($result) == 0) {
echo '<p>Incorrect login.<br>Return to Login Page</p>';
} else {
$_SESSION['user'] = $username;
echo '<p>Login successful.<br>Go to Admin Page</p>';
}
}
?>
The goal is to have it redirect to the login page if unsuccessful and to redirect to another admin page if successful. I keep getting the "Incorrect Login" error, even when I type in the correct username and password.
Side Note: I know to redirect, I need to use header('Location: link.php'), it is not included for testing purposes.
If you didn't save your password as MD5 hash in your database you will never match it, cause in the line above you hash the password via MD5 before using in the query.
MD5 isn't secure! Use the PHP internal functions (password_hash(), password_verify()) to create and check passwords!
Use prepared statements!
Example code:
<?php
// Save a new user password in DB
$username = 'Max User';
$password = 'My_Secr3t_Pa5sw0rd';
$passwordHash = password_hash($password, PASSWORD_BCRYPT);
$stmt = $mysqli->prepare("INSERT INTO `users` (`username`, `password`) VALUES(?, ?)");
$stmt->bind_param("ss", $username, $passwordHash);
$stmt->execute();
// Check user password
$stmt = $mysqli->prepare("SELECT `password` FROM `users` WHERE `username`=?");
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
if (password_verify($password, $row['password']) {
echo "Password correct";
} else {
echo "Password incorrect!";
}
?>

PHP - Unable to login after password reset with sha512

I'm building a simple login script and I am able to register and login no problem. However I am now trying to add a "Forgotten password" feature and I can't figure out why it's not working.
I am able to update the password in the mysql table using the same sha512 and salting method I use in my registration script but after its updated I can no longer login.
The login function that runs when a user tries to login is as follows:
if ($stmt = $mysqli->prepare("SELECT userID, firstName, pWord, salt FROM users WHERE email = ? AND conf = 1 LIMIT 1")) {
$stmt->bind_param('s', $email); // Bind "$email" to parameter.
$stmt->execute(); // Execute the prepared query.
$stmt->store_result();
// get variables from result.
$stmt->bind_result($user_id, $firstName, $db_password, $salt);
$stmt->fetch();
// hash the password with the unique salt.
$password = hash('sha512', $password . $salt);
if ($stmt->num_rows == 1) {
// Check if the password in the database matches
// the password the user submitted.
if ($db_password == $password) {
... // Log user in
}
}
}
The password part of my registration script:
$random_salt = hash('sha512', uniqid(openssl_random_pseudo_bytes(16), TRUE));
// Create salted password
$password = hash('sha512', $password . $random_salt);
// Insert the new user into the database
if ($insert_stmt = $mysqli->prepare("INSERT INTO users (firstName, lastName, email, pWord, salt, accConf, conf) VALUES (?, ?, ?, ?, ?, ?, 0)")) {
$insert_stmt->bind_param('ssssss', $firstName, $lastName, $email, $password, $random_salt, $confirmation);
$insert_stmt->execute();
... // Do something }
The password part of my reset script:
$random_salt = hash('sha512', uniqid(openssl_random_pseudo_bytes(16), TRUE));
// Create salted password
$password = hash('sha512', $password . $random_salt);
// Update the user's password
if ($update = $mysqli->prepare('UPDATE users SET pWord = ?, salt = ? WHERE email = ?')) {
$update->bind_param('sss', $password, $random_salt, $email);
$update->execute();
... //Do something }
I can see that in the database, the password is updating but when I try to login with the new password, my "Invalid login details error is showing up.
Is there a reason that my passwords would not work after updating?

Basic php/db password encryption

've set up two simple php files for a login/register feature on my android app.
I would like to know a simple way to get it to save/write an encrypted password to the mysql database. at the moment its only writing plain text for password.
Code for register.php is :
$username = $_POST["username"];
$email = $_POST["email"];
$password = $_POST["password"];
$statement = mysqli_prepare($con, "INSERT INTO User (username, email, password) VALUES (?, ?, ?)" );
mysqli_stmt_bind_param($statement, "sss", $username, $email, $password);
mysqli_stmt_execute($statement);
mysqli_stmt_close($statement);
mysqli_close($con);
and code for login stuff is:
$password = $_POST["password"];
$username = $_POST["username"];
$statement = mysqli_prepare($con, "SELECT * FROM User WHERE username = ? AND password = ?");
mysqli_stmt_bind_param($statement, "ss", $username, $password);
mysqli_stmt_execute($statement);
mysqli_stmt_store_result($statement);
mysqli_stmt_bind_result($statement, $userID, $username, $email, $password);
$user = array();
while(mysqli_stmt_fetch($statement)) {
$user[username] = $username;
$user[email] = $email;
$user[password] = $password;
}
echo json_encode($user);
mysqli_stmt_close($statement);
mysqli_close($con);
very simple question i know but just learning myself. thanks
EDIT:
Based on Jamesking56's link/ response i've come out with this, but now its not writing to db at all:
$username = $_POST["username"];
$email = $_POST["email"];
$password = $_POST["password"];
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
$statement = mysqli_prepare($con, "INSERT INTO User (username, email, password) VALUES (?, ?, ?)" );
mysqli_stmt_bind_param($statement, "sss", $username, $email, $passwordHash);
mysqli_stmt_execute($statement);
mysqli_stmt_close($statement);
mysqli_close($con);
If you are using PHP 5.5 or newer, there are some built-in functions for password hashing called password_hash() and password_verify().
Never use MD5 or SHA1 on its own for password hashing as they can be reversed by using rainbow tables.
You should use a hashing mechanism with a secret that you define which gives you hashes which are unique to your application. The 'secret' you create should never be shared through VCS.
A good article about this can be found here: http://www.phptherightway.com/#password_hashing
For anyone using PHP versions lower than 5.5 you can use crypt():
http://php.net/manual/en/function.crypt.php
PHP 5.4 will be unsupported as of 14th September 2015 so please consider upgrading to 5.5.

PHP login function not working when I enable sha1

I have a PHP page that registers and logs in users. When I enable sha1, the user gets created and the encrypted password is stored in the DB, but they cannot log in. When I comment out the line to encrypt in both the user creation section as well as the login section, everthing works. Here is my code to create the user:
function add_member($nick_name, $email_address, $password) {
global $db;
$password = sha1($password);
$query = "INSERT INTO members
(nick_name, email_address, password)
VALUES
('$nick_name', :email_address, :password)";
$statement = $db->prepare($query);
$statement->bindValue(':email_address', $email_address);
$statement->bindValue(':password', $password);
$statement->execute();
$statement->closeCursor();
}
Here is my code to validate the user:
function is_valid_member($email_address, $password) {
global $db;
$password = sha1($password);
$query = "SELECT member_ID
FROM members
WHERE email_address = :email_address AND password = :password";
$statement = $db->prepare($query);
$statement->bindValue(':email_address', $email_address);
$statement->bindValue(':password', $password);
$statement->execute();
$valid = ($statement->rowCount() == 1);
$statement->closeCursor();
return $valid;
}
Again, when I comment out the "$password = sha1($password);" in both sections, everything works but the password is clear text.
Thanks!
try to debug like this, echo your $password = sha1($password); and check your database entry, might be your datatype length truncated some text in stored password

Categories