0
<?php
require "Common.php";
$player_username = $_POST ["usernamePost"];
$player_password = $_POST ["passwordPost"];
$hashed_password = password_hash($player_password, PASSWORD_DEFAULT);

$conn = new mysqli ($server_host, $server_username, $server_password, $server_dbName);

$result = mysqli_query ($conn, "SELECT * FROM users WHERE Username ='$player_username' and Password = ''");
$count = mysqli_num_rows($result);

if ($count == 1) {
    while ($row = mysqli_fetch_assoc ($result)) {
        if (password_verify($player_password, $hashed_password)) {
            echo "Signing in...<br>";
            echo "ID:".$row ['ID'] . "|Username:".$row ['Username'] . "|Score:".$row ['Score'] . "|Status:".$row ['Status'];
        }
    }
}
else {
    echo "Incorrect username or password.";
}
?>

Second piece of code:

<?php
require "Common.php";
$player_username = $_POST ["usernamePost"];
$player_password = $_POST ["passwordPost"];
$hashed_password = password_hash($player_password, PASSWORD_DEFAULT);

$conn = new mysqli ($server_host, $server_username, $server_password, $server_dbName);
    $queryCode = "SELECT * FROM users WHERE Username = '$player_username'";
    $query = mysqli_query ($conn, $queryCode);
    if (mysqli_num_rows($query) > 0) {
        echo "Username already exists.";
    } else {
        $sql = "INSERT INTO users (Username, Password)
        VALUES ('".$player_username."','".$hashed_password."')";
        $result = mysqli_query ($conn,$sql);
        echo "User created.";
    }
?>

I can create an account with a hashed password, however, I cannot login with it. I've looked at every post regarding my issue on this website. It's either that I was looking at the wrong thread or I simply did not understand what they were doing.

Fueled By Coffee
  • 2,467
  • 7
  • 29
  • 43
Omar Dajani
  • 378
  • 6
  • 16
  • Make sure the field in your database is at least 60 characters wide. You should really use `VARCHAR(255)` to account for changes in the hash in the future. – Jay Blanchard Dec 20 '16 at 18:30
  • 2
    Remove this from your SELECT query `and Password = ''")` – Jay Blanchard Dec 20 '16 at 18:30
  • Also, you have some nasty SQL injection vulnerabilities. See: [How can I prevent SQL injection in PHP?](http://stackoverflow.com/q/60174/3155639) – Alexander O'Mara Dec 20 '16 at 18:30
  • [Little Bobby](http://bobby-tables.com/) says ***[your script is at risk for SQL Injection Attacks.](http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php)*** Learn about [prepared](http://en.wikipedia.org/wiki/Prepared_statement) statements for [MySQLi](http://php.net/manual/en/mysqli.quickstart.prepared-statements.php). Even [escaping the string](http://stackoverflow.com/questions/5741187/sql-injection-that-gets-around-mysql-real-escape-string) is not safe! [Don't believe it?](http://stackoverflow.com/q/38297105/1011527) – Jay Blanchard Dec 20 '16 at 18:31
  • If an answer solved your problem, consider accepting the answer. Here's how http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work then return here and do the same with the tick/checkmark till it turns green. This informs the community, a solution was found. Otherwise, others may think the question is still open and may want to post (more) answers. You'll earn points and others will be encouraged to help you. *Welcome to Stack!* – Jay Blanchard Dec 20 '16 at 18:39
  • Thank you for your help everyone! :) @Little Bobby - isn't using Bcrypt secure? I was previously using MD5 with no salt, which I found out is not safe at all. Is Bcrypt better in this case? Thanks once again everyone :D – Omar Dajani Dec 20 '16 at 18:39
  • Bcrypt is secure, but you really should use prepared statements for *all* of your queries in addition to hashing the password. – Jay Blanchard Dec 20 '16 at 18:42
  • @JayBlanchard - thank you for your suggestion! I'll make sure to add that asap! :) – Omar Dajani Dec 20 '16 at 18:44

1 Answers1

3

You cannot verify a hashed password because you're select a user having a blank password:

$result = mysqli_query ($conn, "SELECT * FROM users WHERE Username ='$player_username' and Password = ''");

Remove the password test from your query:

<?php
require "Common.php";
$player_username = $_POST ["usernamePost"];
$player_password = $_POST ["passwordPost"];
$hashed_password = password_hash($player_password, PASSWORD_DEFAULT);

$conn = new mysqli ($server_host, $server_username, $server_password, $server_dbName);

$result = mysqli_query ($conn, "SELECT * FROM users WHERE Username ='$player_username'");
$count = mysqli_num_rows($result);

if ($count == 1) {
    $row = mysqli_fetch_assoc ($result);
    if (password_verify($player_password, $row['hashed_password'])) {
        echo "Signing in...<br>";
        echo "ID:".$row ['ID'] . "|Username:".$row ['Username'] . "|Score:".$row ['Score'] . "|Status:".$row ['Status'];
    }
}  else {
    echo "Incorrect username or password.";
}

Since you're only returning one row you have too much code. No need for a while loop and you have to test against the password stored in the database $row['hashed_password'].


In addition:

Little Bobby says your script is at risk for SQL Injection Attacks. Learn about prepared statements for MySQLi. Even escaping the string is not safe! Don't believe it?

EDIT: Here is an example using a prepared statement and proper error checking:

require "Common.php";
$player_username = $_POST ["usernamePost"];
$player_password = $_POST ["passwordPost"];

$conn = new mysqli($server_host, $server_username, $server_password, $server_dbName);

/* check connection */
if (mysqli_connect_errno()) {
    echo "Connect failed: ", mysqli_connect_error());
    exit();
}

 $stmt = $conn->prepare("SELECT * FROM users WHERE Username =?"); // prepare with a placeholder for the variable
 $stmt->bind_param('s', $player_username); // bind the variable
 $stmt->execute(); // execute the query
 $row = $stmt->fetch_assoc(); // get the associative array
 if (password_verify($player_password, $row['hashed_password'])) {
     echo "Signing in...<br>";
     echo "ID:".$row ['ID'] . "|Username:".$row ['Username'] . "|Score:".$row ['Score'] . "|Status:".$row ['Status'];
 } else {
    echo "Incorrect username or password.";
}

