Хорошо, есть две отдельные, но связанные проблемы, и каждая решается по-своему.
Фиксация сеанса
Здесь злоумышленник явно устанавливает идентификатор сеанса для пользователя. Обычно в 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-адреса с идентификаторами сеанса.
Повторно генерируйте идентификатор сеанса в любое время при изменении статуса сеанса. Это означает любое из следующего:
- User authentication
- Хранение конфиденциальной информации в сеансе
- Изменение чего-либо в сеансе
- и т.д...
Взлом сеанса
Здесь злоумышленник получает идентификатор сеанса и может отправлять запросы, как если бы он был этим пользователем. Это означает, что, поскольку злоумышленник имеет идентификатор, они практически неотличимы от действительного пользователя по отношению к серверу.
Вы не можете напрямую предотвратить захват сеанса. Однако вы можете предпринять шаги, чтобы сделать его очень трудным и трудным в использовании.
Используйте надежный хэш-идентификатор сеанса: session.hash_function
в php.ini
. Если PHP ‹5.3, установите session.hash_function = 1
для SHA1. Если PHP> = 5.3, установите session.hash_function = sha256
или session.hash_function = sha512
.
Отправьте надежный хеш: session.hash_bits_per_character
в 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 на стороне браузера, чтобы сделать то же самое (используя локальное хранилище). Затем, когда вы отправляете запрос, просто возьмите одноразовый номер токена и убедитесь, что одноразовый номер такой же на сервере. Сделав это, вы сможете обнаружить захваченный сеанс, поскольку у злоумышленника не будет точного счетчика, или, если они есть, у вас будет две системы, передающие один и тот же счетчик, и могут сказать, что одна из них подделана. Это работает не для всех приложений, но является одним из способов решения проблемы.
Примечание о двух
Разница между фиксацией сеанса и захватом заключается только в том, как скомпрометирован идентификатор сеанса. При фиксации идентификатору присваивается значение, которое злоумышленник знает заранее. В Hijacking он либо угадан, либо украден у пользователя. В противном случае, как только идентификатор будет скомпрометирован, эффекты обоих будут одинаковыми.
Восстановление идентификатора сеанса
Каждый раз при повторном создании идентификатора сеанса с помощью session_regenerate_id
старый сеанс следует удалить. Это происходит прозрачно с основным обработчиком сеанса. Однако некоторые пользовательские обработчики сеансов, использующие session_set_save_handler()
, не делают этого и открыты. атаковать старые идентификаторы сессий. Убедитесь, что если вы используете настраиваемый обработчик сеанса, вы отслеживаете идентификатор, который вы открываете, а если он не тот, который вы сохраняете, вы явно удаляете (или меняете) идентификатор на старом.
Используя обработчик сеанса по умолчанию, вы можете просто вызвать session_regenerate_id(true)
. Это удалит старую информацию о сеансе. Старый идентификатор больше недействителен и приведет к созданию нового сеанса, если злоумышленник (или кто-либо другой в этом отношении) попытается его использовать. Однако будьте осторожны с пользовательскими обработчиками сеансов ....
Уничтожение сеанса
Если вы собираетесь уничтожить сеанс (например, при выходе из системы), убедитесь, что вы уничтожили его полностью. Это включает в себя отключение файла cookie. Используя session_destroy
:
function destroySession() {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
session_destroy();
}
person
ircmaxell
schedule
22.02.2011