Hashing password in register and account settings - hash

I am get login errors when i test my script by logining under my own account. Do you think hashing passwords twice a bad practice?
I have hashed the users password twice in my website. Once, when they register and once, when they update their password in account update. Also i am using bcrypt method and cost of bcrypting is 10 on both hashings and i am on localhost server.
///// this is the code in register.php page
<?php
if(isset($_POST['registeruser'])) {
session_start();
$FName = $_POST['regfname'];
$LName = $_POST['reglname'];
$Email = mysqli_real_escape_string($conn, $_POST['regemail']);
$origignalpassword = preg_replace('#[^a-z0-9_]#i', '',
$_POST['regpassword']);
$Passwordw = $_POST['confirmedpassword'];
$infosql = "SELECT * FROM users WHERE useremail = '".$Email."'";
$result = mysqli_query($conn,$infosql);
if(mysqli_num_rows($result)>=1)
{
echo "Email already taken.";
}
else if(mysqli_num_rows($result) !=1 && $Passwordw ==
$origignalpassword) {
$Passwordhash = password_hash($Passwordw,
PASSWORD_BCRYPT, array('cost' => 10));
$sql = $conn->query("INSERT INTO users(firstname,
lastname, useremail, Passwordcell) Values('{$FName}',
'{$LName}','{$Email}','{$Psswordhash}')");
header('Location: login.php');
} else {
echo 'Please check your password:' . '<br>';
}
}
?>
//// Below code is the code in my update.php page
<?php session_start();
if(isset($_SESSION['user_id'])) {
} else {
header('Location: login.php');
}
$user = $_SESSION['userid'];
$myquery = "SELECT * FROM users WHERE `userid`='$user'";
$result = mysqli_query($conn, $myquery);
$row = mysqli_fetch_array($result, MYSQLI_BOTH);
$_SESSION['upd_fnames'] = $row['firstname'];
$_SESSION['upd_lnames'] = $row['Lastname'];
$_SESSION['upd_emails'] = $row['useremail'];
$_SESSION['upd_passwords'] = $row['Passwordcell'];
$_SESSION['upd_phone'] = $row['phonenum'];
$_SESSION['upd_bio'] = $row['biography'];
?>
<?php
if (isset($_POST['updateme'])) {
$updfname = $_POST['upd_fnames'];
$updlname = $_POST['upd_lnames'];
$updemail = $_POST['upd_emails'];
$updphone = $_POST['upd_phone'];
$upd_pswd = $_POST['upd_passwords'];
$biography = $_POST['update_biography'];
$Pswod = password_hash($upd_pswd, PASSWORD_BCRYPT,
array('cost' => 10));
$sql_input = $mysqli->query("UPDATE users SET firstname = '{$updfname}', Lastname = '{$updlname}', Phonenum = '{$updphone}', useremail = '{$updemail}', Passwordcell = '{$Pswod}', biography = '{$biography}' WHERE userid=$user");
header('Location: Account.php');
}
else
{
}
?>

Your problem could be just a typo, in your registration script, instead of $Passwordhash you wrote:
"INSERT INTO users(..., Passwordcell) Values(...,'{$Psswordhash}')"
Nevertheless there are other problems with your code, and since you asked for advise, i would like to share my thoughts.
Probably the biggest problem is, that your code is vulnerable to SQL-injection. Switch to prepared statements as soon as you can, writing code will become even easier than building the query as you did, and both MYSQLI and PDO are supporting it. This answer could give you a start.
Passwords should not be sanitized. Remove the line $origignalpassword = preg_replace('#[^a-z0-9_]#i', '', $_POST['regpassword']), and just pass the input directly to the hash function password_hash($_POST['regpassword'], PASSWORD_DEFAULT). The password_hash() function works with any type of input.
It is a good habit to place an exit after each redirection, otherwise the script will continue executing. header('Location: login.php', true, 303); exit;
Do you really have reason to put the user info into the session? Instead of $_SESSION['upd_fnames'] = $row['firstname']; i would fetch the information on demand from the database. With fetching it from the database you can be sure that the information is actually set (is not null) and is up to date, you can avoid a state and you get a bit more REST full.
Then last but not least i would recommend to follow some style rules, like starting variable names always with a small letter. You can avoid some silly typos and it makes your code more readable.

Related

Fatal error: require_once(): Failed opening required ... Novice programmer, appreciate any guidance

