Password hash returning false - php

So I have a simple login script, but when I started encrypting passwords and using password_verify I seem to get the same result all the time, false. Here's my login script
<?php
session_start();
$host = "localhost";
$user = "root";
$pass = "root";
$dbname = "users";
try{
$con = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e){
echo $e->getMessage();
}
$email = htmlspecialchars($_POST['email'], ENT_QUOTES, 'UTF-8');
$pass = htmlspecialchars($_POST['password'], ENT_QUOTES, 'UTF-8');
$st = $con->prepare("SELECT * FROM users WHERE email = :email AND password = :pass");
$st->bindValue(':email', $email, PDO::PARAM_STR);
$st->bindValue(':pass', $pass, PDO::PARAM_STR);
$st->execute();
$rows = $st->fetch(PDO::FETCH_NUM);
if($email === ''){
$_SESSION['message1'] = 'Enter a valid email';
header('Location: index.php');
exit();
}
elseif($pass === ''){
$_SESSION['message1'] = 'Enter a valid password';
header('Location: index.php');
exit();
}
elseif($rows > 0){
$_SESSION['loggedin'] = true;
$hash = $con->prepare("SELECT password FROM users WHERE email = :email");
$hash->bindValue(':email', $email);
$hash->execute();
}
elseif(password_verify($pass, $hash)){
$name = $con->prepare("SELECT name FROM users WHERE email = :email");
$name->bindValue(':email', $email, PDO::PARAM_STR);
$name->execute();
$rows = $name->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
$_SESSION['name'] = $row['name'];
}
header('Location: profile.php');
}
else{
$_SESSION['message1'] = 'Make sure email and password are correct';
header('Location: index.php');
exit();
}
?>
Also here's how I'm encrypting
$passh = password_hash($pass, PASSWORD_DEFAULT)."\n";
$db = $con->prepare("INSERT INTO users (name, email, password) VALUES (:name, :email, :passh)");
$db->bindValue(':name', $name, PDO::PARAM_STR);
$db->bindValue(':email', $email, PDO::PARAM_STR);
$db->bindValue(':passh', $passh, PDO::PARAM_STR);
$db->execute();
$_SESSION['name'] = $name;
$_SESSION['email'] = $email;
$_SESSION['loggedin'] = true;
header('Location: profile.php');
exit();
Error reporting is enabled, but for some reason its still not working and simply displays Make sure email and password are correct, which come from the next else statement. Any ideas? I'm fairly new. Also any security tips would be great. Thanks in advance.
UPDATED CODE
<?php
session_start();
$host = "localhost";
$user = "root";
$passw = "root";
$dbname = "users";
try{
$con = new PDO("mysql:host=$host;dbname=$dbname", $user, $passw);
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e){
echo $e->getMessage();
}
$email = htmlspecialchars($_POST['email'], ENT_QUOTES, 'UTF-8');
$pass = htmlspecialchars($_POST['password'], ENT_QUOTES, 'UTF-8');
$hash = $con->prepare("SELECT password FROM users WHERE email = :email");
$hash->bindValue(':email', $email);
$hash->execute();
$rows1 = $hash->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows1 as $row1) {
$_SESSION['hash'] = $row1['hash'];
}
$st = $con->prepare("SELECT * FROM users WHERE email = :email AND password = :pass");
$st->bindValue(':email', $email, PDO::PARAM_STR);
$st->bindValue(':pass', $pass, PDO::PARAM_STR);
$st->execute();
$rows = $st->fetch(PDO::FETCH_NUM);
if($email === ''){
$_SESSION['message1'] = 'Enter a valid email';
header('Location: index.php');
exit();
}
elseif($pass === ''){
$_SESSION['message1'] = 'Enter a valid password';
header('Location: index.php');
exit();
}
elseif($rows > 0 || password_verify($pass, $hash) ){
$_SESSION['loggedin'] = true;
$name = $con->prepare("SELECT name FROM users WHERE email = :email");
$name->bindValue(':email', $email, PDO::PARAM_STR);
$name->execute();
$rows = $name->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
$_SESSION['name'] = $row['name'];
}
header('Location: profile.php');
}
else{
$_SESSION['message1'] = 'Make sure email and password are correct';
header('Location: index.php');
exit();
}
?>

