PHP password verifcation with hash - php

We have a system where the user logs in to an admin page to make edits however when they are logging in they can log in with any password as long as the username is correct. The following code is in php tags
include 'database_conn.php';
$sql = "SELECT passwordHash FROM nmc_users WHERE username = ?";
$stmt = mysqli_prepare($conn, $sql); // prepare the sql statement
mysqli_stmt_bind_param($stmt, "s", $username);
mysqli_stmt_execute($stmt); // execute the query
mysqli_stmt_bind_result($stmt, $passWDHash);
if (mysqli_stmt_fetch($stmt)) {
if (password_verify($passWD, $passWDHash)) {
echo "<p>Password correct!</p><a href='logout.php'>Click here to log off</a></p>\n";
} else {
echo "<p>Sorry we don't seem to have that username.</p>";
session_destroy();
}
if (isset($_SESSION['[url']))
$url = $_SESSION['url'];
else
$url = 'index.php';
header("location $url");
mysqli_stmt_close($stmt);
mysqli_close($conn);
}
?>
Would anyone know how to make it so it only logs users in with the correct username and password that.
The password is in our database as well as the usernames. If any more code is needed then please say and I will reply with the relevant pieces.

From the docs:
session_destroy() destroys all of the data associated with the current
session. It does not unset any of the global variables associated with
the session, or unset the session cookie.
If $_SESSION['url'] is set, and the password is wrong, session_destroy() won't unset it. So you're still falling into the success part of the if statement.
Edit: Also, you should be checking authentication on the actual page that requires it. Here, it looks like you're checking on one page and then conditionally redirecting to another. If I type the other page's URL directly into my address bar, will I get that page without an auth check?

Piggybacking on #AlexHowansky answer, you need to do a few things here:
First you need to be sure you're using session_start() at the beginning of the script to make sure the session is set up correctly.
Second, you need to unset the $_SESSION variables to make sure that once the session is destroyed, you can't accss these variables on the current page (they'll be unset on the next page, so you don't have to worry about that).
Third, you'll need to close the mysql connections before redirecting for them to do any good.
Fourth, there was a typo with this: if (isset($_SESSION['[url']))
Your header() redirect also won't work because you're echoing out text before it, which will cause it to fail, but I'll let you fix that.
I'm also not seeing where $passWD is coming from, but I'm assuming you have it in there somewhere.
Updated code:
include 'database_conn.php';
session_start();
$sql = "SELECT passwordHash FROM nmc_users WHERE username = ?";
$stmt = mysqli_prepare($conn, $sql); // prepare the sql statement
mysqli_stmt_bind_param($stmt, "s", $username);
mysqli_stmt_execute($stmt); // execute the query
mysqli_stmt_bind_result($stmt, $passWDHash);
if (mysqli_stmt_fetch($stmt)) {
if (password_verify($passWD, $passWDHash)) {
echo "<p>Password correct!</p><a href='logout.php'>Click here to log off</a></p>\n";
} else {
echo "<p>Sorry we don't seem to have that username.</p>";
session_destroy();
$_SESSION = array();
}
if (isset($_SESSION['url']))
$url = $_SESSION['url'];
else
$url = 'index.php';
mysqli_stmt_close($stmt);
mysqli_close($conn);
header("location $url");
}
?>

Related

How to update MySql column from -1 to 1 after login from PHP script

