Password works even with extra characters - php

I have two methods that I am using. When a user creates an account I call this method to make a secure password hash for them to save into the database:
public function createPassword($password){
$salt = hash("sha256", time() . uniqid() . rand(1, 1000));
return crypt($password, $salt);
}
It returns a salt which I then save into the database in the password column.
Next when a user logs into his/her account I select their info from the database and pass it to this function which then is supposed to verify their password.
public function verifyPassword($password, $salt){
if(crypt($password, $salt) == $salt){
return true;
}
return false;
}
The issue is that I have found a password that if I put the correct password in it works, but if I add extra characters to the end of the password it still works. This shouldn't happen. am I doing something wrong or is this a bug in php?
For security I am not using the real password below
// Create during registration
$salt = $obj->createPassword('abc123');
// Save to database here
then:
// Get row from database save array $row
if($obj->verifyPassword($_POST["passwd"], $row["password"])){
// Log user in
}
Here are my tests:
abc123 // Works
abc12 // doesn't work
abc12jfjf // doesn't work
abc123123 // Works
abc123asdfadffa // Works
So, it looks as if as long as the string starts with the real password anything after is fine...

This may depend on the encryption method you are using. In your example, is the actually password you are using 8 characters?
If so, then any characters past the 8th are truncated.
https://bugs.php.net/bug.php?id=11240
To avoid this behavior, use MD5 encryption.

Related

Matching hashed password with db password for login sha256 with pepper

