Я новичок в 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
в базе данных, чтобы получить идентификатор пользователя для создания этого сеанса.
Извините за объемное эссе, но поскольку это очень важная часть моего сайта, и из-за моей неопытности я просто хотел запустить ее более опытными разработчиками, чтобы убедиться, что это действительно безопасно.
Итак, видите ли вы какие-либо бреши в безопасности на этом маршруте и как их можно улучшить?