I need help with my login-script – it seems to be broken. If I enter no password I still get logged in correctly. Also if I don’t enter anything. But if I enter the wrong username AND password it says my login credentials were wrong.
<?php
$verbindung = mysql_connect("localhost", "root" , "")
or die("Verbindung zur Datenbank konnte nicht hergestellt werden");
mysql_select_db("v1nce_website") or die ("Datenbank konnte nicht ausgewählt werden");
$username = $_POST["username"];
$password = $_POST["password"];
$abfrage = "SELECT username, password FROM logins WHERE username='$username' LIMIT 1";
$ergebnis = mysql_query($abfrage);
$row = mysql_fetch_object($ergebnis);
if($row->password == $password)
{
$_SESSION["username"] = $username;
echo "<p>Login erfolgreich.</p>";
}
else
{
echo "<p>Benutzername oder Passwort waren falsch. <a href=\"index.php?p=login\">Login</a></p>";
}
?>
Any help would be appreciated.
There’s a lot of things going on in this script that are worrisome:
Let’s start with the actual problem you are here for. If your query won’t find a matching row,
$rowwill equalfalse. And since therefore,$rowis not an object,$row->passwordwill evaluate toNULL. And so, if$passwordis an empty string$row->password == $passwordwill evaluate to true, becauseNULL == ""is truthy.You would have been notified of this, had you turned on the displaying of errors, for instance with
ini_set( 'display_errors', true );, in combination with a sufficient error reporting level,error_reporting( E_ALL );for instance.When you enter a wrong username and a wrong password,
$row->passwordwill again beNULL, but since you entered a non-empty string for a password, this time$row->password == $passwordwill evaluate to false.So, to mitigate this problem you need to make certain that you first check that there is actually a matching row, before you start comparing the passwords, for instance by evaluating
mysql_num_rows( $ergebnis )first.Your script is vulnerable to SQL injection. This means that users of your script could potentially do harm when they enter SQL hacks as values for
$_POST[ 'username' ]. For instance if I were to enter' OR 1 = 1 --your SQL query would result in the following (formatted for display purposes):… always resulting in at least one row if the table is non-empty, because
WHERE username='' OR 1 = 1always evaluates to true (--in SQL signifies a comment, so' LIMIT 1won’t even be evaluated anymore).To mitigate this problem, in your current setup, you need to sanitize your input values first with
mysql_real_escape_string(), before passing them into the SQL query, like this:But as others have advised already as well, you’d be wiser to start using a MySQL compliant library that offers prepared statements with parametrized queries, such as PDO or MySQLi, since the
mysql_*library is in the process of being deprecated, because it offers poor means of defending against SQL injection.Your passwords are stored verbatim (as plain text) in the database. This offers a variety of potential risks of accounts (and possibly user-related accounts) being compromised. Anyone who has access to the database (be it direct, authorized, access, or when the database is compromised) can view the passwords in clear text, and could therefore use these to either log in to your site, or use it as a potential login for other sites and/or services. After all, it is not uncommon for people to use the same combination of username and password for a variety of other sites and services.
To mitigate this problem you’d be wise to hash (one-way encrypt) the passwords before storing them in the database, and then, when the user wants to log in, compare the stored hashed value with the hash (using the same hashing function again) of the user entered password. Using a unique salt per user password as an extra security measure is also strongly advised, as this protects against what is known as rainbow table attacks.
For a more thorough explanation of what the preferred hashing algorithm to use is, and why, see this answer by user Andrew Moore to this question.