It is my understanding reg and login (on a very basic level) work like this...
On registration the password is hashed then sent to the db.
On login the inputted password is hashed using the same hash function then compared using password_verify for a match before procceding.
With this in mind i wrote a php hash function (based on a comment I found at https://www.php.net/manual/en/function.password-hash.php#124138 (I have changed pepper detail for this example)
hash function..
function shashpw($ppw) {
$pepper = "DXmdpEcFwc1dm3jlvxiSVf";
$pwd_peppered = hash_hmac("sha256", $ppw, $pepper);
$pwd_hashed = password_hash($pwd_peppered, PASSWORD_ARGON2ID);
return $pwd_hashed;
}
Example input and outputs..
$pw = "#Hqq20";
echo shashpw($pw);
//output examples..
$argon2id$v=19$m=65536,t=4,p=1$YVozcUxkdWVCemN2OHh2Qg$KUgtrw+yJL6mH9D7besewB2pf6KHxUpxeX12DDPX4ms
$argon2id$v=19$m=65536,t=4,p=1$QXYuckpPYy43YlRmQlZmUw$6qd5Vwn6ac3yr4X3MwRksFZ8GleHotjhgfeavY0f5cg
So you get a new hash each time you run the function, great however there in lies my problem.
If i run the same password hash function at the login on the user inputted password for checking against the db stored at reg password hash they will never match, as the hash is new everytime. What am i doing wrong?

Using crypt () blowfish hash during login [duplicate]

This question already has an answer here:
bcrypt and randomly generated salts
(1 answer)
Closed 8 years ago.
* A REAL WORKING ANSWER is at the bottom of this page! *
This is a question about using crypt () blowfish hash during login for customer verification. I am restricted to PHP 5.3 by my web host and I know it would be better to use PHP 5.5 with password hash () and password verify() but PHP 5.3 doesn’t seem to recognize them. The problem is not hashing the password and putting it in the database the available codes on line work for that. The problem is all the codes I found (about ten so far) don’t take into consideration that the randomized salt that is highly recommended for the registration page can’t be used on login passwords because it will be different every time with no match. Is what I am trying to do not possible on PHP 5.3 or is there a way to re-hash the users password using the salt it was randomized with so it can be checked against the one stored in the database?
Codes like this work well for randomizing the salt and hashing the password for the database entry.
function better_crypt($input, $rounds = 9)
{
$salt = "";
$salt_chars = array_merge(range('A','Z'), range('a','z'), range(0,9));
for($i=0; $i < 22; $i++) {
$salt .= $salt_chars[array_rand($salt_chars)];
}
return crypt($input, sprintf('$2a$%02d$', $rounds) . $salt);
}
$password_hash = better_crypt($input);
But login codes like this don’t work and the functions from the registration page must be redefined on the login page some how. They don’t carry over like session variables. I know I must be missing something… Does anyone have a code that will work for this funtion?
$password_hash = better_crypt($db_password_hash);
if (crypt($user_password, $password_hash) == $password_hash) {
echo '<br>';
echo 'true';
}else{
echo '<br>';
echo 'false';
}
Can’t add comment at bottom of page… I don’t have permission?
The “better crypt” function is for the registration page, it could be called something else. I don’t think it is used for the login page or the PHP include page, but this is what I am asking. Is there a login function or code that can use the original salt and how do I get it out of the hashed password in the database to check it and verify the user?
About the answer (bcrypt and randomly generated salts)
How do I extract the original randomized salt from the hashed password stored in the database or do I try to separate it first during registration and save it separately to use during login? I read this not the way it is suppose to work.
Hi martinstoeckli … The link to “compatibility pack “ goes to the PHP manual on “password_hash”, I don’t see any compatibility pack. The algorithm is set by blowfish and it stays the same for every hashed password. Using crypt by itself is weaker then blowfish, but even that dose not solve the login problem I am asking about. I tried that frist.
If anyone has a working login code to use with blowfish ($2a$) algorithm and using any cost value, please post it. It needs to extract the salt from the saved hashed database password to hash the user enter password during login for comparison. Somehow... Using a fixed salt is not recommended so the randomized salt during registration must be extracted somehow from the saved hash password.
Hi deceze,
I did check the duplicate but it had no login code to try. I will try to make a new code to test using this one line below… where $passwordToCheck is the login password and $2y$10$abcdefg... is the stored hashed password in the database. I will put it in an “if statement and echo if it is true or else false”. Get back to you with the results…Thanks
crypt($passwordToCheck, '$2y$10$abcdefg...')
deceze,
I tried this code below with the “,” and “==” both return true or “worked!” with any password input into the login. Please post the code you use for your login page so I can test or modify it to use on mine .
if
(crypt($user_password == $db_password_hash)){
echo '<br>';
echo ' Worked! ';
echo '<br>';
}
else
{
echo '<br>';
echo ' Did not work ): ';
echo '<br>';
}
Also I am using “$2y$11$” now for the algorithm and cost parameter on my registration page with database input like this “$2y$11$9MUd40QqfmmtPaes91OttOlvAhkAtMvS4.mtg9LT.tazythwhRMwu”
Would someone please remove the post that this question has been answered. This will just frustrate others trying to fine an answer to this problem as I have been for days now. Again if anyone does have a working code to answer this question please post it so this problem can get resolved for others STILL NEEDING A REAL WORKING ANSWER!
//////////////////////////////////////////////////////////////////////////////
EUREKA! “I found it” or at least learned how to write the code.
This is A REAL WORKING ANSWER! , The Blowfish login code I wish I had days ago, when I sill had hair!
The "$2y$" is better for PHP 5.3.7 or higher but I must use the "$2a$" algorithm for PHP 5.3 as explained below from http://php.net/manual/en/function.crypt.php.
Versions of PHP before 5.3.7 only support "$2a$" as the salt prefix: PHP 5.3.7 introduced the new prefixes to fix a security weakness in the Blowfish implementation. Please refer to » this document for full details of the security fix, but to summarise, developers targeting only PHP 5.3.7 and later should use "$2y$" in preference to "$2a$".
<?php
// Blowfish login code to verify user login password with the hashed password in database
// Make variables from login form on another page and use “include()” to get this PHP code
$user_name_from_login = $_POST[ 'login_user_name' ];
$user_password_from_login = $_POST[ 'login_password' ];
//Check users name for match in your database table of user names
// You must use a line like this “include(‘your_conection_name.php');”
//at the top of your page to get the database connection code or add it directly to this page for this to work
$sql = "SELECT * FROM customers WHERE user_name=:login_user_name";
$query = $db->prepare( $sql );
$query->execute( array( ':login_user_name'=>$user_name_from_login ) );
$results = $query->fetchAll( PDO::FETCH_ASSOC );
//Get hashed password in database associated with user name and make it into a php variable
foreach( $results as $row ){
$database_password_hash = $row[ 'password' ];
}
//Using the Blowfish “$2a$” algorithm with a cost of “11$” and random salt form registration page
// this one line converts login password to the original saved hashed so it can be compared with the one saved in database
$user_password_rehashed = crypt($user_password_from_login, $database_password_hash);
//Now a simple comparison can be made and verified with an “if else” using the variables above
if
($user_password_rehashed == $database_password_hash) {
echo '<br>';
echo ' User’s login password “IS A MATCH” with the one in database (:';
echo '<br>';
}
else
{
echo '<br>';
echo ' User’s login password “DOES NOT MATCH” with the one in database ):';
echo '<br>';
}
//Check your output to better understand process
echo '<br>';
echo ' $user_password_from_login = ' . $user_password_from_login;
echo '<br>';
echo ' $user_password_rehashed --- = ' . $user_password_rehashed;
echo '<br>';
echo ' $database_password_hash --- = ' . $database_password_hash;
echo '<br>';
?>
I hope this will save time and money for other web designers…
I know it would be better to use PHP 5.5 with password hash () and password verify() but PHP 5.3 doesn’t seem to recognize them…
Use the password_compat library. It provides those functions for PHP 5.3.7 and later.
The problem with your better_crypt() function is that it generates a new random salt every time it is called, so the results can't be verified. To be compatible with crypt(), it would need to take a salt from another password hash as input.
But don't do that. Use password_compat.

How to use the password_needs_rehash function in PHP 5.5

I have a set of passwords in my database that I had earlier hashed using sha512 and now that I have upgraded my server to PHP 5.5, I would like to use the bcrypt password hashing. So my idea is to have the user's login and then call this password_needs_rehash function described here to check the password and then update the password hash in database:
http://php.net/manual/en/function.password-needs-rehash.php
I'm not sure how to use this function though,there are no examples listed here and it doesn't really clarify what the options array is for. Do I just need to call the password_needs_rehash function like this:
if (password_needs_rehash ($current_hash, PASSWORD_BCRYPT)) {
// update the password using password_hash
}
Yes, that's the general idea.
If the password needs to be rehashed, then you just call password_hash() to rehash it. And, of course, save the new hash in your database.
if (password_needs_rehash ($current_hash, PASSWORD_BCRYPT)) {
// update the password using password_hash
$new_hash = password_hash($cleartext_password, PASSWORD_BCRYPT)
// update the database
...
}
Yes, that's correct. The only option you may want to set is "cost", denoting how much work it takes to generate the hash (and therefore how hard it is to crack). Cost defaults to 10 for bcrypt but can be increased to make hashes harder to crack. So you might set "cost" to 11 here, and use the same value when generating new hashes. The benefit of that is that you could later change it to 12, and it would upgrade existing hashes that were already on bcrypt but only with a cost of 11.
Try this:
$passwordFromDatabase = "A1D292F556AA661B720847487960860F17086A0BD11A4320368E9447FF7139DE089AA88B6159420814F10194F1AA55A3379FB80EA26BA6397BA75CEC811B241A"; // sha512 hash of "somepassword"
$passwordFromForm = $_POST['password']; // $_POST['password'] == "somepassword"
if(password_needs_rehash($passwordFromDatabase, PASSWORD_BCRYPT, ["cost" => 12]) && hash("sha512", $passwordFromForm) === $passwordFromDatabase){
// generate new password hash
$newPasswordHash = password_hash($passwordFromForm, PASSWORD_BCRYPT, ["cost" => 12]);
// update hash from database - replace old hash $passwordFromDatabase with new hash $newPasswordHash
// after update login user
if(password_verify($passwordFromForm, $newPasswordHash)){
// user has logged in successful and hash was updated
// redirect to user area
}else{
// ups something went wrong Exception
}
}else{
if(password_verify($passwordFromForm, $passwordFromDatabase)){
// user password hash from database is already BCRYPTed no need to rehash
// user has logged in successfully
// redirect to user area
}else{
// wrong password
// no access granted - stay where you are
}
}
Ps. If you think about setting your own salt... please don't do that. You won't do it better than a native password_hash(...) php function. Just set the cost which provides balance between check speed and security against brute forcing. If you leave options blank, the cost will by default get set to 10.

PHP md5 and sha1 confusion - Why am I getting different encryption results?

I have a php function in a php page called encrypt_password that I use when processing a registration form:
function encrypt_password($password){
$salt = sha1(md5($password));
$password = md5($password.$salt);
return $password;
}
I try to use it again for when I process the login form but I get a different result.
I get the correct result just by not calling this function and instead just calling:
$salt = sha1(md5($password));
$password = md5($password.$salt);
directly on my process_login page. Why would I get a different result by calling encrypt_password?
I hope I have explained this clearly enough!
Thanks!
I simply cannot believe this to be true. You say you have two pages, one with a registration form and one with a login form.
They both have to encrypt the password the user has posted.
There can be a number of things wrong here, depending on how you find they don't match. Do you just try to login and see an error that your password is wrong? Or did you echo the password hash after a call to encrypt_password? It would be nice to have done that to shown us a hash of the password 'test', from both the registration page and the login page. Perhaps someone could've seen a pattern.
Anyway, let me guess:
You enter the password incorrectly.
You have created this user you're testing it with, with an older version of your encryption function. Perhaps you only used md5(password) to register, then you read somewhere that was unsafe and added a salt. Now you're comparing two different hashes for the same password, since the password is stored in the database using the old hashing function.
You set $password with $password = $_POST['password']; I guess. On both pages, I guess too. Are those statements on both pages typo-free? No $password = $_POST['pasword']; there? And are both <input> elements named "password"?
Typos also go for the $encrypt_password function. Do you define it on both pages, or do you include it from another file? (You should!) If they exist in both files, do they match letter by letter? Copypaste it to test this, and if it works, thank me and put it in an include afterwards, and let it be a lesson.
i faced the same problem .
check the length of password field in db the value after hashed is increased the limit you specified in the db
Yep, I checked the code and theres is no error. This is my code without any flaws:
function encrypt_password($password){
$salt = sha1(md5($password));
$password = md5($password.$salt);
return $password;
}
$myPassword = "test";
echo encrypt_password($myPassword );
// this gives me 34364c859afb02e70306c905374ac2d5
$salt = sha1(md5($myPassword));
$password = md5($myPassword.$salt);
echo "<br />";
echo $password;
//this gives me 34364c859afb02e70306c905374ac2d5
So, they are the same. Like Dimme, I thought the same about variable names. But I could not replicate this. Sorry...

Sharing login and password for personal project with osCommerce store

I'm integrating an application with the osCommerce shopping cart and want users to be able to log into the app with the same account details they do with osCommerce.
Everything works fine but I got stuck on the user login system. I need to know how to check against a user entered password in my application against the osCommerce user's credentials. They're using a combination of MD5 and salt for generating the password.
How can I use that method to check my user's password?
To check against the password saved in osCommerce, just use the osCommerce function that checks the attempt against the one stored in the database. You'll find this function in the following:
catalog/includes/functions/password_funcs.php
////
// This funstion validates a plain text password with an encrpyted password
function tep_validate_password($plain, $encrypted) {
if (tep_not_null($plain) && tep_not_null($encrypted)) {
// split apart the hash / salt
$stack = explode(':', $encrypted);
if (sizeof($stack) != 2) return false;
if (md5($stack[1] . $plain) == $stack[0]) {
return true;
}
}
return false;
}
So all you need to do is extract the password column from the customers table, based on their entered email address, and compare.
tep_validate_password(password_attempt, password_from_osC)
If you're just going to include it, make sure you also include the catalog/includes/functions/general.php file since that's where the tep_not_null function is defined.

Categories