I'm a novice in server-side programming so any advice is appreciated.
I have some PHP files uploaded on a virtual server (000webhost.com) and I'm having trouble with locating a file I'm requiring in another PHP file. The register.php is attempting to "require_once" the update_user_info.php
Here's the code for register.php (Which I've taken from a tutorial and adjusted it with my variables):
<?php
define('__ROOT__', dirname(dirname(__FILE__)));
require_once(__ROOT__.'../update_user_info.php');
$db = new update_user_info();
// json response array
$response = array("error" => FALSE);
if (isset($_POST['name']) && isset($_POST['email']) && isset($_POST ['password']) && isset($_POST['branch']) && isset($_POST['gender'])) {
// receiving the post params
$username = $_POST['username'];
$name = $_POST['name'];
$email = $_POST['email'];
$password = $_POST['password'];
$branch = $_POST['branch'];
$gender = $_POST['gender'];
// check if user is already existed with the same email
if ($db->CheckExistingUser($email)) {
// user already existed
$response["error"] = TRUE;
$response["error_msg"] = "User already existed with " . $email;
echo json_encode($response);
} else {
// create a new user
$user = $db->StoreUserInfo($username, $name, $email, $password, $branch, $gender);
if ($user) {
// user stored successfully
$response["error"] = FALSE;
$response["user"]["username"] = $user["username"];
$response["user"]["name"] = $user["name"];
$response["user"]["email"] = $user["email"];
$response["user"]["branch"] = $user["branch"];
$response["user"]["gender"] = $user["gender"];
echo json_encode($response);
} else {
// user failed to store
$response["error"] = TRUE;
$response["error_msg"] = "Unknown error occurred in registration!";
echo json_encode($response);
}
}
} else {
$response["error"] = TRUE;
$response["error_msg"] = "Required parameter (username, name, email or password) is missing!";
echo json_encode($response);
}
?>
And here's a screenshot of the error that's occurring when attempting to visit the link containing the register.php:
Screenshot of the error
What I've tried so far:
1- tried to use require_once __DIR__."/../filename.php"; and lots more of the same, basically tinkering the statement with different language constructs and constants.
2-Read tutorials on the correct way to use require once but their cases is almost always very different. Either they are using WAMP/XAMPP -meaning they have a local path not a virtual one- So no luck there.
3- tried to change .htaccess file, as someone said in a post that it solved his problem.
4- I'm certain that both files are uploaded to the same directory. Yet it says "No such file".
Does anyone have an idea of where the error could be stemming from? Thanks in advance!

Authentication fails in Zend for account confirmation

I am stuck with this problem. When the login credentials are authenticated in my zend application , I also want to check if the account has been confirmed or not. Confirmed is a boolean column in my account table and is set to False by default. I am trying to achieve this through following code..but it is not working
$db = Zend_Db_Table::getDefaultAdapter();
$authAdapter = new Zend_Auth_Adapter_DbTable($db);
$authAdapter->setTableName('Account');
$authAdapter->setIdentityColumn('Email');
$authAdapter->setCredentialColumn('Password');
$authAdapter->setCredentialTreatment('Confirmed = 1');
$authAdapter->setIdentity($data['email']);
$authAdapter->setCredential($data['password']);
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($authAdapter);
if ($result->isValid()) {
if ($data['public'] == "1") {
Zend_Session::rememberMe(Zend_Registry::getInstance()->constants->sessiontime);
} else {
Zend_Session::forgetMe();
}
return TRUE;
} else {
return FALSE;
}
Despite the account not confirmed the authentication passes. Please tell me where am I wrong
The credential treatment parameter specifies how the password should be checked. You can override this to add additional clauses, but you still need to include the password bit. Really I wouldn't have expected your method to authenticate any users, so this may not be the main issue, but try:
$authAdapter->setCredentialTreatment('MD5(?) AND Confirmed = 1');
Changing the MD5 bit for however your passwords are encrypted. That should generate a query along the lines of:
... WHERE Email = 'xxx' AND Password = MD5(?) AND Confirmed = 1

How to migrate mysqli to pdo

