Я пытаюсь понять больше о фиксации и угоне сеанса PHP и о том, как предотвратить эти проблемы. Я читал следующие две статьи на сайте Криса Шифлетта:
Однако я не уверен, что правильно все понимаю.
Чтобы предотвратить фиксацию сеанса, достаточно вызвать session_regenerate_id (true); после успешного входа в систему? Я думаю, что понимаю это правильно.
Он также говорит об использовании токенов, передаваемых в URL через $ _GET, для предотвращения перехвата сессии. Как бы это было сделано? Я предполагаю, что когда кто-то входит в систему, вы генерируете свой токен и сохраняете его в переменной сеанса, а затем на каждой странице вы сравниваете эту переменную сеанса со значением переменной $ _GET?
Нужно ли менять этот токен только один раз за сеанс или при каждой загрузке страницы?
Кроме того, является ли это хорошим способом предотвращения угона без передачи значения в URL? это было бы намного проще.
Ответы:
Хорошо, есть две отдельные, но связанные проблемы, и каждая решается по-своему.
Фиксация сессии
Здесь злоумышленник явно устанавливает идентификатор сеанса для пользователя. Обычно в 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 Hijacking
Именно здесь злоумышленник получает идентификатор сеанса и может отправлять запросы, как если бы они были этим пользователем. Это означает, что, поскольку у злоумышленника есть идентификатор, он практически неотличим от действительного пользователя по отношению к серверу.
Вы не можете напрямую предотвратить угон сеанса. Однако вы можете сделать шаги, чтобы сделать его очень сложным и сложным в использовании.
Используйте сильный идентификатор хеша сеанса:
session.hash_function
inphp.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 на стороне браузера, чтобы сделать то же самое (используя локальное хранилище). Затем, когда вы отправляете запрос, просто возьмите одноразовый номер токена и убедитесь, что на сервере совпадает одноразовый номер. Сделав это, вы сможете обнаружить захваченный сеанс, поскольку у злоумышленника не будет точного счетчика, или, если он это сделает, у вас будет 2 системы, передающие одинаковое количество, и они могут сказать, что одна из них подделана. Это не будет работать для всех приложений, но это один из способов борьбы с проблемой.Записка о двух
Разница между фиксацией сеанса и перехватом заключается только в том, как скомпрометирован идентификатор сеанса. В фиксации для идентификатора устанавливается значение, которое злоумышленник знает заранее. В угоне это либо угадано, либо украдено у пользователя. В противном случае эффекты двух одинаковы, когда идентификатор скомпрометирован.
Сессия ID Регенерация
Всякий раз, когда вы восстанавливаете идентификатор сеанса, используя
session_regenerate_id
старый сеанс, его следует удалить. Это происходит прозрачно с основным обработчиком сеанса. Однако некоторые пользовательские обработчики сессийsession_set_save_handler()
не делают этого и открыты для атаки на старые идентификаторы сессий. Убедитесь, что, если вы используете пользовательский обработчик сеанса, что вы отслеживаете открываемый идентификатор, и если он не тот, который вы сохраняете, вы явно удаляете (или меняете) идентификатор старого.Используя обработчик сеанса по умолчанию, вам достаточно просто позвонить
session_regenerate_id(true)
. Это удалит старую информацию о сеансе для вас. Старый идентификатор больше не действителен и приведет к созданию нового сеанса, если злоумышленник (или кто-либо еще в этом отношении) попытается использовать его. Будьте осторожны с пользовательскими обработчиками сессий, хотя ....Уничтожение сессии
Если вы собираетесь уничтожить сеанс (например, при выходе из системы), убедитесь, что вы уничтожили его полностью. Это включает в себя удаление куки. Использование
session_destroy
:источник
session_regenerate_id
не делает недействительным сеанс, который все еще связан со старым идентификатором; только если для параметра delete_old_session задано значение true, сеанс будет уничтожен. Но что, если злоумышленник инициирует регенерацию идентификатора?session.entropy_file = /dev/urandom
. Доказано, что внутренняя генерация энтропии в PHP чрезвычайно слабая, а пул энтропии, предоставляемый / dev / random или / dev / uranom, - лучшее, что вы можете получить на веб-сервере без аппаратного обеспечения.session.cookie_httponly
иsession.cookie_secure
. Первый помогает помешать XSS (но это не идеально). Второй - лучший способ остановить OWASP A9 ...Обе сеансовые атаки имеют одну и ту же цель: получить доступ к законному сеансу другого пользователя. Но векторы атаки разные:
При атаке с фиксацией сеанса злоумышленник уже имеет доступ к действительному сеансу и пытается заставить жертву использовать этот конкретный сеанс.
При атаке перехвата сеанса злоумышленник пытается получить идентификатор сеанса жертвы, чтобы использовать его / ее сеанс.
В обеих атаках идентификатором сеанса являются конфиденциальные данные, на которых сосредоточены эти атаки. Таким образом, идентификатор сессии должен быть защищен как для доступа на чтение (перехват сеанса), так и для доступа на запись (фиксация сеанса).
Общее правило защиты конфиденциальных данных с использованием HTTPS применимо и в этом случае. Кроме того, вы должны сделать следующее:
Чтобы предотвратить атаки фиксации сеанса , убедитесь, что:
true
) и сделайте его для HTTPS только, если это возможно (установите для session.cookie_secure. значениеtrue
); Вы можете сделать оба сsession_set_cookie_params
.Чтобы предотвратить атаки Session Hijacking , убедитесь, что:
true
)Предотвращать обе сеансовые атаки, убедитесь, что:
session_regenerate_id(true)
после попытки аутентификации (true
только в случае успеха) или смены привилегий и уничтожить старый сеанс. (Обязательно сохраните любые изменения$_SESSION
использованияsession_write_close
перед регенерацией идентификатора, если вы хотите сохранить сеанс, связанный со старым идентификатором; в противном случае эти изменения будут затронуты только на сеанс с новым идентификатором.)источник
Токены, которые вы упоминаете, являются "nonce" - число, используемое один раз. Их не обязательно использовать только один раз, но чем дольше они используются, тем выше вероятность того, что одноразовый номер может быть захвачен и использован для захвата сеанса.
Еще одним недостатком одноразовых номеров является то, что очень трудно создать систему, которая использует их и допускает несколько параллельных окон в одной форме. Например, пользователь открывает два окна на форуме и начинает работать над двумя сообщениями:
Если у вас нет возможности отследить несколько окон, у вас будет только один одноразовый номер - окна B / Q. Когда пользователь затем отправляет свое сообщение из окна A и передает в nonce 'P', эта система отклонит сообщение как
P != Q
.источник
Я не читал статью Шифлетта, но думаю, вы что-то не так поняли.
По умолчанию PHP передает маркер сеанса в URL всякий раз, когда клиент не принимает куки. В противном случае в наиболее распространенном случае токен сеанса сохраняется в виде файла cookie.
Это означает, что если вы поместите токен сеанса в URL, PHP распознает его и попытается использовать его впоследствии. Фиксация сеанса происходит, когда кто-то создает сеанс, а затем обманывает другого пользователя для совместного использования того же сеанса, открывая URL-адрес, содержащий маркер сеанса. Если пользователь аутентифицируется каким-либо образом, злоумышленник узнает токен сеанса аутентифицированного, который может иметь разные привилегии.
Как я уверен, объясняет Шифлетт, обычная вещь, которую нужно сделать, - это генерировать новый токен каждый раз, когда меняются привилегии пользователя.
источник
Да, вы можете предотвратить фиксацию сеанса, заново создав идентификатор сеанса при входе в систему. Таким образом, если злоумышленник не узнает значение cookie для нового сеанса, прошедшего проверку подлинности. Другой подход, который полностью останавливает проблему, установлен
session.use_only_cookies=True
в вашей конфигурации времени выполнения. Злоумышленник не может установить значение файла cookie в контексте другого домена. Фиксация сеанса основана на отправке значения cookie в виде GET или POST.источник