So, I'm having this issue with my login script where the MD5 password stored in my MySQL database is decrypted and it will check if the password is equal to the one entered.
My code is as follows:
if(isset($_POST['btn-login']))
{
$email = mysqli_real_escape_string($_POST['email']);
$upass = mysqli_real_escape_string($_POST['pass']);
$md5_pass = md5($upass);
$res = mysqli_query($con, "SELECT * FROM users WHERE email='$email'");
$row = mysqli_fetch_array($res, MYSQLI_ASSOC);
if($row['password'] == $md5_pass)
{
$_SESSION['user'] = $row['user_id'];
header("Location: profile.php");
}
else
{ ?>
<script>alert("Wrong details entered!");</script>
<?php
}
}
Both the md5() will be same. You must check your column datatype and number of characters limit.
Check whether your database is having encrypted value. Because you are comparing it with md5() value.
Don't escape before performing md5 on the query.
Ankii's reply can also solve the issue if you have a varchar which is too small.
Also, use a better hashing system (sha512?).
Also, use salt.
Related
I have encrypted and store password. Once user login I want to decrypt and validate .But following code is not able to do that. Can any body help with this?
<?php
include("config.php");
if($_SERVER["REQUEST_METHOD"] == "POST") {
$myusername = mysqli_real_escape_string($con,$_POST['username']);
$mypassword =md5(mysqli_real_escape_string($con,$_POST['password']));
$sql = "SELECT id FROM services WHERE user_name = '$myusername' and password = '$mypassword'";
$result = mysqli_query($con,$sql);
$row = mysqli_fetch_array($result,MYSQLI_ASSOC);
$count = mysqli_num_rows($result);
if($count == 1) {
echo "success";
}else {
echo "fail";
}
}
?>
It isn't necessary to escape value, that will be md5-hashed. You even could change the password (and md5 hash) if it contains some special char. For example, lets see at password's test' hashes:
echo md5(mysqli_real_escape_string($con,$_POST['password']));
echo md5($_POST['password']);
Output is:
e1e7975d4f1958297ede35ea4fc13a27
5c28a8c6d799d302f3ef53afefdfc81b
You shouldn't do:
$row = mysqli_fetch_array($result,MYSQLI_ASSOC);
because you don't use it later and you don't check if num_rows > 0 and it'll give an error if there are 0 records.
md5 should never ever be used for storing passwords.
First off it's been known to be broken for decades already, but that's not the worst of it in this case.
Secondly you're using it without a random salt, which makes it vulnerable to rainbow table attacks.
Finally, and most crucially, it's a fast algorithm, and hence completely unsuitable for password hashing. Any hacker worth their "salt" that gets a hold of your user's hashed passwords will make short work of finding >90% of the passwords in a matter of hours as your users will use predictable passwords instead of truly random ones.
You really need to use something like password_hash().
I found other method and this was success.Thank for your help
<?php
include('config.php');
session_start();
if($_SERVER['REQUEST_METHOD'] == "POST")
{
//Username and Password sent from Form
$username = mysqli_real_escape_string($con, $_POST['username']);
$password = mysqli_real_escape_string($con, $_POST['password']);
$password = md5($password);
$sql = "SELECT * FROM services WHERE user_name='$username' AND '$password'";
$query = mysqli_query($con, $sql);
$res=mysqli_num_rows($query);
//If result match $username and $password Table row must be 1 row
if($res == 1)
{
//header("Location: welcome.php");
echo "did";
}
else
{
echo "Invalid Username or Password";
}
}
?>
I set up a dev server and I installed nginx with php-fpm and 7.2 php (I installed all the necessary php packages).
The time has come to upgrade the security of all logins, using the argon2i algo.
So, I tried this (test code in dev enviroment. The security in the code, will come later):
require('connector.php');
$usr_u = $_POST['username'];
$psw_u = $_POST['password'];
$usr = mysqli_real_escape_string($conn, $usr_u);
$psw = mysqli_real_escape_string($conn, $psw_u);
$f_pass = password_hash($psw, PASSWORD_ARGON2I);
$result = "SELECT `username` FROM `users` WHERE username = '$usr'";
$tbl = mysqli_query($conn, $result);
$table = $tbl->fetch_assoc();
$m_user = $table['username'];
if ($m_user == $usr)
{
//correct username
echo 'Correct username!<br>';
$result = "SELECT `password` FROM `users` WHERE username = '$m_user'";
$tbl = mysqli_query($conn, $result);
$table = $tbl->fetch_assoc();
$m_pass = $table['password'];
if (password_verify($m_pass,$f_pass)) //always returns false
{
echo 'Password correct!<br>';
}
else
{
echo 'Wrong password!<br>';
}
}
else
{
echo 'Wrong username!<br>';
}
//close connection
mysqli_close($conn);
I always get "Correct username!" and "Wrong password!". I used echo on hashed password from the DB and from the input and I see that every time the hashed password is different. I assume that the hashing process, include using random salt and there is my issue.
As far as I understand, the random salt is necessary in order to retain the security of the hashing.
Can you please point me to the right direction, on how to solve this? I have the hashed password in my DB and I can't figure out a way to check the input password against the one in my DB (using password_verify and hash_equals).
Thank everyone in advance for the help.
Look at the documentation for password_verify:
bool password_verify ( string $password , string $hash )
The first argument is the password but you are passing it the hash you want to compare it to.
The second argument is the hash you want to compare it to but you are passing it a new hash created from user input.
password_verify($_POST['password'], $m_pass)
I think i have hashed password using function PASSWORD directly from mysql database(am i doing wrong here?). And i am trying to verify that password with this code:
if($submit)
{
$first=$_POST['first'];
$password=$_POST['password'];
$hash="*85955899FF0A8CDC2CC36745267ABA38EAD1D28"; //this is the hashed password i got by using function PASSWORD in database
$password=password_verify($password,$hash);
$db = new mysqli("localhost", "root","","learndb");
$sql = "select * from admin where username = '" . $first . "' and password = '". $password . "'";
$result = $db->query($sql);
$result=mysqli_num_rows($result);
if($result>0)
{
session_start();
$_SESSION['logged_in'] = true;
session_regenerate_id(true);
header("Location:loginhome.php");
}
}
But the password is not matching. What am i missing here?
UPDATE:
After all the suggestions i have used password_hash from php code to store into database.
$db = new mysqli("localhost", "root","","learndb");
$password=password_hash('ChRisJoRdAn123',PASSWORD_DEFAULT);
$sql="INSERT INTO admin (username,password)values('ChrisJordan','$password')";
$db->query($sql);
still the password is not matching.
One cannot search for a salted password hash in a database. To calculate the hash you need the password_hash() function as you already did correctly in your insert statement.
// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_DEFAULT);
To check a password, you first need to search by username only (used a prepared query to avoid sql injection):
$sql = 'select * from admin where username = ?';
$db->prepare($sql);
$db->bind_param('s', $first);
When you finally got the stored hash from the database, it can be checked like this:
// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);
password_verify is a boolean function which return either true or false. In your code, after getting value of password from Post param, you doing this operation
$password=password_verify($password,$hash);
which changes the $password value to true or false and that boolean value stored in $password you are using in mysql select statement
$sql = "select * from admin where username = '" . $first . "' and password = '". $password . "'";
Another thing is it might be possible that the hashed/salted password you are using is not the correct hashed value of the password you are using.
Update: Try this
$cost = [
'cost' => 15,
];
$hash_password = password_hash('ChRisJoRdAn123', PASSWORD_BCRYPT, $cost);
before any db operation, change your password field varchar length to >=64
$sql = "INSERT INTO admin (username,password)values('ChrisJordan','".$hash_password."')";
After insert operation, execute the select statement with the user
$sql = "select * from admin where username = 'ChrisJordan'";
after this fetching hased password and password from the post parameter, you will need to verify both passwords using password_verify
if (password_verify(validate($_POST['password']), $hash_password_from_db)) {
echo "Valid Password";
}else{
echo "Invalid Password";
}
You must use password_hash to encode passwords verified with password_verify.
The MySQL function PASSWORD is something entirely different. It is used for encoding passwords specific to MySQL authentication. (MySQL specifically recommends against using PASSWORD for anything other than MySQL authentication.)
The two use different hashing algorithms, present their output in different formats, and are generally not compatible with each other.
The typical way to use password_hash and password_verify is:
$hash = password_hash($password, PASSWORD_DEFAULT);
//Store $hash in your database as the user's password
//To verify:
//Retrieve $hash from the database, given a username
$valid = password_validate($password, $hash);
The problem in your code is that you're doing this:
$password=password_verify($password,$hash);
$sql = "select * from admin where username = '" . $first . "' and password = '". $password . "'";
password_verify returns a boolean (whether the password and hash matched). Instead, you need to retrieve the hash from the database and match the entered password with that hash.
This is too long for a comment.
Seeing that this question has yet to contain a green tick next to any of the answers, am submitting the following in order to point out probable issues.
I noticed that you are trying to move over from MD5 to password_hash() - password_verify().
Your other question Switching from md5 to password_hash
What you need to know is that MD5 produces a 32 character length string, as opposed to password_hash() being a 60 length.
Use varchar(255).
If you kept your password column's length to 32, then you will need to clear out your existing hashes from that column, then ALTER your column to be 60, or 255 as the manual suggests you do.
You will need to clear out all your existing passwords, ALTER your column, create a new hash, then try your login code again.
I see this in your code:
"*85955899FF0A8CDC2CC36745267ABA38EAD1D28"; //this is the hashed password i got by using function PASSWORD in database
This string *85955899FF0A8CDC2CC36745267ABA38EAD1D28 is 40 long, which is too short and has been cut off.
This tells me that your column's length is 40, instead of 60, or again as the manual suggests, 255.
MD5 reference:
http://php.net/manual/en/function.md5.php
Returns the hash as a 32-character hexadecimal number.
Reference for password_hash():
http://php.net/manual/en/function.password-hash.php
The result will always be a 60 character string, or FALSE on failure.
To ALTER your column, here is a reference link:
http://dev.mysql.com/doc/refman/5.7/en/alter-table.html
Also make sure that your form contains a POST method and that the inputs bear the matching name attributes and that no whitespace gets introduced.
You can use trim() to get rid of those.
Add error reporting to the top of your file(s) which will help find errors.
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
// Then the rest of your code
Sidenote: Displaying errors should only be done in staging, and never production.
as well as or die(mysqli_error($db)) to mysqli_query().
Edit:
What you need to do is fetch an array and get the match on that.
$sql = "select * from admin where username = '".$first."' and password = '".$password."' ";
$result = $db->query($sql);
if ($result->num_rows === 1) {
$row = $result->fetch_array(MYSQLI_ASSOC);
if (password_verify($password, $row['password'])) {
//Password matches, so create the session
// $_SESSION['user']['user_id'] = $row['user_id'];
// header("Location:/members");
echo "Match";
}else{
echo "The username or password do not match";
}
}
Another possible solution:
$query = "SELECT * from admin WHERE username='$first'";
$result = $db->query($query);
if($result->num_rows ===1){
$row = $result->fetch_array(MYSQLI_ASSOC);
if (password_verify($password, $row['password'])){
echo "match";
} else {
$error = "email or Password is invalid";
echo $error;
}
}
mysqli_close($db); // Closing Connection
The md5 is posting to the database from the signup page so I know that's working, but everything I try here won't let me sign in and just keeps telling me I have the wrong password.
<?php
// Parse the log in form if the user has filled it out and pressed "Log In"
if (isset($_POST["user_name"]) ) {
$user = mysql_real_escape_string($_POST["user_name"]);
$pass_word = mysql_real_escape_string(md5($_POST["pass_word"]));
$pass_word=md5($pass_word);
// Connect to the MySQL database
include "../connect_to_mysql.php";
$sql = mysql_query("SELECT m_id FROM member WHERE user_name='$user' AND pass_word='$pass_word' LIMIT 1"); // query the person
// ------- MAKE SURE PERSON EXISTS IN DATABASE ---------
$existCount = mysql_num_rows($sql); // count the row nums
if ($existCount == 1) { // evaluate the count
while($row = mysql_fetch_array($sql)){
$id = $row["m_id"];
}
$_SESSION["m_id"] = $id;
$_SESSION["user"] = $user;
$_SESSION["pass_word"] = $pass_word;
header("location: ../../index.php");
exit();
} else {
echo 'That information is incorrect, try again Click Here';
exit();
}
}
?>
You're running MD5 twice on your password.
$pass_word = mysql_real_escape_string(md5($_POST["pass_word"]));
$pass_word = md5($pass_word);
Also, don't use MD5, it is completely unsafe, look into using bcrypt, it is secure, and very easy to implement in PHP. Replacing MD5 with this line of code will make your password hashes safe. Preferably add some salt, the salt being some random string. It will make breaking your passwords nigh impossible.
$hash = password_hash($password . $salt, PASSWORD_BCRYPT);
Change these lines from
$pass_word = mysql_real_escape_string(md5($_POST["pass_word"]));
$pass_word=md5($pass_word);
to
$pass_word=md5($_POST["pass_word"]);
My login form isn't recognising existing users. The passwords I have stored in the database are encrypted using PHP's crypt() function. When the user registers their password is also encrypted and inserted into the database.
As you can see in the code below it checks to see if the password entered below matches, but whenever I enter in a password that is stored in the database with the corresponding username it says that the user does not exist.
I'm new to PDO and this is my first time using it, normally if I just use MySQL it works fine, but for some reason this isn't, I have changed the code a bit yet it still does not work. Anyone know why/where/what I'm doing wrong with the code.
include "connect.php";
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT * FROM users WHERE username=:username";
$statement = $db->prepare($sql);
$statement->bindValue(':username',$username,PDO::PARAM_STR);
if($statement->execute())
{
if($statement->rowCount() == 1)
{
$row = $statement->fetch(PDO::FETCH_ASSOC);
if(crypt($password, $row['username']) == $row['user_password'])
{
$username = $row['username'];
$email = $row['email'];
$_SESSION['username'] = $username;
$_SESSION['email'] = $email;
$_SESSION['logged_in'] = 1;
header("Location: index.php");
exit;
}
else
{
include "error_login.php";
}
}
else
{
include "error_login.php";
}
}
if(crypt($password, $row['username']) == $row['user_password'])
Should be
if(crypt($password) == $row['user_password'])
To verify a password with its stored hash-value, you need to know the salt and the algorithm that was used to generate the hash-value before. This salt can be extracted from the stored hash-value, because crypt() stores it as part of the resulting string.
if (crypt($password, $row['user_password']) === $row['user_password'])
PHP 5.5 will have it's own functions password_hash() and password_verify() ready, to simplify generating BCrypt hashes. I strongly recommend to use this excellent api, or it's compatibility pack for earlier PHP versions. The usage is very straightforward:
// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);
// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);