Примечание: Взято из моего предыдущего ответа .
Терминология
- Пользователь: Посетитель.
- Клиент: Определенное веб-совместимое программное обеспечение, установленное на конкретном компьютере.
Понимание сеансов
Для пониманияКак сделать сеанс безопасным, вы должны сначала понять, как сеансы работают.
Давайте посмотрим на этот фрагмент кода:
session_start();
Как только вы это сделаете, PHP будет искать cookieназывается PHPSESSID
(по умолчанию).Если он не найден, он создаст его:
PHPSESSID=h8p6eoh3djplmnum2f696e4vq3
Если он найден, он принимает значение PHPSESSID
и затем загружает соответствующий сеанс.Это значение называется session_id
.
Это единственное, что клиент узнает.Все, что вы добавляете в переменную сеанса, остается на сервере и никогда не передается клиенту.Эта переменная не изменится, если вы измените содержимое $_SESSION
.Он всегда остается неизменным, пока вы не уничтожите его или не истечет время ожидания.Следовательно, бесполезно пытаться запутать содержимое $_SESSION
, хэшируя его или другими способами, поскольку клиент никогда не получает и не отправляет эту информацию.
Затем, в случае нового сеанса, вы будетеустановите переменные:
$_SESSION['user'] = 'someuser';
Клиент никогда не увидит эту информацию.
Проблема
Может возникнуть проблема безопасности, когда злоумышленник крадет session_id
другого пользователя.Без какой-либо проверки он сможет выдать себя за этого пользователя.Нам нужно найти способ уникальной идентификации клиента (а не пользователя).
Одна стратегия (наиболее эффективная) включает проверку того, совпадает ли IP-адрес клиента, начавшего сеанс, с IP-адресом клиента.человек, использующий сеанс.
if(logging_in()) {
$_SESSION['user'] = 'someuser';
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
}
// The Check on subsequent load
if($_SESSION['ip'] != $_SERVER['REMOTE_ADDR']) {
die('Session MAY have been hijacked');
}
Проблема этой стратегии заключается в том, что если клиент использует балансировщик нагрузки или (при длительном сеансе) пользователь имеет динамический IP, он вызовет ложное предупреждение.
Другая стратегия включает проверку пользовательского агента клиента:
if(logging_in()) {
$_SESSION['user'] = 'someuser';
$_SESSION['agent'] = $_SERVER['HTTP_USER_AGENT'];
}
// The Check on subsequent load
if($_SESSION['agent'] != $_SERVER['HTTP_USER_AGENT']) {
die('Session MAY have been hijacked');
}
Недостатком этой стратегии является то, что если клиент обновляет свой браузер или устанавливает надстройку (некоторые добавляют кuser-agent), строка user-agent изменится и вызовет ложное предупреждение.
Другая стратегия заключается в повороте session_id
на каждые 5 запросов.Таким образом, теоретически session_id
не остается достаточно долго для захвата.
if(logging_in()) {
$_SESSION['user'] = 'someuser';
$_SESSION['count'] = 5;
}
// The Check on subsequent load
if(($_SESSION['count'] -= 1) == 0) {
session_regenerate_id();
$_SESSION['count'] = 5;
}
Вы можете комбинировать каждую из этих стратегий по своему желанию, но вы также комбинируете недостатки.
К сожалению, ни одно решение не является надежным.Если ваш session_id
скомпрометирован, вы в значительной степени готовы.Вышеприведенные стратегии являются всего лишь мерой отсрочки.