sql >> Base de Datos >  >> RDS >> Mysql

¿Cómo hacer que mi función de restablecimiento de contraseña de codeiginter sea segura?

He leído su código y creo que incluso si agrego un límite de tiempo para usar un nuevo token, todavía no es seguro. De acuerdo con owasp cheatsheat en la recuperación de contraseña , Puedes hacerlo mejor que eso. Te lo acorto un poco. Nombran cinco puntos.

  1. Utilice algunos datos que recopiló en el proceso de registro de usuario:puede ser la fecha de nacimiento, el número de teléfono móvil, el apellido, etc.
  2. Utilice preguntas de seguridad y coloque las entradas de respuesta como texto puro, no haga menús desplegables ni nada por el estilo. Limite aquí el número de conjeturas. Sea no trivial e inventivo al construir esas preguntas.
  3. Después del paso dos, se recomienda bloquear la cuenta de usuario inmediatamente. Genere un token de contraseña de tiempo limitado y envíelo (al menos inténtelo) a través de un canal de comunicación diferente, tal vez con sms o un correo electrónico secundario.
  4. Vigile la sesión y permita restablecer la contraseña solo durante la sesión actual. Haga cumplir la complejidad de la contraseña en este paso (puede usar algún complemento de jquery para eso).
  5. Intente registrar las acciones del usuario, la dirección IP y los datos del navegador. Concéntrese en los intentos fallidos o en el uso de tokens caducados. De esta manera, puede monitorear comportamientos maliciosos y sacar algunas conclusiones.

Y aquí está mi pequeña mejora. Uso la columna updated_at, que puede ser útil en muchas otras situaciones o puede especificar su propia columna solo para limitar el tiempo de restablecimiento de la contraseña.

<?php

public function recover(){
    $data['main_content'] = 'auth/recover';
    $this->load->view('public/layouts/home_main', $data);
}

public function recover_account(){
    $this->form_validation->set_rules('username','Username','trim|xss_clean|required');
    if ($this->form_validation->run() == FALSE){
        //Show View
        $data = array(
            'errors' => validation_errors()
        );
        $this->session->set_flashdata($data);
        $data['main_content'] = 'auth/recover';
        $this->load->view('public/layouts/home_main', $data);
    }
    else{
        $account = $this->input->post('username');
        if($this->User_model->user_exist($account)){
            $options = [
                'cost' => 8,
                'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM),
            ];
            $temp_pass = password_hash(rand(23456,975655), PASSWORD_BCRYPT, $options);
            $reset_code = rand(23456,975655);
            $data = array(
                'reset_link_code' => $reset_code
            );
            $this->session->set_userdata($data);

            $this->email->from('[email protected]', 'Your Name');
            $this->email->to('[email protected]');
            $this->email->subject($reset_code);
            $this->email->message(
                'Testing the email class.'.' pass: <a href="'.base_url().'auth/reset_password?user='.urlencode($account).'&code='.urlencode($temp_pass).'&rstc='.urlencode($reset_code).'">Click Here</a>'
            );
            $db_pass = array(
                'password' => $temp_pass,
                'updated_at' => time() //or even date("Y-m-d H:i:s")
            );
            $this->db->where('email', $account);
            $this->db->or_where('username', $account);
            $this->db->update('users', $db_pass);

            if($this->email->send()){
                echo 'Passowrd resend link sent to email';
            }else{
                echo 'email count not check, pls talk to support';
            }
        }else{
            echo "User not Fount";
        }
    }
}
function reset_password(){
    $email = urldecode($this->input->get('user', true));
    $temp_pass = urldecode($this->input->get('code', true));
    $reset_code = urldecode($this->input->get('rstc', true));

    if($email && $temp_pass && $reset_code){

        $this->form_validation->set_rules('user','Username','trim|xss_clean|min_length[4]');
        $this->form_validation->set_rules('newpass','Password','trim|xss_clean|required|min_length[4]|max_length[50]');
        $this->form_validation->set_rules('newpass2','Confirm Password','trim|xss_clean|required|matches[newpass]');

        if($reset_code == $this->session->userdata('reset_link_code')){
            //get user data by email
            //$user = $this->User_model->get_heshed_password($email);
            $user = $this->User_model->get_heshed_password_and_updated_value($email);

            //calculate time difference
            $dbdate = strtotime($user->updated_at);
            if (time() - $dbdate > 15 * 60) {
                // 15 mins has passed
                $time_allowed = false;
            } else {
                $time_allowed = true;
            }

            if($temp_pass == $user->password && $time_allowed){
                if ($this->form_validation->run() == FALSE){
                    //Show View
                    $data = array(
                        'errors' => validation_errors()
                    );
                    $this->session->set_flashdata($data);
                    $data['main_content'] = 'auth/reset_password';
                    $this->load->view('public/layouts/home_main', $data);
                }
                else{
                    $options = [
                        'cost' => 8,
                        'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM),
                    ];
                    $password = $this->input->post('newpass');
                    $passtodb = password_hash($password, PASSWORD_BCRYPT, $options);
                    $data = array(
                        'password' => $passtodb
                    );
                    $this->db->where('email', $email);
                    $this->db->or_where('username', $email);
                    $this->db->update('users', $data);
                    redirect('account');
                }

            }
        }else{
            echo 'invalid reset code';
        }

    }else{
        redirect('/');
    }
}