Before I ask the question, I know there are issues with the SQL Injection, I am going to take care of it most likely with PDO, I am just trying to figure this out for now.
I want PHP to read the status column from MySql and if the status column reads -1 where $username = ($_POST["username"]) I want PHP to initially send them to a "change password" screen and then after its changed send an update script to MySql to update column "status" from the default -1 to 1.
If its 1 I want it to log in as normal and if its -1 I want them to be forced to change their password basically and I am having trouble locating a way to do this.
Im assuming my update query would look something like this
$query = "UPDATE login SET status= 1 WHERE user_id='".$username ."' LIMIT 1";
My php login script so far
<?php
// Include config file
require_once 'LoginConn.php';
// Define variables and initialize with empty values
$username = $password = "";
$username_err = $password_err = "";
// Processing form data when form is submitted
if($_SERVER["REQUEST_METHOD"] == "POST"){
// Check if username is empty
if(empty(trim($_POST["username"]))){
$username_err = 'Please enter username.';
} else{
$username = trim($_POST["username"]);
}
// Check if password is empty
if(empty(trim($_POST['password']))){
$password_err = 'Please enter your password.';
} else{
$password = trim($_POST['password']);
}
// Validate credentials
if(empty($username_err) && empty($password_err)){
// Prepare a select statement
$sql = "SELECT username, password FROM scorecardusers WHERE username = ?";
if($stmt = mysqli_prepare($link, $sql)){
// Bind variables to the prepared statement as parameters
mysqli_stmt_bind_param($stmt, "s", $param_username);
// Set parameters
$param_username = $username;
// Attempt to execute the prepared statement
if(mysqli_stmt_execute($stmt)){
// Store result
mysqli_stmt_store_result($stmt);
// Check if username exists, if yes then verify password
if(mysqli_stmt_num_rows($stmt) == 1){
// Bind result variables
mysqli_stmt_bind_result($stmt, $username, $hashed_password);
if(mysqli_stmt_fetch($stmt)){
if(password_verify($password, $hashed_password)){
/* Password is correct, so start a new session and
save the username to the session */
session_start();
$value= $sql['password'];
$_SESSION['username'] = $username;
header("location: Test.php");
} else{
// Display an error message if password is not valid
$password_err = 'The password you entered was not valid.';
}
}
} else{
// Display an error message if username doesn't exist
$username_err = 'No account found with that username.';
}
} else{
echo "Oops! Something went wrong. Please try again later.";
}
}
// Close statement
mysqli_stmt_close($stmt);
}
// Close connection
mysqli_close($link);
}
?>
UPDATED: I added this to my query and it updates correctly.
mysqli_query ($link, "UPDATE Users SET Status = '1' WHERE Status ='-1'and username ='".$username ."' LIMIT 1");
If anyone could help me understand how to pull the status area from my sql and redirect them to the change password page if the status =-1 that would be awesome.
I am just trying to figure out how to redirect to change password if Status =-1 in mysql..
SECOND UPDATE: Ive made a second query that checks the information and sends you to the change password log however I know this is not correct. I feel as if I am getting a lot closer to the answer though. The code works as far as getting me to the right screen but its not getting the correct information. I need the username to be a variable based on what the agent puts in. Again, any help here would be really appreciated.
$id_get = "SELECT Status, username FROM scorecardusers WHERE Status = '-1' and username='MyName' LIMIT 1";
if ($result=mysqli_query($link, $id_get))
{
// Fetch one and one row// check if first time log in
while ($row = mysqli_fetch_assoc($result))
{
$Status=$row["Status"];
$username=$row["MyName"];
if ($Status== "-1" && $username =="MyName");
var_dump($result);
header("location: ChangePW.php");
}
// Free result set
mysqli_free_result($result);
}
I added the update query I posted above after the following code. This has solved my problem and accurately check if the user was logged in before, if they have the website directs them to a change password, if they have logged in it send them to the website. I created a separate query to select status and username so it would not interfere with the password. I am assuming this would work with any user name considering it is completely variable as long as they never logged in before it should direct them. If there is any issues with this code id love to know, however it is working correctly for me.
$id_get = "SELECT Status, username FROM Users WHERE Status = '-1' and username = ?";
if($Check = mysqli_prepare($link, $id_get)){
// Bind variables to the prepared statement as parameters
mysqli_stmt_bind_param($Check, "s", $param2_username);
// Set parameters
$param2_username = $username;
$param_status=$status;
// Attempt to execute the prepared statement
if(mysqli_stmt_execute($Check)){
// Store result
mysqli_stmt_store_result($Check);
if(mysqli_stmt_num_rows($Check) == 1){
// Bind result variables
mysqli_stmt_bind_result($Check, $username, $param2_status);
if(mysqli_stmt_fetch($Check)){
if ($param_status== "-1" && $param2_username == '?');
header("location: ChangePassword.php");
}
}
}
}

redirect after registration is not working

