При фиксации сессии злоумышленник пытается навязать серверу ее идентификационный номер (ID), не позволяя ему самостоятельно присвоить этот номер. Это происходит в том случае, если пользователь злоупотребляет возможностью передачи ID сессии в области GET-запроса URL-адреса:
http://yourserver.com/authenticate.php?PHPSESSID=123456789
В данном случае серверу будет передан вымышленный ID сессии 123456789. А теперь рассмотрим пример, код которого восприимчив к фиксации сессии. Для того чтобы увидеть его в действии, наберите текст примера и сохраните его в файле sessiontest.php.
Пример. Сессия, восприимчивая к фиксации сессии
<?php // sessiontest.php
session_start();
if (!isset($_SESSION['count'])) $_SESSION['count'] = 0;
else ++$_SESSION['count'];
echo $_SESSION['count'];
?>
После того как код будет сохранен, вызовите программу в вашем браузере, используя следующий URL (предваряя его правильным путевым именем, например http://localhost/web/):
sessiontest.php?PHPSESSID=1234
Через некоторое время, щелкнув на кнопке обновления страницы, вы увидите увеличение значения счетчика. Теперь попробуйте ввести в браузер следующий URL-адрес:
sessiontest.php? PHPSESSID=5678
Щелкните несколько раз на кнопке обновления страницы — и увидите, что счет опять начался с нуля. Оставьте показания счетчика на номере, отличающемся от его показаний при использовании первого URL-адреса, вернитесь на первый URL-адрес и посмотрите на то, как показания счетчика вернулись к первоначальному значению. Вы по собственному усмотрению создали две разные сессии и без особого труда можете создать их в любом количестве.
Особая опасность такого подхода состоит в том, что затеявший атаку злоумышленник может попытаться распространить такие URL-адреса среди ничего не подозревающих пользователей, и если кто-нибудь из них перейдет по ссылкам с этими адресами, атакующий сможет вернуться и перехватить любую сессию, которая не была удалена или срок действия которой еще не истек!
Для предотвращения фиксации сессии нужно добавить еще одну простую проверку на изменение ID сессии, воспользовавшись для этого функцией session_regenerate_id
. Эта функция сохраняет значения всех переменных текущей сессии, но заменяет ID сессии новым, о котором не может знать атакующий. Для предотвращения фиксации можно проверить факт существования специальной переменной сессии. Если ее не существует, вы будете знать, что создана новая сессия, поэтому вы просто меняете ID сессии и устанавливаете значение ее специальной переменной, позволяющей заметить изменение. Ниже в примере показано, как может выглядеть код, использующий переменную сессии initiated
.
Пример. Регенерация сессии{subtle}
<?php
session_start();
if (!isset($_SESSION['initiated']))
{
session_regenerate_id();
$_SESSION['initiated'] = 1;
}
if (!isset($_SESSION['count'])) $_SESSION['count'] = 0;
else ++$_SESSION['count'];
echo $_SESSION['count'];
?>
Атакующий может вернуться на ваш сайт, используя любые сгенерированные им ID-номера сессии, но ни один из них не приведет к вызову другой пользовательской сессии, поскольку все они будут заменены регенерированными ID-номерами. Если вы склонны к крайним мерам, то можете даже регенерировать ID сессии при каждом запросе.
Предупреждение хищения сессии | Преднамеренная настройка на сессии, использующие исключительно cookie |