Keep in mind that there are a couple of methods for coding and executing prepared statements. Use the method you're most comfortable with.

From Proper Password Preparation with PHP

The password_hash() can generate some very lengthy text (the current default is 60 characters), so making the field larger now will allow for the length needed. Secondly the PHP team is adding more algorithms to the method which means the hash can and will grow. We also do not want to limit our user's ability to use the password or passphrase of their choice. It's best to leave room for the changes.

Set the password field in your database to be large, for example

`password` text DEFAULT NULL
Community
  • 1
  • 1
Jay Blanchard
  • 34,243
  • 16
  • 77
  • 119
  • Thank you for your help! You've been amazing! I changed the length of my password to 255 characters since it looks like I may have to add more security to this script. Do you have any recommendations on how I could add more security to this script or to my registration script? What algorithm(s) should I use? Thanks again for your help! :) – Omar Dajani Dec 20 '16 at 18:42
  • Click on the links to learn how to created prepared statements for all of your queries. That is the single largest thing you can do to help your scripts to be safe. – Jay Blanchard Dec 20 '16 at 18:45
  • Thanks! I just took a look at the Wikipedia link you provided me. I don't quite understand how and where would the prepared statements would be entered. Would they replace the result variable in the login.php script above? Thanks :) – Omar Dajani Dec 20 '16 at 19:06
  • The Wikipedia link is good, but to get more specific look [here](http://php.net/manual/en/mysqli.quickstart.prepared-statements.php) – Jay Blanchard Dec 20 '16 at 19:14
  • @OmarDajani I added an example of prepared statements to the answer. – Jay Blanchard Dec 20 '16 at 19:53
  • thank you so much! I really appreciate all the help! I just one have quick question for you, whenever I login using a user that I created any password can be used and the player would be able to login. – Omar Dajani Dec 20 '16 at 20:02
  • You want to be able to do that? Or is it doing that now? Once you change the column size you need to create new passwords for users that existed before, since their password hashes are probably wrong. – Jay Blanchard Dec 20 '16 at 20:06
  • It is doing that now. And I deleted all the users in my database and set the character limit for the password to varchar(255). I created a new user and tried signing in and now no echo is being displayed which verifies that the user is signed in. – Omar Dajani Dec 20 '16 at 20:09
  • No, I'm not. No message at all. – Omar Dajani Dec 20 '16 at 20:12
  • It automatically displays "Incorrect username or password.". So I'm guessing it is signing with with the username "" and the password ""? I'm however using the Unity Engine to also display my result, so I'm guessing it is a problem on Unity's end then. However, that does not explain why I could sign in with any username. – Omar Dajani Dec 20 '16 at 20:20
  • So I just tried inputing an invalid username and it gives the error: "Incorrect username or password". However, whenever I try signing in I don't get anything. Which probably means that the problem is with this line of code: (password_verify($player_password, $row['hashed_password'])) right? – Omar Dajani Dec 20 '16 at 20:23
  • It is hard to know. Is there anything in the error logs? – Jay Blanchard Dec 20 '16 at 20:43
  • Where are the error logs? I'm using a Mac. Is it like stored in a local directory on my Mac? So sorry for the hassle :( – Omar Dajani Dec 20 '16 at 20:51
  • Since you're using a MAC I assume you're using MAMP as you webserver. `/Applications/MAMP/logs` – Jay Blanchard Dec 20 '16 at 20:54
  • I don't have it installed, i'm going to install it now. I'll let u know what the error log says. – Omar Dajani Dec 20 '16 at 20:56
  • So all along you haven't been running this on a webserver? – Jay Blanchard Dec 20 '16 at 20:56
  • I've been following this tutorial where they use AlwaysData.com for my FTP and mysql server. However, I'm trying to edit the code to my own needs. – Omar Dajani Dec 20 '16 at 20:58
  • And I have been uploading it to my web server. – Omar Dajani Dec 20 '16 at 21:01
  • I was able to fix the error, thank you for your help I really appreciate it. :) – Omar Dajani Dec 20 '16 at 23:19