Look at your query one more time:
SELECT password FROM users WHERE email = :email
You are selecting the column password,
when you fetch the row you are using the field hash
$_SESSION['hash'] = $row1['hash'];
Unlike you think, your script is not simple at all, you are performing 3 queries on the same record, try this approach
$email = $_POST['email'];
$pass = $_POST['password'];
if($email === ''){
$_SESSION['message1'] = 'Enter a valid email';
header('Location: index.php');
exit();
}
if($pass === ''){
$_SESSION['message1'] = 'Enter a valid password';
header('Location: index.php');
exit();
}
$query = 'SELECT name, email, password
FROM users
WHERE email = :email LIMIT 1';
$stmt = $con->prepare($query);
$stmt->bindValue(':email', $email);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if(!$row){
$_SESSION['message1'] = 'User does not exist';
header('Location: index.php');
exit();
}
//hashed password from Database
$hash = $row['password'];
if(password_verify($pass, $hash)){
$_SESSION['hash'] = $row['password'];
$_SESSION['name'] = $row['name'];
$_SESSION['email'] = $row['email'];
header('Location: profile.php');
}else{
$_SESSION['message1'] = 'Make sure email and password are correct';
header('Location: index.php');
exit();
}

Related

Why is this piece of code not writing anything into database?

I need a second pair of eyes to have a look at my code and tell me what I am missing, as I think I have identified the portion of code that doesn't work, I just don't know why.
Basically I am trying to register a user to a database, in a way that it prevents SQL injection. For the life of me however, it doesn't work. When I deconstruct the code and make it less secure, it works. Anyway, code is here:
//require_once 'sendEmails.php';
session_start();
$username = "";
$email = "";
$user_dob = "";
$user_fname = "";
$user_lname = "";
$user_telephone = "";
$errors = [];
$servername = '';
$login = '';
$password = '';
$DBname = '';
$rows = 0;
$query = "";
$conn = new mysqli($servername, $login, $password, $DBname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
if ($conn) {
echo "Connected successfully";
}
// SIGN UP USER
if (isset($_POST['signup-btn'])) {
if (empty($_POST['username'])) {
$errors['username'] = 'Username required';
}
if (empty($_POST['email'])) {
$errors['email'] = 'Email required';
}
if (empty($_POST['password'])) {
$errors['password'] = 'Password required';
}
if (isset($_POST['password']) && $_POST['password'] !== $_POST['passwordConf']) {
$errors['passwordConf'] = 'The two passwords do not match';
}
if (empty($_POST['dob'])) {
$errors['dob'] = 'Date of birth required';
}
if (empty($_POST['fname'])) {
$errors['fname'] = 'First name required';
}
if (empty($_POST['lname'])) {
$errors['lname'] = 'Last name required';
}
if (empty($_POST['telephone'])) {
$errors['telephone'] = 'Telephone number required';
} //--checks input in browser
//I think it works untill this point...
$token = bin2hex(random_bytes(50)); // generate unique token
$username = $_POST['username'];
$password = password_hash($_POST['password'], PASSWORD_BCRYPT); //encrypt password
$user_dob = $_POST['dob'];
$user_fname = $_POST['fname'];
$user_lname = $_POST['lname'];
$user_telephone = $_POST['telephone'];
$email = $_POST['email'];
//Above assigns inputted values into variables declared at the start
//echo $token, $email; //-- this works
//nl2br() ; // -- line break in php
// Check if email already exists
//$result = $mysqli->query("SELECT * FROM User_tbl WHERE email='$email' LIMIT 1");
$sql = "SELECT * FROM User_tbl WHERE email='$email' LIMIT 1";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) > $rows) {
$errors[] = $email;
echo "Email already exists";
}
$errorsInt = count($errors);
echo mysqli_num_rows($result);
echo count($errors);
echo $errorsInt;
if ($errorsInt === $rows) {
$query = "INSERT INTO User_tbl SET token=?, username=?, password=?, user_dob=?, user_fname=?, user_lname=?, user_telephone=?, email=?";
// "INSERT INTO User_tbl VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
echo $query;
//---------------------------------------------------------------------------
$stmt = $conn->prepare($query); //first
$stmt->bind_param('sssissis', $token, $username, $password, $user_dob, $user_fname, $user_lname, $user_telephone, $email);
$result = $stmt->execute();
echo $result;
if ($result) {
$user_id = $stmt->insert_id;
$stmt->close();
$_SESSION['id'] = $user_id;
$_SESSION['username'] = $username;
$_SESSION['email'] = $email;
$_SESSION['verified'] = false;
$_SESSION['message'] = 'You are logged in!';
$_SESSION['type'] = 'alert-success';
header('location: index.php');
} else {
$_SESSION['error_msg'] = "Database error: Could not register user";
}
}
}
The problem I believe starts here:
$stmt = $conn->prepare($query); //first
$stmt->bind_param('sssissis', $token, $username, $password, $user_dob, $user_fname, $user_lname, $user_telephone, $email);
$result = $stmt->execute();

