Сессии PHP + Useragent с солью

Он продолжает работать в моей голове последние пару дней, но я прочитал несколько статей о том, как сделать ваши сессии PHP более безопасными. Почти все эти статьи говорят, что вам нужно сохранить useragent в сеансе с дополнительной солью. Что-то вроде этого:

$fingerprint = md5('SECRET-SALT'.$_SERVER['HTTP_USER_AGENT']); 

Соль затруднит захват или любой другой сеанс. Но ПОЧЕМУ добавьте соль каждый раз, когда вы проверите ее так:

 md5('SECRET-SALT'.$_SERVER['HTTP_USER_AGENT']) == $_SESSION [ 'fingerprint' ] 

Поэтому ПОЧЕМУ соль сделала бы ее более безопасной, так как злоумышленнику по-прежнему нужен только пользовательский агент (который относительный небольшой набор разных пользовательских атак) и sessionid?

Наверное, что-то маленькое, я спускаюсь, но не могу понять это, сводит меня с ума

Благодаря!

Solutions Collecting From Web of "Сессии PHP + Useragent с солью"

Причина, по которой предлагается добавить соль, проста. Как правило, когда вы создаете этот «отпечаток пальца» – если вы используете только один элемент данных, который имеет ограниченный набор данных, тогда это облегчает для внешнего хакера генерировать это и захватывать сеанс.

В приведенном выше примере да, если у злоумышленника есть как «отпечаток пальца», так и агент «Пользователь», тогда они смогут захватить сеанс.

Добавление соли только усложняет для злоумышленника создание отпечатка пальца, это случай «если у них есть только одна часть информации, тогда последняя часть информации оказывается бесполезной»,

Я бы предположил, что вы добавили еще несколько вещей, например, в vBulletin (проект, который я использовал для работы) хэш-код сеанса (который в основном совпадает с отпечатком пальца) генерируется с помощью следующего кода.

 define('SESSION_IDHASH', md5($_SERVER['HTTP_USER_AGENT'] . $this->fetch_substr_ip($registry->alt_ip))); // this should *never* change during a session 

Кроме того, создается хэш сеанса с использованием

 md5(uniqid(microtime(), true)); 

Они проверяются при попытке идентифицировать сеанс

Таким образом, чтобы захватить сеанс, человеку нужно знать следующее

  • Время (точно) на сервере при создании сеанса
  • Строка агента браузера пользователей
  • IP-адрес пользователя

Они также должны были бы обмануть IP-адрес (или, по крайней мере, первые 2/3 октета), чтобы это сделать.

Если они на самом деле находятся в точке, где им удалось получить вышеуказанную информацию, они, вероятно, могут атаковать другими способами, чем просто захват сеанса.

vBulletin фактически не использует «соль» как таковой, но в вашем примере выше соль просто добавляет ограниченное количество энтропии, всегда лучше всего найти как можно больше энтропии.

Например, во что-то, что я сейчас пишу на python, я генерирую хэш для использования с защитой XSRF. Следующее – это то, что я использую.

  self.key = sha1( self.user.username + self.user.password + settings.SECRET_KEY + strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime()) ).hexdigest() 

Для этого требуется имя пользователя и пароль пользователя, текущее время и заданная соль. Это было бы трудно для злоумышленника генерировать из-за соли и времени (хотя, обратите внимание, что это только защищено тем фактом, что он изменяется после его использования, со временем это не займет много времени для кого-то взломать это для конкретного пользователя, если он не изменился)

Если вы находитесь на своем собственном сервере, шифрование переменных сеанса бессмысленно, потому что они не выходят из сервера. См. Ответ Linead на вопрос Что мне нужно хранить в php-сеансе при входе пользователя в систему? для получения дополнительной информации. Если вы находитесь на общем сервере, вам может потребоваться зашифровать все переменные сеанса, помимо идентификатора сеанса, поскольку они хранятся в файлах temp, доступных для чтения на том же веб-сервере, что и все ваши соседи.

В любом случае, если вы действительно беспокоитесь о безопасности, вам лучше со своим (виртуальным или нет) сервером, поэтому опасность будет возникать только из-за пределов вашего сервера.

Некоторые примеры риска для ваших сеансов:

  • Ваш сервер отправляет идентификатор сеанса в URL-адрес, и ваш пользователь следует за ссылкой на badguys.com. Они получат в переменных сервера референт (полный URL-адрес, включая идентификатор сеанса), браузер и IP-адрес вашего пользователя. Если вы не проверяете IP-адреса, или ваш пользователь использует открытый прокси-сервер, им нужно только установить такую ​​же версию браузера, вставить URL-адрес, и они будут выполнены.
  • Пользователь переходит на общедоступный ПК, регистрируется и уходит, не закрывая сеанс (эй, он ведь человек). Следующий парень в строке открывает браузер, проверяет историю и находит открытый сеанс. Тьфу.

Итак, некоторые меры, которые вы можете предпринять, по моим обычным предпочтениям:

  1. Не отправляйте идентификатор сеанса в URL-адрес; включить session.use_only_cookies в PHP. Минусы: пользователю необходимо включить файлы cookie.
    • О опасных действиях (смените пароль, сделайте заказ …), снова попросите пароль. Вы можете делать это периодически тоже. Минусы: Раздражающе.
    • Тайм-аут быстро. Минусы: в большинстве сайтов это заставит пользователей часто входить в систему, раздражая их.
    • Используйте SSL (только для того, чтобы избежать атаки «человек в середине»). Минусы: Медлен. Глупые сообщения браузера. Нужен SSL на сервере.
    • Проверьте IP. Минусы: Неэффективно для посетителей, использующих общедоступный прокси. Раздражает динамические IP-адреса.
    • Проверьте агент пользователя (браузер). Минусы: почти бесполезно, UA легко получить и тривиально подражать.