I can't figure out why my redirection wont work?
All I get is a blank page with the same url from where I tried to redirect from..
The code is from my registration page, however I removed some code to make it easier to look at my redirection here. Everything else is working except the redirection.
<?php
if($_SERVER["REQUEST_METHOD"] == "POST"){
//removed bunch of code for clear overview for stackoverflow question
// Prepare an insert statement
$sql = "INSERT INTO users (username, password) VALUES (?, ?)";
if($stmt = mysqli_prepare($link, $sql)){
// Bind variables to the prepared statement as parameters
mysqli_stmt_bind_param($stmt, "ss", $param_username, $param_password);
// Set parameters
$param_username = $username;
$param_password = password_hash($password, PASSWORD_DEFAULT); // Creates a password hash
// Attempt to execute the prepared statement
if(mysqli_stmt_execute($stmt)){
// Redirect to login page
header("location: login.php");
} else{
echo "Something went wrong. Please try again later.";
}
}
// Close statement
mysqli_stmt_close($stmt);
}
// Close connection
mysqli_close($link);
}
?>
I think your redirect might work if you are going to this page.
Yo get a blank page because your code starts with:
if($_SERVER["REQUEST_METHOD"] == "POST"){
You state that you have removed some code. If the code you expect to run is also in that codeblock and it is no POST (this might be a GET), the code inside that codeblock will not be executed.
There is no form tag in your example, but you could also check if you use method="POST".

I have a trouble in the Log-in procedure of my website

I having a difficulty on Log-in procedure. The username & password are both correct based on the database. The name of the fields on the database are also correct. I'm using PDO. When I click the log-in, I'm always redirecting to the else bracket. Please help me,thank you.
<?php
session_start();
include 'config.php';
if ($_POST) {
$user = $_POST['user'];
$pass = md5($_POST['pass']);
$query = "SELECT * FROM useraccounts WHERE USER_NAME=? AND USER_PASSWORD=?";
$stmt = $conn->prepare($query);
$stmt -> bindParam(1,$user);
$stmt -> bindParam(2,$pass);
$stmt -> execute();
$num = $stmt->rowCount();
if ($num>0) {
session_start();
$_SESSION['user']=$user;
$_SESSION['active']=true;
header('location:frontpage.php'); //Must be the destination
echo "SUCCESS";
}
else{
header('location:login.php'); // <-- I'm always directing here
echo "FAILED";
}
}
else{
header('location:login.php');
echo "FAILED";
}
If you are getting redirected to the login.php page, please keep in mind the following:
1) Unless you access that page with a POST request, you will always get the login.page. You have an if statement that looks like this:
if ($_POST) {
So if you access the page directly from the browser, you are redirected straight to the login.php page.
2) If you are getting redirected from the second else statement like you stated with your comment "<-- I'm always directing here" then your query is not returning any result. Your query looks fine. So check the credentials you are passing. Make sure it matches that of the database.
Is your html form using POST or GET in the method attribute. it should be using POST otherwise your database checking code will not be run

How to use $_SESSION in right way?

At the moment I am writing a little media library in PHP and i want to set sessions, so the user stays logged in and get's echoed his name at the front page.
[index.php]
if(isset($_SESSION['loggedin']))
{
//ECHO $USERNAME
}else{
echo '<p>To start, please login or register.</p>';
}
?>
I want, if theres an session id set, that PHP echoes out the $username.
[signup.php]
<?php
session_start();
$conn = mysqli_connect("$host", "$user", "$pass", "$db");
$uid = ($_POST['uid']);
$pw = ($_POST['pw1']);
$pw2 = ($_POST['pw2']);
if ($pw == $pw2) {
$sql = "INSERT INTO user (uid, pw) VALUES ('$uid', '$pw')";
$result = mysqli_query($conn, $sql);
echo "Registration succeeded.";
}else{
echo "Please check your information.";
}
header ("Refresh: 3; ../index.php");
So, after PHP successfully compares my $pw1 and $pw2 i want to start a session, then it should put the $username in the $_SESSION array.
Of course next to the secure session id.
I repeat, after this i want to echo the $username out at front page.
What is the best way to do it?
Thanks.
$sql="SELECT username FROM users WHERE userid=$uid";
$result=mysqli_query($conn,$sql);
$row=mysqli_fetch_assoc($result);
$_SESSION['username']=$row['username'];
You can do something like this.
Usage of $_SESSION super global array (compact version)
session_start(); //To init
$_SESSION['username'] = 'Bob'; // Store value
echo $_SESSION['username']; // Treat like normal array
Detailed example
To use a session, you have to init it first.
session_start();
After that you access the session vars via the super global
$_SESSION
A good way is always to store a value in your variables you want to use:
// init session
session_start();
// check if session var is set, if not init the field with value in the super global array
if(!isset($_SESSION['auth'])) $_SESSION['auth'] = false;
if(!$_SESSION['auth']) {
//do auth here like eg.
header('Location: signup.php'); // if auth is okay -> $_SESSION['auth] = true + redirect to this (main) script
die(); // This is really necessary because a header redirect can be ignored.
}
// if auth okay, do fancy stuff here
For security read the following
Remember to escape your user input, always!
How can I prevent SQL injection in PHP?
The session_id is stored in cookies normally.
Or - the old way via URL parameter.
You do not have to secure the session_id.
Read also advices about XSS/CSRF.
Plus tokens are also good.
May be this is what you mean with secure session_id.
Stackoverflow: preventing csrf in php
OWASP: https://www.owasp.org/index.php/PHP_CSRF_Guard
OWASP: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet

PHP Multiple Restricted Access

I am trying in my PHP to make it to where if the Account database value matches 0 or 1 or 2 or 3 then it makes the login go to a certain page but so far it doesn't log me in and it doesn't take me to the page. Before I had a log in page but it sent it to a universally restricted page, but what I want is depending on what the User signed up for then he gets put this value(which I have already implemented) that if this page were to work than it would send him to one of four restricted sites upon login. What I can't get is the value to get pulled and used to send him upon login to the specific page.I am using Mysqli. Here is the code:
<?php require 'connections/connections.php'; ?>
<?php
if(isset($_POST['Login'])){
$Username = $_POST['Username'];
$Password = $_POST['Password'];
$result = $con->query("select * from user where Username='$Username'
AND Password='$Password'");
$row = $result->fetch_array(MYSQLI_BOTH);
$AccountPerm = $con->query("SELECT * FROM `user` WHERE Account =
?");
session_start();
$AccountPerm = $_SESSION['Account'];
if($AccountPerm == 0){
header("Location: account.php");
}
if($AccountPerm == 1){
header("Location: Account1.php");
}
if($AccountPerm == 2){
header("Location: Account2.php");
}
if($AccountPerm == 3){
header("Location: Account3.php");
}
}
?>
so far it doesn't log me in
Just to be sure, your Account.php, Account1.php, Accout2.php and Account3.php rely on $_SESSION['Account'] right? (The code below assume so)
As for your problem with both login and redirecting you forget a line :
$_SESSION['Account'] = $row['Account'];
Also, I removed
$AccountPerm = $con->query("SELECT * FROM `user` WHERE Account =
?");
You code should look like :
<?php require 'connections/connections.php'; // NOTE: I don't close the php tag here ! See the "session_start()" point in the "Reviews" section below
if(isset($_POST['Login'])){
$Username = $_POST['Username'];
$Password = $_POST['Password'];
// TODO: Sanitize $Username and $Password against SQL injection (More in the "Reviews" section)
$result = $con->query("select * from user where Username='$Username'
AND Password='$Password'");
// TODO: Check if $result return NULL, if so the database couldn't execute your query and you must not continue to execute the code below.
$row = $result->fetch_array(MYSQLI_BOTH);
// TODO: Check if $row is NULL, if so the username/password doesn't match any row and you must not execute code below. (You should "logout" the user when user visit login.php, see the "Login pages" point in the "Reviews" section below)
session_start();
$_SESSION['Account'] = $row['Account']; // What you forgot to do
$AccountPerm = $_SESSION['Account'];
if($AccountPerm == 0){
header("Location: account.php");
}
if($AccountPerm == 1){
header("Location: Account1.php");
}
if($AccountPerm == 2){
header("Location: Account2.php");
}
if($AccountPerm == 3){
header("Location: Account3.php");
}
}
?>
Reviews
session_start()
Should be call at the top of your code. (It will probably end-up in a a shared file like connections.php that you will include in all of your file).
One reason is that session_start() won't work if you send ANY character to the user browser BEFORE calling session_start().
For exemple you close php tag after including connections.php, you may not know but you newline is actually text send to the browser !
To fix this you just have to not close your php tag, such as in
<?php require 'connections/connections.php'; ?>
if(isset($_POST['Login'])){
Login page
Make sure to logout (unset $_SESSION variables that you use to check if user is logged) the user in every case except if he enter the right username/password combinaison.
If the user is trying to login it may be a different user from the last time and we don't want him to be logged as somebody else if his username/password is wrong.
MySQL checks : You should always check what the MySQL function returned to you before using it ! (see the documentation !) Not doing so will throw php error/notification.
SQL injection : You must sanitize $Username/$Password before using them into your query.
Either you append the value with $con->real_escape_string() such as
$result = $con->query("SELECT * FROM user WHERE Account = '" . $con->real_escape_string($Username) . "' AND Password = '" . $con->real_escape_string($Password) ."')
or you use bind parameter, such as explained in this post (THIS IS THE RECOMMENDED WAY)
No multiple account pages
Your login page should redirect only to accout.php and within this page split the logic according with the $_SESSION['Account'] value.
Nothing stop you from including account1.php, account2.php, ... within account.php.
If you do so put your account1.php, account2.php, account3.php in a private folder that the user can't browse in.
(One of the method is to create a folder (such as includes) and put a file name .htaccess with Deny from all in it)

Categories