Register and login with password_hash password default

I am trying to improve my security by using password_hash and PDO prepared statements to prevent SQL Injection. I already worked with MySQLi OOP and Procedural. I am trying to shift to PDO and want to learn.
So I created a signup form using PDO which is already working and the encryption of password is working too. But when I logged in even with the correct username and password I can't login.
This is the code I use to hash my password in the sign up form.
$password = $_POST['password'];
$hash = password_hash($password, PASSWORD_DEFAULT);
Then I execute it using prepared statements. So no errors at here everything works fine.
But when I tried to login it won't redirect me to the landing page where it should be.
So here is the code to my login
<?php
session_start();
$host = "localhost";
$username = "root";
$password = "";
$database = "PDOtesting";
$message = "";
try
{
$connect = new PDO("mysql:host=$host; dbname=$database", $username, $password);
$connect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if(isset($_POST["login"]))
{
if(empty($_POST["username"]) || empty($_POST["password"]))
{
$message = '<label>All fields are required</label>';
}
else
{
$query = "SELECT * FROM users WHERE username = :username AND password = :password";
$statement = $connect->prepare($query);
$statement->execute(
array(
'username' => $_POST["username"],
'password' => $_POST["password"]
)
);
$count = $statement->rowCount();
if($count > 0)
{
$_SESSION["username"] = $_POST["username"];
header("location:login_success.php");
}
else
{
$message = '<label>Wrong Data</label>';
}
}
}
}
catch(PDOException $error)
{
$message = $error->getMessage();
}
?>
Should I include also the password_hash function that I included it in the signup and where should I place the code?
Don't try and match the password in the query, select the user, return and then use password_verify on the result.
Update:
<?php
...
try
{
$connect = new PDO("mysql:host=$host; dbname=$database", $username, $password);
$connect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if(isset($_POST["login"]))
{
if(empty($_POST["username"]) || empty($_POST["password"]))
{
$message = '<label>All fields are required</label>';
}
else
{
$query = "SELECT * FROM users WHERE username = :username LIMIT 1";
$statement = $connect->prepare($query);
$statement->execute(
array(
'username' => $_POST["username"]
)
);
$count = $statement->rowCount();
if($count > 0)
{
$result = $statement->fetch();
//check password
if (password_verify($_POST["password"], $result['password'])) {
$_SESSION["username"] = $_POST["username"];
exit(header("location:login_success.php"));
} else {
$message = '<label>Wrong Data</label>';
}
}
else
{
$message = '<label>Wrong Data</label>';
}
}
}
}
catch(PDOException $error)
{
$message = $error->getMessage();
}
?>
Here is what I did to signup, I am using meekrodb class:
session_start();
include "../includes/db.class.php";
if (!empty($_POST))
$username =$_POST["username"];
$pass =$_POST["password"];
$email =$_POST["email"];
$id_number =$_POST["id_number"];
$password = password_hash($pass, PASSWORD_DEFAULT);
$check = DB::query("SELECT * FROM tbs.credentials WHERE username=%s AND email=%s AND id_number=%s", $username, $email, $id_number);
if ($check)
{
echo '
<div class="medium medium-small red-text animated wobble">Account already exist</div>
<script> M.toast({html: \'Account already exists\'})</script>
<p class="medium medium-small teal-text">Click here to reset password</p>
';
} else {
$rows = array(
'username'=>$username,
'password'=>$password,
'email'=>$email,
'id_number'=>$id_number,
);
$validate = DB::insert('credentials', $rows);
if($validate) {
echo
'
<div class="medium medium-small green-text animated rubberBand">Account created</div>
<script> M.toast({html: \'Account created successful\'})</script>
';
}
}
}
For Loging in:
session_start();
include "../includes/db.class.php";
if (!empty([$_POST])) {
$username = $_POST['username'];
$password = $_POST['password'];
$check = DB::query("SELECT * FROM tbs.credentials where username=%s", $username);
if ($check)
{
$check_password= DB::query("SELECT password FROM tbs.credentials WHERE password=%s", $username);
if ($check_password){
password_verify($password, $check_password);
$_SESSION['username'] = $password;
echo "Login";
}
}
}

Login user using password_verify

I'm creating a back end to my website and running into issues with the login user part.
The user registration into the database is made with the password_hash function using the code below:
UserReg.php :
<?php
require_once 'db.php';
$mysqli = new mysqli($host, $user, $password, $dbname);
if($mysqli -> connect_error) {
die($mysqli -> connect_erro);
}
$username = "userF";
$password = "somePass";
$token = password_hash("$password", PASSWORD_DEFAULT);
add_user($mysqli,$username, $token);
function add_user($mysqli,$username, $token) {
$query = $mysqli->prepare("INSERT INTO users(username, password) VALUES
(?,?)");
$query->bind_param('ss',$username, $token);
$query->execute();
$result = $query->get_result();
if(!$result) {
die($mysqli->error);
}
$query->close();
}
My login form skips to a blank page even when i insert my username and password. Doesn't even go to the login error message.
Login.php
<?php
include 'db.php';
$username = $_POST['user'];
$pwd = $_POST['password'];
$sql = "SELECT password FROM users WHERE username = ?";
$stmt = $mysqli->prepare($sql);
$stmt->execute();
$stmt->bind_result($pass);
while ($result = $stmt->num_rows()) {
if($stmt->password_verify($pwd, $result)) {
echo "Your username or password is incorrect";
} else {
header("Location: Menu.php");
}
}
What am i missing?
Appreciate your help.
I think you need to take a look at password_verify how it works.
$username = $_POST['user'];
$pwd = $_POST['password'];
$sql = "SELECT username, password FROM users WHERE username = ?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('s', $username);
$stmt->execute();
$stmt->bind_result($username, $password);
$stmt->store_result();
if ($stmt->num_rows == 1) { //To check if the row exists
if ($stmt->fetch()) { //fetching the contents of the row
if (password_verify($pwd, $password)) {
$_SESSION['username'] = $username;
echo 'Success!';
exit();
} else {
echo "INVALID PASSWORD!";
}
}
} else {
echo "INVALID USERNAME";
}
$stmt->close();

Hashed password not coming out to what it should be (PHP)

So I'm trying to make a fairly simple login system, but for some reason the hashed password that is being sent to my database is not hashing correctly. I checked my database and the stored password is not what the sha256 hashed with the generated salt appended is not what it's supposed to be. Here's my code for generating the hash that's being uploaded to the database:
<?php
include "connection.php";
//Check Connection
if ($connect->connect_error) {
echo "Failed to connect to server: " . mysqli_connect_error();
}
//Reset all Checks
$username_exists = NULL;
$email_valid = NULL;
$passwords_match = NULL;
$password_acceptable = NULL;
$password_long_enough = NULL;
$password = NULL;
//Prepare Statements
//Check for Username Existing Statement
$check_username_match = $connect->stmt_init();
$sql_check_username = "SELECT id FROM $tablename WHERE username=?";
$check_username_match->prepare($sql_check_username);
$check_username_match->bind_param("s", $username);
//Insert Into Table Statement
$register_query = $connect->stmt_init();
$sql_register = "INSERT INTO $tablename (username, email, password, token, active, level) VALUES (?, ?, ?, ?, ?, ?)";
$register_query->prepare($sql_register);
$register_query->bind_param("sssssi", $username, $email, $hashedpassword, $token, $activated, $level);
//Execute When Form Submitted
if($_SERVER["REQUEST_METHOD"] == "POST") {
$username = mysqli_escape_string($connect, $_POST['username']);
$email = mysqli_escape_string($connect, $_POST['email']);
$password = $_POST['password'];
$confirm_password = $_POST['confirm_password'];
//Check if Username Exists
$check_username_match->execute();
$check_username_match->store_result();
$numrows = $check_username_match->num_rows;
if ($numrows==0){
$username_exists = false;
} else {
$username_exists=true;
}
//Check if Passwords Match
if ($password==$confirm_password){
$passwords_match = true;
} else {
$passwords_match = false;
}
//Check if Email Address is Valid
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
$email_valid = true;
} else {
$email_valid = false;
}
//Check if Passwords Contains Special Characters
$uppercase = preg_match('#[A-Z]#', $password);
$lowercase = preg_match('#[a-z]#', $password);
$number = preg_match('#[0-9]#', $password);
//Check if Password is Long Enough
$password_length = strlen($password);
if ($password_length>8){
$password_long_enough = true;
} else {
$password_long_enough = false;
}
//Validate Password
if(!$uppercase || !$lowercase || !$number || !$password_long_enough || $password = '') {
$password_acceptable = false;
} else {
$password_acceptable = true;
}
//Register if all Validations Met
if(!$username_exists && $email_valid && $passwords_match && $password_acceptable){
//$salt = dechex(mt_rand(0, 2147483647)) . dechex(mt_rand(0, 2147483647));
$token = dechex(mt_rand(0, 2147483647)) . dechex(mt_rand(0, 2147483647));
$activated="No";
$level = 0;
$hashedpassword = password_hash($password, PASSWORD_DEFAULT);
$register_query->execute();
$message = "Hello, welcome to the site.\r\n\r\nPlease click on the following link to activate your account:\r\nlocalhost/login_system/activate.php?token=".$token;
mail($email, 'Please Activate Your Account', $message);
header("Location: login.php");
}
}
?>
UPDATE: I changed my above code to reflect the changes I made with password_hash. However, the problem still persists.
This is my login php:
<?php
include("connection.php");
session_start();
//Reset Variables
$message = '';
$location = "/login_system/index.php"; //default location to redirect after logging in
$username = '';
$password = '';
//Check to see if user is newly activated; if he is display a welcome message.
if(isset($_GET['activated'])){
if($_GET['activated'] == "true"){
$message = "Thank you for verifying your account. Please login to continue.";
}
}
//Check to see if user is coming from another page; if he is then store that page location to redirect to after logging in.
if(isset($_GET['location'])) {
$location = htmlspecialchars($_GET['location']);
}
echo $location;
//Prepare login check statement
$check_login = $connect->stmt_init();
$sql = "SELECT id, password FROM $tablename WHERE username=?";
$check_login->prepare($sql);
$check_login->bind_param("s", $username);
//Execute Login Check
if($_SERVER["REQUEST_METHOD"] == "POST") {
$username = mysqli_escape_string($connect, $_POST['username']);
$password = $_POST['password'];
$check_login->execute();
$check_login->store_result();
$numrows = $check_login->num_rows;
$check_login->bind_result($id, $match);
$check_login->fetch();
if ($numrows==1 && password_verify($password, $match)) {
$_SESSION['login_user'] = $id;
$goto = "localhost".$location;
header("location: $goto");
$message = "Success!";
} else {
$message="Username or password is not valid."."<br>".$match."<br>";
}
}
$connect->close();
?>
You should just feed the password you want to hash into PHP's password_hash();function. Like so...
$password = $_POST['password'];
$options = [
'cost' => 12,
];
echo password_hash($password, PASSWORD_BCRYPT, $options);
Then when you want to check if the password exists in the database use password_verify(); Like so...
$password = PASSWORD_HERE;
$stored_hash = HASH_HERE;
if (password_verify($password, $stored_hash)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}

Checking sha1 against stored sha1 password

I'm hashing a password using sha1 and it is successfully storing it in the database, however i cannot seem to properly check to see if the sha1 matches one that is in the database. I've tried numerous different iterations of the below code, but nothing seems to work - what am i missing?
Registration
<?php
$username = $_POST['username'];
$password = $_POST['password'];
$passwordEncrypted = sha1($password);
try {
$result = $db->prepare("INSERT INTO
user_info
SET
username = :user,
pass = :pass
");
$result->bindParam(':user', $username);
$result->bindParam(':pass', $passwordEncrypted);
$result->execute();
}
catch (Exception $e) {
echo "Could not create username";
}
if (isset($_POST['submit'])) {
foreach ($_POST as $field) {
if (empty($field)) {
$fail = true;
}
else {
$continue = false;
}
}
if ($field == $fail) {
echo "You must enter a username and/or password";
}
else {
echo "Your account has been successfully created.";
}
}
?>
Logging in
<?php
$username = $_POST['username'];
$password = $_POST['password'];
$encryptedPassword = sha1($password);
try {
$result = $db->prepare("SELECT username, pass FROM user_info WHERE username = :user AND BINARY pass = :pass");
$result->bindParam(':user', $username);
$result->bindParam(':pass', $password);
$result->execute();
$rows = $result->fetch(PDO::FETCH_NUM);
}
catch (Exception $e) {
echo "Could not retrieve data from database";
exit();
}
if ($rows) {
session_start();
$_SESSION['username'] = $_POST['username'];
$_SESSION['loggedin'] = true;
include("inc/redirect.php");
} else {
if (isset($_POST['login'])) {
echo "Username or password incorrect (passwords are case sensitive)";
}
}
?>
You need to hash the password before querying the table, not afterwards:
<?php
$username = $_POST['username'];
$password = $_POST['password'];
$passwordEncrypted = sha1($password);
try {
$result = $db->prepare("SELECT username, pass FROM user_info WHERE username = :user AND BINARY pass = :pass");
$result->bindParam(':user', $username);
$result->bindParam(':pass', $passwordEncrypted);
$result->execute();
if ($result->fetch(PDO::FETCH_NUM)) {
session_start();
$_SESSION['username'] = $_POST['username'];
$_SESSION['loggedin'] = true;
include("inc/redirect.php");
} else {
if (isset($_POST['login'])) {
echo "Username or password incorrect (passwords are case sensitive)";
}
}
}
catch (Exception $e) {
echo "Could not retrieve data from database";
exit();
}
?>

Categories