Как сделать мою функцию сброса пароля codeiginter безопасной?

#php #mysql #codeigniter

#php #mysql #codeigniter

Вопрос:

Я написал пароль пользователя и код отправки по электронной почте в codeignter.

Я создал контроллер для восстановления пароля. Мой код отправляет временный пароль по электронной почте с полученным URL, и я проверяю этот URL и сохраняю новый пароль в базе данных.

Теперь, как я могу сделать этот код более безопасным и надежным.

мой контроллер:

 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('info@netbeam.in', 'Your Name');
                $this->email->to('vikas@onusworld.com');
                $this->email->subject($reset_code);
                $this->email->message(
                    'Testing the email class.'.' pass: <a href="'.base_url().'auth/reset_password?user='.urlencode($account).'amp;code='.urlencode($temp_pass).'amp;rstc='.urlencode($reset_code).'">Click Here</a>'
                );
                $db_pass = array(
                    'password' => $temp_pass
                );
                $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 amp;amp; $temp_pass amp;amp; $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')){
                $db_pass = $this->User_model->get_heshed_password($email);
                if($temp_pass == $db_pass){
                    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('/');
        }
    } 
  

мои файлы просмотра:

     <?php if(!$this->session->userdata('logged_in')) : ?>
    <section style="background:#ccc;padding-top:20px;">
    <div class="container">
        <div class="col-md-10 col-md-offset-1">
            <div class="coupon-area">
                <div class="container-fluid">
                    <div class="col-md-12">
                        <div class="col-md-9 col-md-offset-1 ac-form-login">
                            <h4 class="modal-title">Recover Password</h4>
                            <hr class="separator">
                            <br>
                            <?php if($this->session->flashdata('errors')) : ?>
                            <div class="alert alert-danger">
                                <?php echo $this->session->flashdata('errors'); ?>
                            </div>
                            <?php endif; ?>
                            <div>
                                <form class="form-horizontal" action="<?php echo base_url(); ?>auth/recover_account" method="post">
                                    <div class="form-group">
                                        <div class="col-sm-8">
                                            <input type="text" name="username" class="form-input-modal" placeholder="Enter your registered email" required>
                                        </div>
                                    </div>
                                    <div class="form-group">
                                        <div class=" col-sm-6">
                                            <button type="submit" class="btn btn-default">Recover Password</button>
                                        </div>
                                    </div>
                                </form>
                            </div>
                            <br>

                            <hr class="separator">
                            <br>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    </section>
    <?php else: ?>
    <?php redirect('account'); ?>
    <?php endif; ?>
  

моя форма сброса пароля:

     <?php if(!$this->session->userdata('loged_i')):?>
    <section style="background:#ccc;padding-top:20px;">
    <div class="container">
        <div class="col-md-10 col-md-offset-1">
            <div class="coupon-area">
                <div class="container-fluid">
                    <div class="col-md-12">
                        <div class="col-md-9 col-md-offset-1 ac-form-login">
                            <h4 class="modal-title">Recover Password</h4>
                            <hr class="separator">
                            <br>
                            <?php if($this->session->flashdata('errors')) : ?>
                            <div class="alert alert-danger">
                                <?php echo $this->session->flashdata('errors'); ?>
                            </div>
                            <?php endif; ?>
                            <div>
                                <form class="form-horizontal" action="<?php echo base_url(); ?>auth/reset_password?user=<?php echo urlencode($this->input->get('user', true)).'amp;code='.urlencode($this->input->get('code', true)).'amp;rstc='.urlencode($this->input->get('rstc', true));?>" method="post">
                                    <div class="form-group">
                                        <div class="col-sm-8">
                                            <input type="text" name="user" class="form-input-modal form-control" value="<?php echo urldecode($this->input->get('user', true));?>" required>
                                        </div>
                                    </div>
                                    <div class="form-group">
                                        <div class="col-sm-8">
                                            <input type="password" name="newpass" class="form-input-modal" placeholder="Set Password" required>
                                        </div>
                                    </div>
                                    <div class="form-group">
                                        <div class="col-sm-8">
                                            <input type="password" name="newpass2" class="form-input-modal" placeholder="Confirm Set Password" required>
                                        </div>
                                    </div>
                                    <div class="form-group">
                                        <div class=" col-sm-6">
                                            <button type="submit" class="btn btn-default">Reset Password</button>
                                        </div>
                                    </div>
                                </form>
                            </div>
                            <br>

                            <hr class="separator">
                            <br>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
   </section>
   <?php else: ?>
   <?php redirect('account'); ?>
   <?php endif; ?>
  

Моя проблема в том, что я хочу сделать этот код более удобным для пользователя и безопасным, чтобы я мог предотвратить внедрение SQL и другие проблемы.

Комментарии:

1. Я надеюсь, вы выполнили шифрование и дешифрование, чтобы сделать пароли безопасными.

2. да. это правильно.

3. Я бы также добавил ограничение по времени для использования сброса пароля.

4. @cssBlaster21895 спасибо за комментарий. можете ли вы внести изменения в код?

Ответ №1:

Я прочитал ваш код и думаю, что даже если я добавлю ограничение по времени для использования нового токена, он все равно не будет безопасным. Согласно owasp cheatsheat по восстановлению пароля, вы можете сделать лучше. Я немного сокращаю его для вас. Они называют пять пунктов.

  1. Используйте некоторые данные, которые вы собрали в процессе регистрации пользователя — это может быть день рождения, номер мобильного телефона, фамилия и т.д.
  2. Используйте контрольные вопросы и вводите ответы в виде чистого текста, не делайте выпадающий список или что-то в этом роде. Ограничьте здесь количество догадок. Будьте нетривиальны и изобретательны в построении этих вопросов.
  3. После второго шага рекомендуется заблокировать учетную запись пользователя imidiatelly. Сгенерируйте токен пароля с ограниченным временем и отправьте его (по крайней мере, попытайтесь) по другому каналу связи, возможно, с помощью sms или на дополнительную электронную почту.
  4. Следите за сеансом и разрешайте сброс пароля только во время текущего сеанса. На этом шаге примените сложность пароля (для этого вы можете использовать какой-нибудь плагин jquery).
  5. Попробуйте записать действия пользователя, IP-адрес, данные браузера. Сосредоточьтесь на неудачных попытках или использовании токенов с истекшим сроком действия. Таким образом, вы можете отслеживать вредоносное поведение и делать некоторые выводы.

И вот мое небольшое обновление. Я использую столбец updated_at, который может быть полезен во многих других ситуациях, или вы можете указать свой собственный столбец только для ограничения времени сброса пароля.

 <?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('info@netbeam.in', 'Your Name');
            $this->email->to('vikas@onusworld.com');
            $this->email->subject($reset_code);
            $this->email->message(
                'Testing the email class.'.' pass: <a href="'.base_url().'auth/reset_password?user='.urlencode($account).'amp;code='.urlencode($temp_pass).'amp;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 amp;amp; $temp_pass amp;amp; $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 amp;amp; $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('/');
    }
}
  

Комментарии:

1. Не унывайте, самая популярная библиотека аутентификации для ci также не такая строгая. Я могу написать этот фрагмент кода, но позже 🙂 На данный момент вы можете взглянуть github.com/benedmunds/CodeIgniter-Ion-Auth/blob/2/libraries /… , вы можете сделать что-то подобное.