PHP Change Account Password Brakes at verify current password - php

I am trying to make a Change You Account Password Function for my website.
The login codes are working properly, hashed passwords with bcrypt , log in verifies and confirms that the account name and password are correct with the ones that are entered.
I am trying to use the same algorithm to check the Current pass and Database pass verification ,but something seems to be missing.
I constantly get a different hash from the password that is entered and respectively wrong current password error.
Here is the exact code I use in the php file.
<?php
session_start();
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
$client_new_password_err = $client_current_password_err = $client_confirm_new_password_err = $general_err = "";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$user_check = $_SESSION['login_user'];
$stmt = $conn->prepare("SELECT UserName FROM user_main WHERE UserName='$user_check'");
$stmt->execute();
foreach ($stmt->fetch(PDO::FETCH_ASSOC) as $arr) {
$login_session = $login_session . $arr;
}
if (empty($login_session)) {
$conn = null;
header('Location: login.php');
}
$stmt = $conn->prepare("SELECT Email FROM user_main WHERE UserName='$user_check'");
$stmt->execute();
foreach ($stmt->fetch(PDO::FETCH_ASSOC) as $arr) {
$login_email = $login_email . $arr;
}
}
catch(PDOException $e)
{
echo $stmt . "<br>" . $e->getMessage();
}
$conn = null;
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (!empty($_POST["current-password"])) {
$client_current_password = test_input($_POST['current-password']);
$cost = [
'cost' => 11,
];
$client_current_hashed_password = password_hash($client_current_password, PASSWORD_BCRYPT, $cost);
} else {
$client_current_password_err = "No input on Current Password";
}
if (!empty($_POST['new-password'])) {
$client_new_password = test_input($_POST['new-password']);
$cost = [
'cost' => 11,
];
$client_new_hashed_password = password_hash($client_new_password, PASSWORD_BCRYPT, $cost);
} else {
$client_new_password_err = "No input on New Password";
}
if (!empty($_POST['confirm-new-password'])) {
$client_confirm_new_password = test_input($POST['confirm-new-password']);
$cost = [
'cost' => 11,
];
$client_confirm_new_hashed_password = password_hash($client_confirm_new_password, PASSWORD_BCRYPT, $cost);
} else {
$client_confirm_new_password_err = "No input on New Password";
}
if ($client_new_hashed_password == $client_confirm_new_hashed_password) {
$to_change_pass = 1; // not yet implemented
} else {
$to_change_pass = 0; // not yet implemented
}
}
if (!empty($client_current_hashed_password) && !empty($client_new_hashed_password) && !empty($client_confirm_new_hashed_password)) {
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$user_check = $_SESSION['login_user'];
$stmt = $conn->prepare("SELECT Password FROM user_main WHERE UserName='$user_check'");
$stmt->execute();
foreach ($stmt->fetch(PDO::FETCH_ASSOC) as $db_hash_pass) {
if(password_verify($client_current_password, $db_hash_pass)) {
$stmt = $conn->prepare("UPDATE user_main SET Password = '$client_new_hashed_password' WHERE UserName = '$user_check'");
} else {
$general_err = "Entered current password does not match the actual password for this account. Please try again.";
}
}
}
catch(PDOException $e)
{
echo $stmt . "<br>" . $e->getMessage();
}
$conn = null;
}
?>
The main question is how should I be checking if the inputted current pass matches the one on the database?
Should i be using the hashed version of the pass entered by the client or should i be using the plain text password?
This is the login password verify code which is 100% operational
if (!empty($_POST['password'])) {
if (!preg_match("/^[a-zA-Z0-9 ]*$/",$_POST['password'])) {
$usernameErr = 'Only Letters and Numbers';
} else {
$client_password = test_input($_POST['password']);
if(password_verify($client_password, $hashed_password)) {
$_SESSION['login_user'] = $client_username;
header("location: profile.php");
where $hashed_password is drawn from the database column Password with username match and here it works.
As you can see I have limited passwords to letters and numbers only so -
Bonus question : By allowing all characters to be used in a password , does that impose any type of injection threat?

Don't hash, but verify instead. – jeroen 13 mins ago
Removed hashing from the code entirely and it is ok now, it works by using password_verify($client_current_password, $db_hash_pass).
Thank you jeroen for the push u gave me to do this :D

Related

Multilevel Login in PHP

I have php code for login, it is worked if i input just username and password, but i need to check it with column hak_akses. For example if i login with hakakses = Dosen, the response says "Login Berhasil", if i login with hakakses = TU, the response says "Login Failed"
This is my code login php
<?php
$con = new mysqli("localhost","root","","komplain");
if($con->connect_error)
{
die("Connection Failed: " .$con->connect_error);
}
$response = array();
if(isset($_GET['apicall']))
{
switch ($_GET['apicall']) {
case 'signup':
# code...
break;
case 'login':
if(isParameterAvailable(array('username','password')))
{
$username = $_POST['username'];
$password = password_hash($_POST['password']);
$stmt = $con->prepare("SELECT id_user, username, email, no_telp FROM user WHERE username = ? AND password = ?");
$stmt->bind_param("ss",$username,$password);
$stmt->execute();
$stmt->store_result();
if($stmt->num_rows > 0)
{
$stmt->bind_result($id,$username,$email,$no_telp);
$stmt->fetch();
$user = array(
'id'=>$id,
'username'=>$username,
'email'=>$email,
'no_telp'=>$no_telp
);
$response['error'] = false;
$response['message'] = "Login Berhasil";
$response['user'] = $user;
}
else
{
$response['error'] = false;
$response['message'] = "Username / Password Salah";
}
}
break;
default:
$response['error'] = true;
$response['message'] = 'Invalid Operation Called';
}
}
else
{
$response['error'] = true;
$response['message'] = 'Invalid API call';
}
echo json_encode($response);
?>
This is my database
enter image description here
This is response from postman
enter image description here
My question is what should i do if i need to check login with hakakses(level user) ?
This code is just simulation, i am not using this code for my project, so i want to know how to login with multilevel user base on my code
Sorry for my English
Thank You
You should use password_hash() for PHP versions less than 5.5.
I'm using PHP 7.0 and I'm using hash() with a salt for extra security.
I'm first looking for the user inside the db based on username/email and then compare the password with the hashed entered password.
In that way you can show an invalid password error or even a user not found error.
$stmt = $con->prepare("SELECT id_user, username, email, no_telp, password, salt FROM user WHERE username = ? ");
$stmt->bind_param("ss",$username);
$stmt->execute();
$login_ok = false;
$row = $stmt->fetch();
if($row){
$check_password = hash('sha256', $row['password'] . $row['salt']);
if($check_password === $row['password']){
$login_ok = true;
}
else{
// invalid password
}
}
else {
// no user found
}
Based on $login_ok you can do stuff like showing errors
By creating a new user you should add the hashed password + the salt inside the db.
First generate a new salt:
$salt = dechex(mt_rand(0, 2147483647)) . dechex(mt_rand(0, 2147483647));
And save the password into the db like this:
hash('sha256', $password . $salt)
Also don't forget to add the salt itself to the db.
Okay i find a solution. First i changed my code to this
<?php
$con = new mysqli("localhost","root","","tugas_akhir");
if($con->connect_error)
{
die("Connection Failed: " .$con->connect_error);
}
$response = array();
$username = $_POST['username'];
$password = $_POST['password'];
$login = mysqli_query($con,"SELECT * from user WHERE username='$username'and password='$password'");
$cek = mysqli_num_rows($login);
if ($cek > 0) {
while($data = mysqli_fetch_assoc($login))
{
$id = $data['id_user'];
$email = $data['email'];
$hak = $data['hak_akses'];
$no_telp = $data['no_telp'];
if ($data['hak_akses'] == "Dosen") {
$user = array(
'id_user'=>$id,
'username'=>$username,
'email'=>$email,
'hak_akses'=>$hak,
'no_telp'=>$no_telp);
$response['error'] = false;
$response['message'] ="Berhasil Login";
$response['user'] = $user;
}
else{
$response['error'] = true;
$response['message'] = "Tidak Mempunyai Akses";
}
}
}
else{
$response['error'] = true;
$response['message'] = "Username/Password Salah";
}
echo json_encode($response);
?>
I use mysqli_fetch_assoc() to retrieve data from database. And then i store data with $data
If user input is true, the message is Berhasil Login(Successful), else the message is Tidak Punya Akses(Access Denied) because i give statement if($data['hak_akses'] == "Dosen")

Activating a registered account using code (PHP + JS)

I'm currently working on a project and managed to get a working registration and login form. Upon registration, the user is emailed with a 5 character activation code and is asked to insert it on the user profile page in order to change the status from active:0 to active:1 and gains permission to the rest of the site.
For some reason the activation code just simply won't work :/
The following code is the PHP code written to activate the account, I am using PDO queries to connect to the database, but I tried using a mysqli query too but didn't seem to work.
<?php
session_start();
// Allow the config
define('__CONFIG__', true);
// Require the config
require_once "inc/config.php"; //possibly have to change the location
include_once "inc/classes/DB.php"; //possibly have to change location
include_once "inc/classes/Page.php";
include_once "inc/classes/User.php";
Page::ForceLogin();
//
//$email = filter_input(INPUT_POST['email'] );
//$username = Filter::String($_POST['username']);
//$skills = Filter::String($_POST['skills']);
//$email = filter_input(INPUT_POST['email'] );
//$username = filter_input(INPUT_POST['username'] );
$return=[];
$User = new User($_SESSION['user_id']);
$username = $User->username;
////Connection Variables
//$host = 'localhost';
//$user = 'root';
//$password = '';
//$db = 'mdb_';
////Creating mysql connection
//$conn = new mysqli($host,$user,$password,$db);
//$username = $User->username;
$activationCode = User::Find(INPUT_GET['activationCode']);
if(isset($_GET['activationCode'])) {
if(!empty($_GET['activationCode'])) {
$query = "SELECT * FROM users WHERE username='.$username.'";
$result = query($con, $query);
if(ocirowcount($result) > 0){
while($row = mysqli_fetch_array($result)){
if($_GET['activationCode'] == $row["activationCode"]){
$con->query ("UPDATE users SET active=1 AND credit=100 WHERE username = '.$username.'");
$return['error'] = 'Your account is now activated! You have earned 100 Time-banking credits.';
//header("Refresh:0");
}
else{
$return['error'] = 'Code incorrect, please try again';
}
}
}
echo json_encode($return, JSON_PRETTY_PRINT);
}
}
//$activationCode = filter_input(INPUT_GET, "activationCode" );
//if(isset($_GET['activationCode'])) {
// if(!empty($_GET['activationCode'])) {
// $query = "SELECT * FROM users WHERE username='$username'";
// $result = mysqli_query($conn, $query);
// if(mysqli_num_rows($result) > 0){
// while($row = mysqli_fetch_array($result)){
// if($_GET['activationCode'] == $row["activationCode"]){
// $sql = $conn->query ("UPDATE users SET active=1 AND credit=100 WHERE username = '$username'");
// $return['error'] = 'Your account is now activated! You have earned 100 Time-banking credits.';
// //header("Refresh:0");
// }
// else{
// $return['error'] = 'Code incorrect, please try again';
// }
// }
// }
// echo json_encode($return, JSON_PRETTY_PRINT);
// }
//}
//$activationCode = filter_input(INPUT_POST, "activationCode" );
//
// if(isset($_POST['activationCode'])) {
// $activationCode = Filter::String( $_POST['activationCode'] );
//
//
//
//
//
// $query = "SELECT * FROM users WHERE username='$username'";
// $result = mysqli_query($con, $query);
// if(mysqli_num_rows($result) > 0){
//
// while($row = mysqli_fetch_array($result)){
//
// if($_POST['activationCode'] == $row["activationCode"]){
//
//
// $activateUser = $con->query ("UPDATE `users` SET `credit` = :100, `active` = :1, WHERE `user_id` = :$user_id");
// //$sql = $con->query ("UPDATE users SET active=1, credit=100 WHERE username = '$username'");
//
// $return['error'] = 'Your account is now activated! You have earned 100 Time-banking credits.';
//
// header("Refresh:0");
// }
// else{
// $return['error'] = 'Code incorrect, please try again';
// }
//
// }
// }
//
// echo json_encode($return, JSON_PRETTY_PRINT);
//
//// }
// }
?>
The code below is the db class that creates the $con in PDO
class DB {
protected static $con;
private function __construct(){
try {
self::$con = new PDO( 'mysql:charset=latin1;host=host;port=****;dbname=mdb_', 'root', 'pass'); //change connection string
self::$con->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
self::$con->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
self::$con->setAttribute( PDO::ATTR_PERSISTENT, false );
self::$con->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch (PDOException $e) {
echo "Could not connect todatabase."; exit;
}
}
public static function getConnection() {
//If this instance has not been started, start it.
if (!self::$con) {
new DB();
}
//Return the writeable db connection
return self::$con;
}
There are several issues here, from mixing database API's to possible SQL injection, string concatenation issues and incorrect SQL syntax in your UPDATE query.
If you're using PDO for your database connection, you need to remove all references to the oci* (which are for Oracle databases) and mysqli* (which is a different API and not compatible with PDO) functions, and use the PDO equivalents.
I will also remove $username from the queries and use prepared statements instead. $username may be coming from your own database, but I can't see how it got in there. If you do not have a limit on which characters a username can contain, and the username is properly escaped when it is inserted into your database, then it may contain single (or double) quotes that can still cause trouble in this code. Bottom line: if it was originally user input, it should never be trusted.
// I missed this in the code in your question
$con = DB::getConnection();
if (isset($_GET['activationCode'])) {
if(!empty($_GET['activationCode'])) {
// Note the placeholder ":username" -- PDO will fill that with
// $username for you (see $stmt->execute() below) and take care
// of adding quotes around it
$query = "SELECT * FROM users WHERE username = :username";
try {
$stmt = $con->prepare($query);
$stmt->execute(array(':username' => $username));
if ($stmt->rowCount() > 0) {
foreach ($stmt as $row) {
if ($_GET['activationCode'] == $row["activationCode"]) {
// note the syntax: "SET active=1, credit=100"
$update = $con->prepare("UPDATE users SET active=1, credit=100 WHERE username = :username");
$update->execute(array(':username' => $username));
$return['error'] = 'Your account is now activated! You have earned 100 Time-banking credits.';
//header("Refresh:0");
} else {
$return['error'] = 'Code incorrect, please try again';
}
}
}
} catch (PDOException $error) {
$return['error'] = (string)$error;
}
echo json_encode($return, JSON_PRETTY_PRINT);
}
}
Note that this can be somewhat optimised by just attempting the UPDATE query. For the sake of convenience, I'll also assume you only want the activation code to be able to be used on inactive accounts, which you aren't currently checking:
$con = DB::getConnection();
if (isset($_GET['activationCode']) && !empty($_GET['activationCode'])) {
$query = "UPDATE users SET active = 1, credit = 100 WHERE username = :username AND activationCode = :code AND active = 0";
try {
$stmt = $con->prepare($query);
$stmt->execute(array(
':username' => $username,
':code' => $_GET['activationCode']
));
if ($stmt->rowCount() > 0) {
$return['error'] = 'Your account is now activated! You have earned 100 Time-banking credits.';
} else {
$return['error'] = 'Code incorrect or account is already active, please try again';
}
} catch (PDOException $error) {
$return['error'] = (string)$error;
}
echo json_encode($return, JSON_PRETTY_PRINT);
}

PHP PDO Session redirecting me to login page

I am trying to improve my skills in PHP. I came from PHP procedural and shifting to PHP using PDO which will make my web application more secured to prevent SQL Injections or XSS attacks. I created a login form that is working fine that the user can input either email or username and followed by a password to verify that is encrypted in the back-end. I used password_hash() for my encryption in the registration form.
So here is the code in my login PHP to authenticate the user below
<?php
session_start();
$host = "localhost";
$username = "root";
$password = "";
$database = "test";
$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 = '
<script>
sweetAlert("Incorrect username or password!", "Please try again.", "error");
</script>;
';
}
else
{
// User login authentication
$query = "SELECT * FROM users WHERE user_type = :user_type AND (username = :username OR email = :username) LIMIT 1";
$statement = $connect->prepare($query);
$statement->execute(
array(
'username' => $_POST["username"],
'email' => $_POST["username"],
'user_type' => 'user'
// 'archive' => 1
)
);
$count = $statement->rowCount();
// Administrator login authentication
$query2 = "SELECT * FROM users WHERE user_type = :user_type AND (username = :username OR email = :username) LIMIT 1";
$statement2 = $connect->prepare($query2);
$statement2->execute(
array(
'username' => $_POST["username"],
'email' => $_POST["username"],
'user_type' => 'admin'
// 'archive' => 1
)
);
$count2 = $statement2->rowCount();
if($count > 0)
{
$result = $statement->fetch();
//check password
if (password_verify($_POST["password"], $result['password'])) {
$_SESSION["login_user"] = $_POST["username"];
exit(header("location:user/dashboard.php"));
} else {
$message = '
<script>
sweetAlert("Incorrect username or password!", "Please try again.", "error");
</script>;
';
}
}
else if($count2 > 0)
{
$result2 = $statement2->fetch();
//check password
if (password_verify($_POST["password"], $result2['password'])) {
$_SESSION["login_admin"] = $_POST["username"];
exit(header("location:admin/dashboard.php"));
} else {
$message = '
<script>
sweetAlert("Incorrect username or password!", "Please try again.", "error");
</script>;
';
}
}
else
{
$message = '
<script>
sweetAlert("Incorrect username or password!", "Please try again.", "error");
</script>;
';
}
}
}
}
catch(PDOException $error)
{
$message = $error->getMessage();
}
?>
But everything here works fine and vulnerable to SQL Injection attacks. So it is redirecting to the right place if the user has inputted the correct data.
But when I added the session it redirects me back to the login page.
Here is the code in my session.php below
<?php
$dbhost = "localhost";
$dbname = "test";
$dbuser = "root";
$dbpass = "";
$conn = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
session_start();
$user_check=$_SESSION['login_user'];
$result = $conn->prepare("SELECT * FROM users WHERE email = :user_check OR username = :user_check");
$result->execute(array(":usercheck"=>$user_check));
$row = $result->fetch(PDO::FETCH_ASSOC);
$login_session = $row['username'];
$ln_session = $row['last_name'];
$fn_session = $row['first_name'];
$user_id =$row['id'];
// $user_passwords = $row['password'];
if(!isset($login_session))
{
$conn = null;
header('Location: ../index.php');
}
?>
I would include in the admin its just because the same procedure but different session to be checked. So I think I messed up with the session?
Appreciate if someone can help.
Thanks in advance.
I noticed that you used ':user_check' as a parameter in the SQL string but, you used ':usercheck' as an index in the array on execute() function. You need to use the same parameter name on the sql string and in indexes of array in execute function.

how to use hash sha256 password for pdo Login php

my register using hash 'sha256' password for database, i dont know the function that using for login with hash password.. i tried it but not fix or i need to use hash password for it ::
session_start();
try{
$bdd = new PDO('mysql:host=localhost; dbname=senio743_payless','senio743_peter', 'P#ssw0rd123');
}
catch (Exception $e) {
die ('Error: '.$e->getMessage ());
}
$data = array ();
if (isset($_POST['submit'])) {
if (isset($_POST['con_id'])) {
$conId= htmlspecialchars($_POST['con_id']);
}
if (isset($_POST['con_password'])) {
$pass= htmlspecialchars($_POST['con_password']);
}
if ($conId==''||$pass=='') {
$message="Fill in all the enteries";
echo "<script>alert('".$message."');</script>";
exit();
}
$query= "SELECT * FROM `consumer` WHERE `con_id`='".$conId."' AND `con_password`= '".$pass."'";
$prepare = $bdd->prepare($query);
$exist = $prepare->execute();
if ($exist) {
if ($prepare->rowCount()>0) {
$data[]=$prepare->fetch();
foreach ($data as $datas) {
$con_name=$datas['con_name'];
$con_amount=$datas['con_amount'];
//echo $mer_name;
}
$_SESSION['ID']= $conId;
$_SESSION['name']= $con_name;
$_SESSION['balance']= $con_amount;
// $message="LOGIN Succesful";
header("location:../consumer/summary.php");
exit();
}
else {
$_SESSION['ID']= "";
$_SESSION['name']= '';
$_SESSION['balance']= 'Login Please';
$message="Login not succesful";
echo "<script>alert('".$message."');</script>";
header("location:../login.php");
exit();
}
}
please need help,
thank you..
Do not use md5().
PHP has a password hashing function.
$options = [ 'cost' => 15 ];
$hashed_password = password_hash('password', PASSWORD_BCRYPT, $options);
if(password_verify($_POST['password'], $hashed_password))
{
// Password the same
}
else
{
// Password failed
}
http://php.net/manual/en/function.password-hash.php
http://php.net/manual/en/function.password-verify.php
Using your script something along these lines may work as well
if (isset($_POST['submit'])) {
if ($conId==''||$pass=='') {
$message="Fill in all the enteries";
echo "<script>alert('".$message."');</script>";
exit();
}
$query = "SELECT * FROM `consumer` WHERE `con_id`= :con_id";
$prepare = $bdd->prepare($query);
$prepare->bindParam(':con_id', $con_id);
$prepare->execute();
$exists = $prepare->fetch();
$pass = hash('sha256', $_POST['pass']);
if($pass == $exists['pass'])
{
// Passwords Match
}
else
{
// They Don't
}
}
The hash function is just hash('sha256', $pass);
http://php.net/manual/en/function.hash.php
Also, when logging someone in, I've always looked up the user my their username and then compared the passwords in PHP. It should be faster because the query doesn't have compare a 200 character string to thousands of other strings.

Undefined property: PDOStatement::$rows

I'm not sure why this bit of code:
if($sth->rows == 0){
echo "Incorrect username or password - 1";
}
is pulling the error Undefined property: PDOStatement::$rows. This works just fine on a different PHP script that I basically had changed only a few things. I do however also receive the echo "Incorrect username or password -1" meaning that if statement did run.
Here is the full PHP code.
<?php
$lusername = $_POST['username'];
$lpassword = $_POST['password'];
//Hashing password
$cost = 10;
$salt = strtr(base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)), '+', '.');
$salt = sprintf("$2a$%02d$", $cost) . $salt;
$hash = crypt($lpassword, $salt);
// Create connection
$dsn = 'mysql:dbname=weblupne_template3;host=localhost';
$username = 'somethingFreakingCrazyMagical';
$password = 'somethingEvenMoreCrazyFreakingMagical';
try {
$db = new PDO($dsn, $username, $password); // also allows an extra parameter of configuration
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // set the PDO error mode to exception
} catch(PDOException $e) {
die('Could not connect to the database:<br/>' . $e);
}
//Where to select from
$sth = $db->prepare('SELECT password FROM login WHERE username = :username LIMIT 1');
$sth->bindParam(':username', $lusername);
$sth->execute();
$user = $sth->fetch(PDO::FETCH_OBJ);
if($sth->rows == 0){
echo "Incorrect username or password - 1";
}
else{
//Tests if correct
echo $user->hash;
if ( hash_equals($user->password, crypt($lpassword, $user->password)) ) {
echo "You check out";
}
else{
echo "Incorrect username or password - 2";
}
}
?>
You have to use $sth->rowCount(), there is no property named rows.

Categories