(Я считаю, что у вас еще есть PHP, настроенный для максимальной безопасности).

Еще более экстремальные меры:

  • Поддерживайте постоянное соединение между сервером и браузером, например, с помощью апплета Java. Нет связи, нет сеанса. Минусы: пользователю нужны Java, ActiveX или все, что вы используете. Сессия закрывается браузером (это может быть хорошо). Не работает на очень медленных соединениях. Более высокая загрузка на сервере. Вам нужно открыть порты, иметь специальный сервер для апплета.
  • То же самое, но используя асинхронные запросы (например, AJAX), чтобы очень часто обновлять сеанс и очень короткий тайм-аут. Или обновить скрытый IFRAME. Минусы: пользователю нужен JavaScript. Не работает на очень медленных соединениях. Более высокая загрузка на сервере.
  • То же самое, но перезагрузка всей страницы. Минусы: пользователю нужен JavaScript. Автоматическая перезагрузка при чтении страницы очень раздражает.

В некоторых случаях можно забыть о сеансах и вместо этого использовать аутентификацию Apache. Самое простое решение, но множество ограничений.

Если я правильно понимаю, вы хотите предотвратить захват сеанса удаленным злоумышленником, который угадывает идентификаторы сеансов?

Если это не так, то вы серьезно не в своей глубине – злоумышленник, который может отслеживать трафик, также может имитировать пользовательский агент, а злоумышленник, который получает доступ к вашему хранилищу сеансов, все равно имеет ваши шары.

Если вы храните строку пользовательского агента для «блокировки» сеанса текущему пользовательскому агенту, то в хэшировании нет никакой точки – сравнение строк в полной строке пользовательского агента выполняется быстрее (затем хеширование, а затем сравнение), а не значительно больше с точки зрения хранения.

Я не верю, что сохранение пользовательского агента обеспечивает достаточную дифференциацию – лучше было бы генерировать более высокий идентификатор (с большим количеством бит) во время начала сеанса (возможно, sha1 текущая отметка времени + имя пользователя + пользовательский агент + что-то), затем храните его в куки, а также в сеансе и сопоставляйте его с каждым дополнительным запросом. Это не сильно меняет вектор атаки (вам все равно нужно угадать некоторое число), но его легко значительно увеличить количество бит, которое должно быть угадано для успешной атаки там, увеличивая сложность атаки.

Я вижу одну цель – солить отпечаток пальца. Если плохой парень получает ваш сеанс-db (бог знает почему), но не вашего кода, он не мог «догадаться» о вашем методе отпечатка пальца, пытаясь использовать против него обычных агентов-пользователей.

Я также делаю это, чтобы частично защитить от атак сеанса . Вам также необходимо указать IP-адрес.

Имейте в виду, что когда клиентский браузер автоматически обновляет агент пользователя, и вы подумаете, что его сессия была захвачена;)

Поскольку отпечаток пальца хранится на стороне сервера, вам не нужно использовать соленый хеш. «Нормального» хэша достаточно, чтобы уменьшить данные.

Имейте в виду, что если вы это сделаете, вы заставляете людей заходить снова, если они обновляют свой браузер. Это может быть хорошо, но просто убедитесь, что это ваше намерение.

Использование удаленного адреса пользователя также не без проблем. Многие люди используют один и тот же компьютер из разных мест. Мобильные устройства, ноутбуки используются дома и на работе, ноутбуки используются в горячих точках Wi-Fi и так далее. ИМХО, это плохая идея использовать IP-адрес таким образом, что новый IP-адрес требует входа в систему, если вы не имеете дело с высокочувствительной информацией, такой как онлайн-банкинг. Это так?

Что вас беспокоит? Внешняя атака? Или в ситуации с общим хостом, что кто-то может прочитать вашу информацию о сеансе?

Если это последнее, решение прост: просто не храните ничего чувствительного в сеансе. Все важные данные должны храниться в базе данных.

Что касается создания секретной соли, вам нужно использовать что-то, что нельзя догадаться. Я бы выбрал нечто вроде случайной строки, созданной при создании пользователя. При необходимости воссоздайте его каждый раз, когда сеанс недействителен.

Что касается того, что сделало бы его более безопасным, вы сказали бы это сами: существуют ограниченные строки пользовательских агентов (менее сотни, вероятно, будут охватывать 99,99% пользователей). Соль просто увеличивает количество возможностей. При этом, если вы используете ту же соль для всех сеансов, то это всего лишь вопрос времени, прежде чем он будет найден с грубой силой.

Хорошо, например, я использую следующий вымышленный код:

 <?php // The sessionid cookie is now a certain hash if ( array_key_exists ( $_COOKIE [ 'sessionid' ] ) ) { // Get the session from database $db_sessid = $pdo -> getStuff ( 'session_database', $_COOKIE [ 'sessionid' ] ); if ( $db_sessid !== null && $db_sessid [ 'fingerprint' ] == sha1 ( 'SOMESALT' . $_SERVER [ 'HTTP_USER_AGENT' ] ) ) { set_cookie ( ... ); // New sessionid and write also to DB // User is now logged in, execute some user stuff } else { // Session doesn't exist, or the fingerprint does not match } } 

Теперь злоумышленнику все еще нужен sessionid, который находится в файле cookie (отправленном по HTTP-заголовкам) и useragent. Так что же еще вопрос дополнительной соли?

Проверка на IP-адрес также, на мой взгляд, не такая хорошая опция, некоторые провайдеры или прокси меняют их каждый отдельный запрос.

Спасибо до сих пор (-: