
Одно из указаний - вызывать session_regenerate_id каждый раз при изменении уровня безопасности сеанса. Это помогает предотвратить захват сеанса.
Я думаю, что одна из основных проблем (которая решается в PHP 6) - это register_globals. В настоящее время одним из стандартных методов, используемых для предотвращения использования register_globals, является использование массивов $_REQUEST, $_GET или $_POST.
«Правильный» способ сделать это (начиная с 5.2, хотя там немного глючит, но стабильно с 6, которая скоро появится) через фильтры.
Так что вместо:
$username = $_POST["username"];
вы бы сделали:
$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
или даже просто:
$username = filter_input(INPUT_POST, 'username');
Действительно? Тогда почему в принятом ответе они упоминают не использовать глобальные регистры? Разве, с точки зрения большинства рядовых разработчиков, регистрация глобальных переменных и обработка переменных формы не подпадают под действие «сеансов», даже если они технически не являются частью объекта «сеанс»?
Я согласен, это не ответ от корки до корки на вопрос, но это определенно ЧАСТЬ ответа на вопрос. Опять же, это конкретизирует пункт в принятом ответе: «Не использовать глобальные переменные регистров». Это говорит о том, что делать вместо этого.
Это довольно тривиально и очевидно, но обязательно выполняйте session_destroy после каждого использования. Это может быть сложно реализовать, если пользователь не выходит из системы явно, поэтому для этого можно установить таймер.
Вот хороший руководство для setTimer () и clearTimer ().
Основная проблема с сеансами PHP и безопасностью (помимо перехвата сеанса) связана с тем, в какой среде вы находитесь. По умолчанию PHP хранит данные сеанса в файле во временном каталоге ОС. Без каких-либо особых размышлений или планирования это каталог, доступный для чтения во всем мире, поэтому вся информация о вашем сеансе является общедоступной для всех, у кого есть доступ к серверу.
Что касается поддержки сеансов на нескольких серверах. На этом этапе было бы лучше переключить PHP на сеансы, обрабатываемые пользователем, где он вызывает предоставленные вами функции для CRUD (создание, чтение, обновление, удаление) данных сеанса. На этом этапе вы можете сохранить информацию о сеансе в базе данных или в кэше памяти, как решение, чтобы все серверы приложений имели доступ к данным.
Хранение ваших собственных сеансов также может быть выгодным, если вы находитесь на общем сервере, потому что это позволит вам хранить его в базе данных, которую вы часто имеете больший контроль, чем файловая система.
Я бы проверил как IP, так и User Agent, чтобы узнать, меняются ли они
if ($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']
|| $_SESSION['user_ip'] != $_SERVER['REMOTE_ADDR'])
{
//Something fishy is going on here?
}
IP-адрес может изменяться законно, если пользователь находится за фермой прокси с балансировкой нагрузки.
А user_agent может меняться каждый раз, когда пользователь обновляет свой браузер.
@scotts Я согласен с IP-частью, но для обновления браузера вы должны установить сеанс, когда они войдут в систему, поэтому я не вижу, как они будут обновлять там браузер, не создавая новый сеанс, когда они снова войдут в систему.
Я считаю, что user_agent также может измениться при переключении между совместимым режимом в IE8. Также очень легко подделать.
Да, но как насчет пользователей, у которых был статический IP-адрес GSM, который меняется каждые полчаса. Итак, сохраненный IP в сеансе + имя хоста, WHEN IP! = REMOTE_ADDR проверяет хост и сравнивает хосты eq. 12.12.12.holand.nl-> когда holand.nl == true. Но у какого-то хоста было имя хоста на основе IP. Тогда нужно сравнить маску 88.99.XX.XX.
@jasondavis Существует браузер Chrome.
По моему опыту, использование IP-адреса - не лучшая идея. Например; В моем офисе два IP-адреса, которые используются в зависимости от нагрузки, и мы постоянно сталкиваемся с проблемами при использовании IP-адресов.
Вместо этого я решил хранить сеансы в отдельной базе данных для доменов на моих серверах. Таким образом, никто в файловой системе не имеет доступа к этой информации о сеансе. Это было действительно полезно с phpBB до 3.0 (с тех пор они это исправили), но я думаю, что это все еще хорошая идея.
Если вы используете session_set_save_handler (), вы можете установить свой собственный обработчик сеанса. Например, вы можете хранить свои сеансы в базе данных. Обратитесь к комментариям php.net за примерами обработчика сеанса базы данных.
Сеансы БД также хороши, если у вас есть несколько серверов, в противном случае, если вы используете сеансы на основе файлов, вам нужно будет убедиться, что каждый веб-сервер имеет доступ к одной и той же файловой системе для чтения / записи сеансов.
Чтобы обеспечить безопасность сеанса, нужно сделать несколько вещей:
$_SERVER['HTTP_USER_AGENT']. Это добавляет небольшой барьер для перехвата сеанса. Вы также можете проверить IP-адрес. Но это вызывает проблемы у пользователей, которые меняют IP-адрес из-за балансировки нагрузки при нескольких подключениях к Интернету и т. д. (Что имеет место в нашей среде здесь).Использование SSL только для некоторых операций недостаточно, если у вас нет отдельных сеансов для зашифрованного и незашифрованного трафика. Если вы используете один сеанс через HTTPS и HTTP, злоумышленник украдет его при первом запросе, отличном от HTTPS.
Я согласен с porneL. Кроме того, для номера 6, если у злоумышленника есть ваш идентификатор сеанса, не будет ли он также иметь доступ к вашему пользовательскому агенту?
Если вы регенерируете идентификатор сеанса, то идентификатор сеанса, который злоумышленник украл по запросу, отличному от HTTPS, бесполезен.
-1 пользовательский агент легко подделать. То, что вы описываете, является пустой тратой кода и не является системой безопасности.
Черт, я бы хотел дать вам еще -1 для использования ssl. Ни в коем случае cookie не может быть пропущен через http, это изложено в OWASP A3.
@ The Rook, да, User Agent можно подделать. Это всего лишь один маленький барьер. И что вы имеете в виду, говоря, что cookie не может просочиться через http. Да, его можно украсть. http - это простой текст.
@grom единственный барьер - это тот, который находится в вашем уме, вы не останавливаете атаку.
@The Rook, это может быть тривиальный барьер (злоумышленник может захватить пользовательский агент жертвы, используя свой собственный сайт) и полагается на безопасность через неясность, но это все еще один дополнительный барьер. Если пользовательский агент HTTP изменится во время использования сеанса, это будет крайне подозрительно и, скорее всего, станет атакой. Я никогда не говорил, что вы можете использовать его в одиночку. Если вы объедините его с другими методами, вы получите гораздо более безопасный сайт.
@grom Я думаю, это все равно что приклеить кусок скотча к двери и сказать, что это предотвратит проникновение людей.
Если вы проверяете пользовательский агент, вы блокируете все запросы от пользователей IE8, когда они переключают режим совместимости. Посмотрите, как весело я отследил эту проблему в моем собственном коде: serverfault.com/questions/200018/http-302-problem-on-ie7. Я беру проверку пользовательского агента, потому что это такая тривиальная вещь, чтобы подделать, как говорили другие.
Не создавайте сеанс заново при каждом запросе. Он чувствителен к условиям гонки, и вы рано или поздно потеряете сессию.
@grom Разве Chrome не меняет свой пользовательский агент автоматически, когда он обновляется в фоновом режиме, пока пользователь использует браузер? Таким образом вы блокируете реальных пользователей без уважительной причины. Не забывайте, что повышенное удобство использования - это еще и повышенная безопасность.
Вы должны быть уверены, что данные сеанса в безопасности. Посмотрев на свой php.ini или используя phpinfo (), вы можете найти настройки сеанса. _session.save_path_ сообщает вам, где они сохранены.
Проверьте разрешение папки и ее родителей. Он не должен быть общедоступным (/ tmp) или быть доступным для других веб-сайтов на вашем общем сервере.
Предполагая, что вы все еще хотите использовать сеанс php, вы можете настроить php для использования другой папки, изменив _session.save_path_, или сохранить данные в базе данных, изменив _session.save_handler_.
Возможно, вы сможете установить _session.save_path_ в своем php.ini (некоторые поставщики разрешают это) или для apache + mod_php в файле .htaccess в корневой папке вашего сайта:
php_value session.save_path "/home/example.com/html/session". Вы также можете установить его во время выполнения с помощью _session_save_path () _.
Отметьте Руководство Криса Шифлетта или Zend_Session_SaveHandler_DbTable для установки альтернативного обработчика сеанса.
Этот документ фиксации сеанса имеет очень хорошие указатели, где может произойти атака. См. Также страница фиксации сеанса в Википедии.
Мои два (или более) цента:
По этой теме есть небольшая, но хорошая книжка: Основная безопасность PHP, Крис Шифлетт.
Основная безопасность PHP http://shiflett.org/images/essential-php-security-small.png
На домашней странице книги вы найдете несколько интересных примеров кода и примеры глав.
Вы можете использовать упомянутую выше технику (IP и UserAgent), описанную здесь: Как избежать кражи личных данных
+1 за XSS-предотвращение. Без этого невозможно защититься от CSRF, и, таким образом, кто-то может «оседлать» сеанс, даже не получив его идентификатора.
Я настроил свои сеансы так:
на странице входа:
$_SESSION['fingerprint'] = md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR']);
(фраза определена на странице конфигурации)
затем в заголовке, который есть на всем остальном сайте:
session_start();
if ($_SESSION['fingerprint'] != md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR'])) {
session_destroy();
header('Location: http://website login page/');
exit();
}
session.cookie_httponly = 1
change session name from default PHPSESSID
X-XSS-Protection 1
httpd.conf ->
Имейте в виду, что X-XSS-Protection на самом деле бесполезен. Фактически, сам алгоритм защиты можно было использовать, что сделало его хуже, чем раньше.
Это вообще не имеет отношения к вопросу.