Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Improve this question
I have a problem with a bit of code and connat figure why it is going wrong
//Searches the database for the username
$mysqli_username = mysqli_query($mysqli, "SELECT username FROM ajbs_users WHERE username=`".$username."`");
// if name does not exist
if ($mysqli_username == null)
{
echo "<p>Username was inccorect, or user does not exist</p>";
}
else //if username is correct
{
//finds and stores password of the user
$mysqli_userPassword = mysqli_query($mysqli, "SELECT password FROM ajbs_users WHERE password=`".$password."`");
if ($mysqli_userPassword != $password) //checks password matches from user
{
echo "<p>Password was inccorrect</p>";
}
else
{
//Login
echo "<p>You have been logged in";
// Re directs to other page after creating a session
}
}
The script keeps outputting the "Password is incorrect" statement.
There are a number of problems with your code:
mysqli_query() does not return rows from the database, it returns a resource from which you can fetch rows from the database. Or else it returns false if the query produces a parse error or an execution error. You need to check for these error cases.
Or else use mysqli_report(MYSQLI_REPORT_STRICT) to configure mysqli to throw exceptions on error (if you know how to program with exceptions).
You are using the back-ticks around the values $username and $password. Back-ticks are for delimiting identifiers like table names and column names. For string values and date values, use single quotes. Double-quotes are used the same as single quotes by default, for strings and dates. But this can change if you set MySQL into ANSI mode, then double-quotes are used like back-ticks, for identifiers. See MySQL's different quote marks
You are interpolating variables directly into your SQL expressions, which is not safe unless you've been very careful to escape them. This is how SQL injection happens. Read What is SQL injection? and How can I prevent SQL injection in PHP? You should use prepared statements and add dynamic elements to the query using parameters.
Keep in mind that if you use parameters, the quote issue disappears. You don't put any type of quotes around parameters. Using parameters is both easier and more secure than interpolating variables into strings.
And some problems with your logic or application design:
You checked if a username exists. Then if it does, you checked if a password exists. But in your code, the password is not necessarily used by the same username. Your code doesn't check that the same user has that password, only that any user has that password.
What this means is that I can hack your site if I can register one username with password I know, say 'xyzzy'. Then I can log in as any other username, using password 'xyzzy'.
It's not a good security practice to tell the user whether the username or the password is incorrect. They should only be told that the login failed. If they're a hacker, it can be useful to them to know that they're on the right track, that is, they have chosen a valid username, they just need to guess the password. You might want to log the information for your own troubleshooting, but be more vague as you report to the user.
You shouldn't store a plaintext password. Store a hash of the password. Also store a random salt per user, and use that in the hash calculation. See You're Probably Storing Passwords Incorrectly and What data type to use for hashed password field and what length?
You can do this search with one query instead of two if you compare the username and password in one query. I search for the username in the WHERE clause, and then return the result of a boolean comparison of the stored password hash against the hash of the user's input.
So here's how I would write it, keeping in mind all the points from above.
/*
* Search the database for the username, and report if the password matches
*/
$sql = "SELECT (password = SHA2(CONCAT(?, salt), 256)) AS password_matches
FROM ajbs_users WHERE username = ?";
if (($stmt = $mysqli->prepare($sql)) === false) {
trigger_error($mysqli->error, E_USER_ERROR);
}
$stmt->bind_param("ss", $password, $username);
if ($stmt->execute() === false) {
trigger_error($stmt->error, E_USER_ERROR);
}
$stmt->bind_result($password_matches);
if ($stmt->fetch()) {
if ($password_matches) {
echo "<p>You have been logged in";
// Re directs to other page after creating a session
} else {
error_log("Login attempted with user '$username', but password was incorrect.");
}
} else {
error_log("Login attempted with user '$username', but user does not exist.");
}
// Tell the user only what they need to know.
echo "<p>Login failed. Username or password was incorrect</p>";
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
this is my first time posting on stackoverflow for a couple of years, so please excuse me if this isn't the correct posting format.
I'm trying to create a simple php registration and login script using mysqli. I have not yet added prepared statements to protect myself from SQL injection attacks as I want to learn the basics of submitting and receiving data from a mysql database first.
I have created a registration script that uses the password_hash function. This is completely working and is submitting to my mysql database perfectly.
However, i'm having problems with the password_verify function. I cannot get it to seem to work. If i don't use the password_hash or password_verify function in my register.php or login.php, the login works perfectly.
Although when using password_verify and password_hash together i cannot get the code to work.
Here's the code for my login.php:
<?php
include('database_connect.php');
if(isset($_POST["submit"])) {
$email = $_POST['email'];
$password = $_POST['password'];
$query = mysqli_query($conn, "SELECT * FROM users WHERE email='$email'");
$row = mysqli_fetch_array($query);
$encrypted_password = $row['password'];
if($row == 1) {
if(password_verify($password, $encrypted_password)) {
session_start();
$_SESSION['email'] = $email;
header("Location: index.php");
exit;
} else {
echo "Incorrect email or password";
}
} else {
echo "Email cannot be found, please sign up for an account";
}
}
?>
Here is the code for my register.php:
<?php
include('database_connect.php');
if(isset($_POST["submit"])) {
$firstName = $_POST['firstName'];
$lastName = $_POST['lastName'];
$email = $_POST['email'];
$password = $_POST['password'];
$confirmPassword = $_POST['confirm_password'];
$encrypted_password = password_hash($password, PASSWORD_DEFAULT);
$sql = "INSERT INTO users (firstName, lastName, email, password) VALUES ('$firstName','$lastName', '$email', '$encrypted_password')";
if ($conn->query($sql)) {
echo "<span>Account created succesfully, please <a href='login.php'>log in</a></span>";
} else {
echo "<span>There was an error, please contact site administrator</span>";
}
}
?>
I have removed the registration form validation so that the code is easier to read. If anybody could point me to the right direction or help me out, i would gladly appreciate it.
I'm pretty certain it has something to do with password hash, but i'm not sure and after countless attempts i cannot get it working.
All the best.
(in no particular order)
1)
$encrypted_password = password_hash('$password', PASSWORD_DEFAULT);
'$password' is a literal $password, because it is in single quotes PHP ignores the variable identifier ($) and prints it directly, as-is.
So your password value is always going to be "$password" and not the string that you were given in $_POST['password'].
Read about this on the original Q&A
2)
$row = mysqli_num_rows($query);
This variable is a numeric counter of rows, it is not the data within the rows.
To get the data within the rows you want mysqli_fetch_array($query) (or its similar companions).
So;
$row = mysqli_fetch_array($query);
This will be an array of data values from the database.
3)
Your code is wide open to SQL Injection attack and is completely unsafe. Yes, you're using password hash; that's a start, but you're not securing your user submitted data.
You should be using either MySQLi or PDO Prepared Statement RIGHT NOW.
4)
Headers should always be followed by die/exit commands to stop PHP continuing to execute script actions before deciding to follow the header() relocation action.
e.g.
header("Location: home.php");
exit;
5)
Whilst you may technically survive this time, on this page, you should be putting session_start(); at the very top of your PHP page, not half way down nestled in an unrelated if statement. this is inconsistent and very poor coding that will come back to bite you in the arse.
6)
Look at number 3 again, above, and absolutely do it!
7)
NEVER TRUST USER DATA. EVER.
So check and verify all values passwed from the <form> are roughly the expected shape. (filter_var($email, filter_validate_email) ;-)
After update to question.
8)
Read your PHP Error Log file. This will save you (and us all) an epic amount of time!
9)
Best practise is that if you're using PASSWORD_BCRYPT or PASSWORD_DEFAULT that you really, really should be manually setting the cost parameter yourself as the default value (10) is far too low. You should be setting it to as high a value as your server can comfortably take (14 as a guideline minimum).
Please view the details on the PHP Password_hash Manual page.
$encrypted = password_hash($password, PASSWORD_DEFAULT, ['cost' => 15]);
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
Background -
I have spent the last hour or so looking through various posts sites and so on to see why my password checking function has suddenly stopped working.
Every time I try to use it, it returns false, including when the inputted password is correct.
I have echoed my input and my hash, both of which match fine (by comparing the hash in the table to the one echoed).
However, when these variables are put through password_verify, it returns false 100% of the time.
What do I think is wrong? - Based on a post from an external site, I think this is due to the way that my hashedPassword variable is being parsed. When is compares the two, something goes wrong in the variable type and returns false.
What does my code and database look like? -
users table. Contains other columns.
userId | username | password
----------------------------
1 | example | temp1
Class containing the password checker function. (Have trimmed away try/catch)
public function checkPasswordCorrect($username, $password) { // Returns true is the entered password is correct and false if it isn't.
// This creates a mysqli context to run the connection through.
$mysqli = new mysqli($this->dbHost, $this->dbUsername, $this->dbPassword, $this->dbPlusPlus);
// If there is an error connecting to the database, it will be printed and the process will close.
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$sql = "SELECT password FROM users WHERE username='$username'";
$result = $mysqli->query($sql);
$row = $result->fetch_array(MYSQLI_ASSOC);
$hashedPassword = $row["password"];
$mysqli->close();
echo $password."<br>".$hashedPassword."<br>"; // The input is correct and the hash matches that in the table.
// We return a value of true or false, depending on the outcome of the verification.
if(password_verify($password, $hashedPassword)) {
echo "return true";
return true;
}
else {
echo "return false";
return false;
}
}
By echoing $hashedPassword just before using password_verify, the hash matches by manually checking it, as you can see by the output below.
temp0022
$2y$10$9TgjJzSaqOB
return false
What am I asking? -
Is there a better way of checking password inputs, more specifically, the way I'm pulling the information from the table (there must be some simpler way of doing this).
Is the variable parsing to blame? Is there any documentation or articles available for this topic that I haven't seen?
What am I aware of? - My usage of mysqli is shocking, I'm new to it. I am also aware that there are similar answers out there, but seem to be down to some kind of syntax error more than anything else.
Thank you for taking the time to help! :D
For all of those of you who are worried that I'm going to be hit by SQL injection attacks: I have since modified this example code
massively and am using prepared, statements. Thank you for your
concern :)
Check your table structure. Your hash field needs to be of length 60 (for PASSWORD_BCRYPT) or 255 (for PASSWORD_DEFAULT) (ref) to save the whole hash. What you got from the database is 18 characters long. You probably have it as VARCHAR(18), so it's getting truncated upon saving, which is why you're not getting a match.
Edit: Added length for the PASSWORD_DEFAULT algorithm. Thanks #Don'tPanic.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have a basic question, just starting to dive into PHP and Mysql.
There seems to be an error in this construct, can anyone help me?
Thanks!
K.
if ($password = mysqli_query ("SELECT password FROM users WHERE firstname = '$username'")) {
echo "password success!";
}
else {
echo "Password fail!";
}
Step one when you have a question, refer to the manual.
http://php.net/manual/en/mysqli.query.php
Now are you using the object oriented style or procedural? You are missing the link in either approach.
Once you resolve that you have the issue that the function doesn't return a string.
Returns FALSE on failure. For successful SELECT, SHOW, DESCRIBE or EXPLAIN queries mysqli_query() will return a mysqli_result object. For other successful queries mysqli_query() will return TRUE.
So with that you'll either get false on an error or a mysqli_result object. To parse through the object use fetch; http://php.net/manual/en/mysqli-stmt.fetch.php.
But first you should be using prepared statements which will greatly reduce your chances of being SQL injected; http://php.net/manual/en/mysqli.quickstart.prepared-statements.php.
After that you should pass the password in with your query because you can just have mysql evaluate that the password and username match up then if you get a returned result you know the data is valid.
Additional note: you shouldn't store passwords in plain text, if you are.
Also the = assigns a value. To compare two values you need to use == or ===. For a longer write up see http://php.net/manual/en/language.operators.comparison.php.
In mysqli you have to store your db_connection into a variable and have to pass in every query. Below is the complete path what you have to follow:
Create connection with database by using host_name, user_name, password,db_name. And store connection into a variable.
You can run any query by passing connection variable.
below code is:
<?php
$con = mysqli_connect("localhost","my_user","my_password","my_db");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
if ($password = mysqli_query ($con, "SELECT password FROM users WHERE firstname = '$username'")) {
echo "password success!";
}
else {
echo "Password fail!";
}
?>
Assuming your connection details are stored in a variable $db
Firstly, you need to provide mysqli_query with the database connection resource in procedural mode.
$password = mysqli_query($db, "SELECT password FROM users WHERE firstname = '$username'");
For some reason, this query is running case-sensitive:
$stmt = $db->prepare("SELECT * FROM people WHERE email = :email LIMIT 1");
It simply returns whether or not it found the user:
$stmt->bindParam(':email', $email);
$stmt->execute();
$row = $stmt->fetch();
if($row['email'] == $email)
{
return "<span style='color: red;'>User found.</span><br>";
} else {
return "<span style='color: red;'>User not found.</span><br>";
}
(By the way, this is all just staging. There will be password hashing as soon as I see this is working properly).
It finds the user no problem if I use the same case as the database entry.
Here is my table, so you can see it's all defined ci:
This is actually an existing site that I built when I didn't know much about php, so I'm totally re-writing a lot, and setting up proper password hashing and https. This was all working fine before I wrote the new function and nothing in the database has changed...
So right now it only checks the email entered, just to see if the query is functioning and we're getting results from the database, later on we'll check the password and add actual login functionality.
Here is the data in the database:
Now if I fill out my username as "chris", and run the function, it returns "User Found", so I know the query was successful. If I fill it in as "Chris", however, it returns "User not found.", so I know it was unsuccessful.
Found the issue, though. Posted as an answer.
The issue is with:
if($row['email'] == $email)
The "==" comparison of the strings is case sensitive. A better way to do this would be to use:
if(!empty($row['email']))
If $row['email'] is not empty, then the query returned a result and was successful, else the query failed, which would be caused by using an email address which does not match any in the database.
To make the string comparison case inssensitive requires one of three approaches
Use lower (this will effect performance)
$stmt = $db->prepare("SELECT * FROM people WHERE LOWER(email) = LOWER(:email) LIMIT 1");
Another way is to use collation
And a way that I use is that I store the email as lower case to begin with and convert the search string to lower before doing the search.
I need the following authentication script finished. I am weak at php/pdo so I do not know how to ask for the number of rows equalling one and then setting the session id's from the results of the query. I need to not only set the $_SESSION['userid'] but also the ['company'] and the ['security_id'] as well from the results.
here is what I have:
$userid = $_POST['userid'];
$password = $_POST['pass'];
if ( $userid != "" || $password != "" )
{
$sql = "SELECT * FROM contractors WHERE userid = '" . $userid . "' AND password = '" . $password . "'";
$result = $dbh->query( $sql );
} else
{
echo "login failed. Your fingers are too big";
}
Optional Information:
Browser: Firefox
DO NOT EVER USE THAT CODE!
You have a very serious SQL injection open there. Every user input that you take, whether from cookies or CGI, or wherever, must be sanitized before it's used in an SQL statement. I could easily break into that system by attempting a login with an username like:
user'; UPDATE contractors SET password = '1337'
... after which I could then login as anyone. Sorry if I sound aggressive, but what that code does is like forgetting to lock the front door into your company which probably doesn't even contain an alarm system.
Note that it doesn't matter whether the input is actually coming from the user or not (perhaps it's in a pre-filled, hidden from). From the security point of view, anything that comes from anywhere outside has to be considered to contain malicious input by the user.
As far as I know, you need to use the quote function of PDO to properly sanitize the string. (In mysql, this would be done with mysql_real_escape_string().) I'm not an expert on PDO, mind you, somebody please correct if I'm wrong here.
Also you probably shouldn't store any passwords directly in the database, but rather use a hash function to create a masked password, then also create a hash from the user provided password, and match the hashes. You can use the PHP hash function to do this.
As for other issues, I don't know if the approach you have on SQL SELECT is the best approach. I would just select the corresponding user's password and try matching that in the program. I don't think there's any fault in the method you're using either, but it just doesn't seem as logical, and thus there's a greater chance of me missing some bug - which in case of passwords and logins would create a window for exploits.
To do it your way, you need to notice that the result you are getting from the PDO query is a PDOStatement, that doesn't seem to have a reliable function to diretly count the amount of result rows. What you need to use is fetchAll which returns an array of the rows, and count that. However, as I said this all feels to me like it's open for failures, so I'd feel safer checking the password in the code. There's just too much distance from the actual password matching compasion for my taste, in such a security-critical place.
So, to the get the resulting password for the userid, you can use PDOStatement's fetch() which returns the contents of the column from the result. Use for example PDO::FETCH_ASSOC to get them in an associative array based on the column names.
Here's how to fix it:
$userid_dirty = $_POST['userid'];
$password_dirty = $_POST['pass'];
$success = false; // This is to make it more clear what the result is at the end
if ($userid != "" || $password != "") {
$userid = $dbh->quote($userid_dirty);
$passwordhash = hash('sha256',$password_dirty);
$sql = "SELECT userid, passwordhash, company, security_id FROM contractors WHERE userid = ".$userid;
$result = $dbh->query( $sql );
if ($result) { // Check if result not empty, that userid exists
$result_array = $result->fetch(PDO::FETCH_ASSOC);
if ($result_array['PASSWORDHASH'] == $passwordhash) {
// login success
$success = true;
// do all the login stuff here...
// such as saving $result_array['USERID'], $result_array['COMPANY'], $result_array['SECURITY_ID'] etc.
} // else fail, wrong password
} // else fail, no such user
} else {
// fail, userid or password missing
echo ' please enter user id and password.';
}
if (!$success) {
echo ' login failed.';
}
Of course, the code can be cleaned up a bit, but that should explain what needs to be done. Note that since the password is both hashed, and never used in the SQL, it doesn't actually need cleaning. But I left it there just in case, since in the original code it was used in the query.
Note that all the code concerning storing passwords need to be changed to store the hash instead of the password. Also, it would be a very good idea to use a salt added to the password before hashing.
Also, I provided the code simply for educational purposes - I just thought that code was the clearest way to explain how to do this. So do not mistake this site as a service to request code. :)
The php manual is an excellent resource for learning PHP. It looks like you know a little SQL, and you have heard of PDO, which is a good start. If you search google for "PDO", or look in the PHP manual for the term, you'll find the PDO section of the manual. It looks like you've found the ->query function, so now you need to see what that returns. Going to the that function's manual page, we see that it returns a PDOStatement object. The word PDOStatement is helpfully linked to the relevant page in the manual, which lists the methods available on that object. There is a rowCount() method that will likely do what you want.