Хорошо, есть две отдельные, но связанные проблемы, и каждая из них обрабатывается по-разному.
Фиксация сеанса
Здесь злоумышленник явно устанавливает идентификатор сеанса сеанса для пользователя.Как правило, в PHP это делается с помощью URL-адреса типа http://www.example.com/index...?session_name=sessionid
.После того, как злоумышленник передаст URL-адрес клиенту, атака аналогична атаке захвата сеанса.
Существует несколько способов предотвратить фиксацию сеанса (сделать все из них):
Установите session.use_trans_sid = 0
в вашем файле php.ini
.Это скажет PHP не включать идентификатор в URL и не читать URL для идентификаторов.
Установить session.use_only_cookies = 1
в вашем файле php.ini
,Это скажет PHP никогда не использовать URL с идентификаторами сеанса.
Регенерация идентификатора сеанса каждый раз, когда изменяется статус сеанса.Это означает любое из следующего:
- Аутентификация пользователя
- Хранение конфиденциальной информации в сеансе
- Изменение чего-либо в сеансе
- и т. Д..
Перехват сеанса
Здесь злоумышленник получает идентификатор сеанса и может отправлять запросы, как если бы они были этим пользователем.Это означает, что, поскольку злоумышленник имеет идентификатор, он практически неотличим от действительного пользователя по отношению к серверу.
Вы не можете напрямую предотвратить перехват сеанса.Однако вы можете сделать шаги, чтобы сделать его очень трудным и трудным в использовании.
Используйте сильный идентификатор хеша сеанса: session.hash_function
в php.ini
.Если PHP <5.3, установите его <code>session.hash_function = 1 для SHA1.Если PHP> = 5.3, задайте для него session.hash_function = sha256
или session.hash_function = sha512
.
Отправьте сильный хэш: session.hash_bits_per_character
in php.ini
.Установите для этого session.hash_bits_per_character = 5
.Хотя это не делает взломать труднее , это имеет значение, когда атакующий пытается угадать идентификатор сеанса.Идентификатор будет короче, но будет содержать больше символов.
Установите дополнительную энтропию с помощью session.entropy_file
и session.entropy_length
в вашем php.ini
файл.Установите для первого значение session.entropy_file = /dev/urandom
, а для второго - количество байтов, которые будут считаны из файла энтропии, например session.entropy_length = 256
.
Измените имя сеанса с PHPSESSID по умолчанию.Это достигается путем вызова session_name()
с вашим собственным идентификатором в качестве первого параметра перед вызовом session_start
.
Если вы действительно параноик, вы также можете повернуть имя сеанса, но имейте в виду, что все сеансы будут автоматически признаны недействительными, если вы измените это (например, есливы делаете это в зависимости от времени).Но в зависимости от вашего варианта использования, это может быть вариант ...
Часто меняйте идентификатор сеанса.Я не буду делать это каждый запрос (если вам действительно не нужен такой уровень безопасности), но с произвольным интервалом.Вы хотите часто менять это, поскольку, если злоумышленник захватывает сеанс, вы не хотите, чтобы он мог использовать его слишком долго.
Включите пользовательский агент из$_SERVER['HTTP_USER_AGENT']
в сессии.Обычно, когда начинается сеанс, сохраняйте его как $_SESSION['user_agent']
.Затем при каждом последующем запросе проверяйте, соответствует ли он.Обратите внимание, что это может быть подделано, так что это не на 100% надежно, но лучше, чем нет.
Включите IP-адрес пользователя из $_SERVER['REMOTE_ADDR']
в сеанс.Как правило, когда начинается сеанс, сохраните его как $_SESSION['remote_ip']
.Это может быть проблематично для некоторых интернет-провайдеров, которые используют несколько IP-адресов для своих пользователей (например, AOL раньше).Но если вы используете его, это будет гораздо безопаснее.Для злоумышленника единственный способ подделать IP-адрес - это скомпрометировать сеть в какой-то момент между реальным пользователем и вами.И если они скомпрометируют сеть, они могут сделать намного хуже, чем угон (например, атаки MITM и т. Д.).
Включите токен в сеанс и на стороне браузера, который вы увеличиваете и часто сравниваете.Как правило, для каждого запроса выполняйте $_SESSION['counter']++
на стороне сервера.Также сделайте что-нибудь в JS на стороне браузера, чтобы сделать то же самое (используя локальное хранилище).Затем, когда вы отправляете запрос, просто возьмите одноразовый номер токена и убедитесь, что на сервере совпадает одноразовый номер.Сделав это, вы сможете обнаружить захваченный сеанс, поскольку у злоумышленника не будет точного счетчика, или, если он это сделает, у вас будет 2 системы, передающие одинаковое количество, и они могут сказать, что одна из них подделана.Это не будет работать для всех приложений, но является одним из способов борьбы с этой проблемой.
Примечание по двум
Разница между фиксацией сеанса и перехватом толькоо том, как идентификатор сеанса скомпрометирован.В фиксации для идентификатора устанавливается значение, которое злоумышленник знает заранее.В угоне это либо угадано, либо украдено у пользователя.В противном случае эффекты обоих одинаковы после того, как идентификатор скомпрометирован.
Регенерация идентификатора сеанса
Всякий раз, когда вы генерируете идентификатор сеанса с использованием session_regenerate_id
старый сеанс долженбыть удаленным.Это происходит прозрачно с основным обработчиком сеанса.Однако некоторые пользовательские обработчики сеансов , использующие session_set_save_handler()
, этого не делают и открыты для атаки на старые идентификаторы сеансов.Убедитесь, что, если вы используете пользовательский обработчик сеанса, вы отслеживаете открываемый идентификатор и, если он не тот, который вы сохраняете, вы явно удаляете (или изменяете) идентификатор старого.
Используя обработчик сеанса по умолчанию, вы можете просто вызвать session_regenerate_id(true)
.Это удалит старую информацию о сеансе для вас.Старый идентификатор больше не действителен и приведет к созданию нового сеанса, если злоумышленник (или кто-либо еще в этом отношении) попытается его использовать.Будьте осторожны с пользовательскими обработчиками сеансов, хотя ....
Уничтожение сеанса
Если вы собираетесь уничтожить сеанс (например, при выходе из системы), обязательно полностью его уничтожите.Это включает в себя удаление куки.Использование session_destroy
:
function destroySession() {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
session_destroy();
}