Насколько безопасна моя система входа в PHP?

Я новичок в PHP, и это тоже мой первый вход в систему, так что было бы здорово, если бы вы, ребята, могли просмотреть мой код и увидеть, можете ли вы обнаружить какие-либо дыры в безопасности:

примечание: я дезинфицирую весь пользовательский ввод, хотя здесь это не показано.

Регистрация:

Шаг 1: Я беру пароль, выбранный пользователем, и запускаю его с помощью этой функции:

encrypt($user_chosen_password, $salt);

function encrypt($plain_text, $salt) {
    if(!$salt) {
        $salt = uniqid(rand(0, 1000000));
    }
    return array(
        'hash' => $salt.hash('sha512', $salt.$plain_text),
        'salt' => $salt
    );
}

Шаг 2: Затем я сохраняю хэш и соль ( $ password ['hash'] и $ password ['salt'] ) в таблице пользователей в базе данных:

id | username | password  | salt       | unrelated info...
-----------------------------------------------------------
1  | bobby    | 809a28377 | 809a28377f | ...
                fd131e5934
                180dc24e15
                bbe5f8be77
                371623ce36
                4d5b851e46

Войти:

Шаг 1: Я беру имя пользователя, введенное пользователем, и поиск в базе данных, чтобы увидеть, возвращаются ли какие-либо строки. На моем сайте нет двух пользователей, которые могут делиться одним и тем же имя пользователя, чтобы поле имени пользователя всегда имело уникальное значение. Если я получаю 1 строку, я хватаю соль для этого пользователя.

Шаг 2: Затем я запускаю пароль, введенный пользователем, с помощью функции шифрования (как ранее сообщалось выше), но на этот раз я также предоставляю соль, полученную из базы данных:

encrypt($user_entered_password, $salt);

Шаг 3: Я сейчас иметь правильный пароль для сопоставления в этой переменной: $ password ['hash'] . Итак, я провожу второй поиск в базе данных, чтобы увидеть, введенное имя пользователя и хешированный пароль вместе возвращают одну строку. Если да, то учетные данные пользователя верны.

Шаг 4: Для входа пользователя в систему после передачи его учетных данных я генерирую случайную уникальную строку и хеширую ее:

$random_string = uniqid(rand(0, 1000000));
$session_key = hash('sha512', $random_string);

Затем я вставляю $ session_key в Таблица active_sessions в базе данных:

user_id | key
------------------------------------------------------------
1       | 431b5f80879068b304db1880d8b1fa7805c63dde5d3dd05a5b

Шаг 5:

Я беру незашифрованную уникальную строку, сгенерированную на последнем шаге ( $ random_string ), и устанавливаю ее как значение cookie, которое я call active_session :

setcookie('active_session', $random_string, time()+3600*48, '/');

Шаг 6:

В верхней части моего header.php include есть эта проверка:

if(isset($_COOKIE['active_session']) && !isset($_SESSION['userinfo'])) {
   get_userinfo();
}

get_userinfo () выполняет поиск в таблице users в базе данных и возвращает ассоциативный массив, который хранится в сеансе с именем userinfo :

// сначала эта функция принимает значение cookie active_session и хеширует его, чтобы получить session_key:

hash('sha512', $random_string);

// затем он выполняет поиск в таблице active_sessions , чтобы узнать, существует ли запись по этому ключу ts, в этом случае он получит user_id , связанный с этой записью, и использует его для второго поиска в таблице users , чтобы получить userinfo :

    $_SESSION['userinfo'] = array(
        'user_id'           => $row->user_id,
        'username'          => $row->username,
        'dob'               => $row->dob,
        'country'           => $row->country,
        'city'              => $row->city,
        'zip'               => $row->zip,
        'email'             => $row->email,
        'avatar'            => $row->avatar,
        'account_status'    => $row->account_status,
        'timestamp'         => $row->timestamp,
    ); 

] Если существует сеанс userinfo , я знаю, что пользователь аутентифицирован. Если он не существует, но файл cookie active_session существует, тогда эта проверка в верхней части файла header.php создаст этот сеанс.

Причина, по которой я использую cookie, а не только сеансы, заключается в том, чтобы сохранить логин.Поэтому, если пользователь закрывает браузер, сеанс может быть пропущен, но cookie все еще будет существовать. И поскольку эта проверка находится в верхней части header.php , сеанс будет воссоздан, и пользователь сможет работать как зарегистрированный в пользователе как обычно.

Выход:

Шаг 1: Сеанс userinfo и файл cookie active_session не установлены.

Шаг 2: Связанная запись из таблицы active_sessions в базе данных удаляется.


Примечания: Единственная проблема, которую я вижу (и, возможно, есть много других), это то, что пользователь подделывает файл cookie active_session , создавая его сам в своем браузере. Конечно, они должны установить в качестве значения этого файла cookie строку, которая после шифрования должна соответствовать записи в таблице active_sessions , откуда я извлечу user_id для создания этого сеанса. Я не уверен, каковы реальные шансы того, что пользователь (возможно, использующий автоматизированную программу) правильно угадывает строку, которую он не знает, затем будет зашифрован sha512 и сопоставлен со строкой в ​​ active_sessions в базе данных, чтобы получить идентификатор пользователя для создания этого сеанса.

Извините за объемное эссе, но поскольку это очень важная часть моего сайта, и из-за моей неопытности я просто хотел запустить ее более опытными разработчиками, чтобы убедиться, что это действительно безопасно.

Итак, видите ли вы какие-либо бреши в безопасности на этом маршруте и как их можно улучшить?

40
задан TK123 31 December 2011 в 23:33
поделиться