Welcome Guest, Not a member yet? Register   Sign In
password hashing doesn't work for all special characters
#1

(This post was last modified: 08-04-2020, 06:01 AM by BilltheCat.)

I'm trying to hash passwords using the CodeIgniter 3 library "Community Auth", and I think I've found that only certain special characters will work. The passwords are saved to the DB, but it doesn't work to login. 
  • Here's an example password that works: KA83**8!d#
  • Here's an example password that does NOT work: 1aA!@#%^&*()-_=+{};:,<.>
If I pull the below methods out to a single function that does hash_passwd and password_verify, then a comparison do work for both passwords. 

Here are the two methods that I use to change a password, and then the third to check for login.

Model = application\models\User_model.php
Method = change_password
Code:
$this->db->where('user_id', $user_data->user_id)
                        ->update(
                                $this->db_table('user_table'), [
                            'passwd' => $this->authentication->hash_passwd($password),
                            'passwd_recovery_code' => NULL,
                            'passwd_recovery_date' => NULL
                                ]
                );

Model = application\third_party\community_auth\libraries\Authentication.php
Method = hash_passwd
Code:
public function hash_passwd($password) {
        return password_hash($password, PASSWORD_BCRYPT, ['cost' => 11]);
    }

Model = application\third_party\community_auth\libraries\Authentication.php
Method = check_passwd
Code:
public function check_passwd($hash, $password) {
        if (password_verify($password, $hash)) {
            return TRUE;
        }
        return FALSE;
    }
Reply
#2

(This post was last modified: 08-04-2020, 10:35 AM by jreklund.)

Have you enabled the global xss_clean? In case that manipulate your data.

(Should be disabled)
Reply
#3

No, it's disabled (NULL)
Reply
#4

It should be FALSE, but don't think it will be activated with NULL.

How is it stored in your database?
Does it look the same when you stored it to when you get it from the DB? (you need to start dumping it and debug it)
Reply
#5

Ok, thanks that's a good direction to go.  I checked the debug log and I do see that the listed hash matches the database record.  So now I'm left with figuring out why the password_verify method isn't matching it correctly.  Here's the log, and you can see the match fails:


Code:
DEBUG - 2020-08-04 19:22:45 -->
string    = admin
password  = 1aA!@#%^&*()-_=+{};:,<.>
DEBUG - 2020-08-04 19:22:46 -->
user is banned            = no
password in database      = $2y$11$2k7Pqno0oosBz.B2VcI.MuQp7GqQcKnmNeazhawa/ROlz6bemh6y6
supplied password match    = False
required level or role    = 1
auth level in database    = 9
auth level equivalant role = admin
Reply
#6

Can you add a debug log function to save what the generated hash is before storing it in the database. So that you can match it against the one being stored.
Reply
#7

I added it to my user model, and it matches on the save too:

PHP Code:
protected function _change_password($password$password2$user_id$recovery_code) {
        // User ID check
        if (isset($user_id) && $user_id !== FALSE) {
            $query $this->db->select('user_id')
                    ->from($this->db_table('user_table'))
                    ->where('user_id'$user_id)
                    ->where('passwd_recovery_code'$recovery_code)
                    ->get();

            // If above query indicates a match, change the password
            if ($query->num_rows() == 1) {
                $user_data $query->row();
                
                $data 
= array(
                    'passwd' => $this->authentication->hash_passwd($password),
                            'passwd_recovery_code' => NULL,
                            'passwd_recovery_date' => NULL
                
);
                $this->db->where('user_id'$user_data->user_id)
                        ->update($this->db_table('user_table'), $data);
                log_message('debug'"\n password stored in DB       = " $data['passwd']);
            

Code:
DEBUG - 2020-08-04 20:26:36 -->
password stored in DB       = $2y$11$5Uupqt4RFN8E.RNjaBdlu./SlFpX7HgkvOSDM0pcflqzFhWF3anKa

DEBUG - 2020-08-04 20:26:42 -->
string     = admin
password   = 1aA'/[!@#$%^&*()\-_=+{};:,<.>§~]/'

DEBUG - 2020-08-04 20:26:42 -->
user is banned             = no
password in database       = $2y$11$5Uupqt4RFN8E.RNjaBdlu./SlFpX7HgkvOSDM0pcflqzFhWF3anKa
supplied password match    = False
required level or role     = 1
auth level in database     = 9
auth level equivalant role = admin
Reply
#8

Okay... Can you add another log_message after "password stored in" that uses the built in password_verify and log a var_dump of that, too see if it validates before storing it in the database.
Reply
#9

OK, updated the change_password method with the new log line:

PHP Code:
protected function _change_password($password$password2$user_id$recovery_code) {
        // User ID check
        if (isset($user_id) && $user_id !== FALSE) {
            $query $this->db->select('user_id')
                    ->from($this->db_table('user_table'))
                    ->where('user_id'$user_id)
                    ->where('passwd_recovery_code'$recovery_code)
                    ->get();

            // If above query indicates a match, change the password
            if ($query->num_rows() == 1) {
                $user_data $query->row();
                
                $data 
= array(
                    'passwd' => $this->authentication->hash_passwd($password),
                            'passwd_recovery_code' => NULL,
                            'passwd_recovery_date' => NULL
                
);
                $this->db->where('user_id'$user_data->user_id)
                        ->update($this->db_table('user_table'), $data);
                log_message('debug'"\n password stored in DB       = " $data['passwd']);
                log_message('debug'"\n Password Validation       = " . (password_verify($password$data['passwd']) ? "Passed" "Failed"));
                    
            
}
        }
    

Logs show it passed:
Code:
DEBUG - 2020-08-04 20:47:33 -->
password stored in DB       = $2y$11$86rH8RbY.5BHpjq6AKZvE.SBwJoe1AwxE99M1iSPJeDzEaBufDy2S
DEBUG - 2020-08-04 20:47:33 -->
Password Validation       = Passed

DEBUG - 2020-08-04 20:47:38 -->
string     = admin
password   = 1aA'/[!@#$%^&*()\-_=+{};:,<.>§~]/'

DEBUG - 2020-08-04 20:47:39 -->
user is banned             = no
password in database       = $2y$11$86rH8RbY.5BHpjq6AKZvE.SBwJoe1AwxE99M1iSPJeDzEaBufDy2S
supplied password match    = False
required level or role     = 1
auth level in database     = 9
auth level equivalant role = admin
Reply
#10

Okay, did you change password btw? Because it dosen't match the first one in the thread anymore.

I would then look at what password password_verify get when you try to login. So that it dosen't change it.
Have you checked that it's the same before saving it as well? So that it dosen't manipulate it in any way?
Reply




Theme © iAndrew 2016 - Forum software by © MyBB