Hi I was wondering how I would migrate a mysqli php file to use PDO. Would anyone be able to take a look at my code and see if I'm on the right track?
This is my original (mysqli) code:
<?php
// connecting to database
$conn = new mysqli('xxxxxx', 'xxxxxx', 'password', 'xxxxxx');
$match_email = 'email';
$match_passhash = 'passhash';
if (isset($_POST['email'])) {
$clean_email = mysqli_real_escape_string($conn, $_POST['email']);
$match_email = $clean_email;
}
if (isset($_POST['passhash'])) {
$clean_passhash = mysqli_real_escape_string($conn, $_POST['passhash']);
$match_passhash = sha1($clean_passhash);
}
$userquery = "SELECT email, passhash, userlevel, confirmed, blocked FROM useraccounts
WHERE email = '$match_email' AND passhash = '$match_passhash'
AND userlevel='user' AND confirmed='true' AND blocked='false';";
$userresult = $conn->query($userquery);
if ($userresult->num_rows == 1) {
$_SESSION['authorisation'] = 'knownuser';
header("Location: userhome.php");
exit;
} else {
$_SESSION['authorisation'] = 'unknownuser';
header("Location: userlogin.php");
exit;
}
?>
And this is my attempt to migrate it to PDO:
<?php
// connecting to database
$dbh = new PDO("mysql:host=xxxxxx; dbname=xxxxxx", "xxxxxx", "password");
$match_email = 'email';
$match_passhash = 'passhash';
if (isset($_POST['email'])) {
$clean_email = mysqli_real_escape_string($conn, $_POST['email']);
$match_email = $clean_email;
}
if (isset($_POST['passhash'])) {
$clean_passhash = mysqli_real_escape_string($conn, $_POST['passhash']);
$match_passhash = sha1($clean_passhash);
}
$userquery = "SELECT email, passhash, userlevel, confirmed, blocked FROM useraccounts
WHERE email = ':match_email' AND passhash = ':match_passhash' AND
userlevel='user' AND confirmed='true' AND blocked='false';";
$stmt = $dbh->prepare($query);
$stmt->bindParam(":match_email", $match_email);
$stmt->bindParam(":match_passhash", $match_passhash);
$stmt->execute();
$userresult = $conn->query($userquery);
if ($userresult->num_rows == 1) {
$_SESSION['authorisation'] = 'knownuser';
header("Location: userhome.php");
exit;
} else {
$_SESSION['authorisation'] = 'unknownuser';
header("Location: userlogin.php");
exit;
}
?>
I'm also not sure how to count the number of rows returned in PDO.
If anyone would be able to help me out that wold be very great.
A million thanks in advance!
When using prepared statements and $stmt->bindValue() or $stmt->bindParam() you do not need to escape values with mysqli_real_escape_string(), PDO will do that for you.
Just remember to set a correct data type for the value. That is the third argument in the bind functions and it is a string by default so your code here is fine. I would only use bindValue() instead of bindParam() as you do not need references.
$stmt->execute() will run your prepared statement as a query. The other $conn->query() does not work with prepared statements. It is for raw queries, like you used to have with MySQLi.
When $stmt->execute() runs your response is saved in the $stmt object. For row count use $stmt->rowCount().

Zend framework - Auth: additional validation

I want to check the user table for status=1 as extra validation. My getAuthAdapter() method looks like this:
private function getAuthAdapter (){
$authAdapter = new Zend_Auth_Adapter_DbTable(Zend_Db_Table::getDefaultAdapter());
$authAdapter->setTableName('vi_users')
->setIdentityColumn('email')
->setCredentialColumn('password');
return $authAdapter;
}
How would I alter this to include the extra validation?
I ran across this problem myself, and I'm not sure it is possible to check another column at the sametime. So I do it straight aftwerwards, with something like this:
$auth = Zend_Auth::getInstance();
....
if (process($form->getValues())) {
// login credentials are correct, so we now need to check if their account is activated
if ($auth->getIdentity()->active != 1) {
// if not, log them out and tell them to activate
Zend_Auth::getInstance()->clearIdentity();
$output .= "Your account has not yet been activated, please check your email (including spam bin) for the activation link.";
} else {
// if they're active then login is successful
$output .= "You are now logged in";
}
} else {
// username/password wrong
$output .= "Credentials invalid";
}
Update: Given Orlando's answer, it looks like what you've asked for originally is possible. You could use my solution though if you would like to distinguish between status value being 'wrong' and user/pass being wrong.
You could do something like:
$adapter = new Zend_Auth_Adapter_DbTable(
$db,
'users',
'username',
'password',
'MD5(?) AND status = 1'
);
where $db would be Zend_Db_Table::getDefaultAdapter()
Taken from http://framework.zend.com/manual/en/zend.auth.adapter.dbtable.html

weird php error - cannot explain just in title

discovered this forum a few days ago and still not into it enough to contribute - will happen soon i hope :)
right now i am experiencing something weird i hope someone can help me with.
In the following php code:
when i run it and enter a valid username and password, it will always send me to failed.php although it should have returned a result.
When i add a random "echo" before the if clause, it goes into the correct branch, but of course can't do the header("Location..) any more.
Does anyone have an idea what i am missing here or why this is happening?
Could it be some PHP setting i am not aware of?
thanks in advance
Seb
(NOTE i know php4 is not up to date, sql injections etc. - i just want to know and maybe understand why this is happening ;) )
<?php
include("config.php");
$query = 'select * from users where username = "' .
$_POST['username'] . '" and password = "' .
md5($_POST['password']) . '"';
$select_user = mysql_query($query);
//echo "something";
if ($select_user && ($row = mysql_fetch_row($select_user)))
{
$user_id = $row[0];
session_start();
session_register('authorized');
$_SESSION['authorized'] = true;
$_SESSION['uid'] = $user_id;
//echo "anothersomething";
header("Location: portal.php");
exit;
}
else
{
$_SESSION['authorized'] = false;
$_SESSION['uid'] = 0;
header("Location: failed.php");
exit;
}
#MYSQL_CLOSE($db);
?>