PHP Session Security

Каковы некоторые рекомендации по поддержанию ответственной безопасности сеанса с помощью PHP? В Интернете есть информация, и пришло время приземлиться в одном месте!

13 ответов

Решение

Есть несколько вещей, чтобы сохранить ваш сеанс в безопасности:

  1. Используйте SSL при аутентификации пользователей или выполнении конфиденциальных операций.
  2. Регенерируйте идентификатор сеанса всякий раз, когда изменяется уровень безопасности (например, вход в систему). Вы можете даже восстановить идентификатор сессии каждый запрос, если хотите.
  3. Время сессий
  4. Не используйте регистр глобалов
  5. Храните данные аутентификации на сервере. То есть не отправляйте такие данные, как имя пользователя, в cookie.
  6. Проверить $_SERVER['HTTP_USER_AGENT'], Это добавляет небольшой барьер для захвата сессии. Вы также можете проверить IP-адрес. Но это вызывает проблемы у пользователей, которые меняют IP-адрес из-за балансировки нагрузки на несколько интернет-соединений и т. Д. (Что имеет место в нашей среде здесь).
  7. Заблокируйте доступ к сеансам в файловой системе или используйте пользовательскую обработку сеансов
  8. Для чувствительных операций рассмотрите требование, чтобы вошедшие в систему пользователи снова предоставили свои данные аутентификации.

Одно из правил - вызывать http://www.php.net/session_regenerate_id каждый раз, когда изменяется уровень безопасности сеанса. Это помогает предотвратить угон сеанса.

Мои два (или более) цента:

  • Не доверять никому
  • Фильтр ввода, экранирование вывода (cookie, данные сеанса также являются вашими данными)
  • Избегайте XSS (держите ваш HTML правильно, посмотрите на PHPTAL или HTMLPurifier)
  • Глубокая защита
  • Не подвергайте данные

На эту тему есть небольшая, но хорошая книга: Essential PHP Security от Chris Shiflett.

http://shiflett.org/images/essential-php-security-small.png

На главной странице книги вы найдете несколько интересных примеров кода и примеров глав.

Вы можете использовать метод, упомянутый выше (IP & UserAgent), описанный здесь: Как избежать кражи личных данных

Я думаю, что одна из основных проблем (которая решается в 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');

Этот документ по фиксации сессии имеет очень хорошие указатели, где может произойти атака. Смотрите также страницу фиксации сессии в Википедии.

Использование IP-адреса не является лучшей идеей в моем опыте. Например; В моем офисе есть два IP-адреса, которые используются в зависимости от нагрузки, и мы постоянно сталкиваемся с проблемами с использованием IP-адресов.

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

Это довольно тривиально и очевидно, но обязательно используйте http://www.php.net/session_destroy после каждого использования. Это может быть трудно реализовать, если пользователь явно не выходит из системы, поэтому для этого можно установить таймер.

Вот хороший учебник по setTimer() и clearTimer().

Я настроил свои сессии так

на странице входа в систему:

$_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();     
}

php.ini

session.cookie_httponly = 1
change session name from default PHPSESSID

eq Apache добавить заголовок:

X-XSS-Protection    1

Основная проблема с PHP-сессиями и безопасностью (помимо перехвата сессий) связана с тем, в какой среде вы находитесь. По умолчанию PHP сохраняет данные сессий в файле во временном каталоге ОС. Без какого-либо особого размышления или планирования, это общедоступный каталог, поэтому вся информация о вашем сеансе доступна для всех, кто имеет доступ к серверу.

Что касается ведения сеансов на нескольких серверах. В этот момент было бы лучше переключить PHP на пользовательские сеансы, где он вызывает предоставленные вами функции для CRUD (создание, чтение, обновление, удаление) данных сеанса. В этот момент вы можете хранить информацию о сеансе в базе данных или в виде решения, подобного memcache, чтобы все серверы приложений имели доступ к данным.

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

Вы должны быть уверены, что данные сеанса в безопасности. Посмотрев на свой 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 для установки и альтернативного обработчика сеанса.

Если вы используете session_set_save_handler(), вы можете установить свой собственный обработчик сессии. Например, вы можете хранить ваши сессии в базе данных. Обратитесь к комментариям php.net за примерами обработчика сеанса базы данных.

Сеансы БД также хороши, если у вас несколько серверов, в противном случае, если вы используете файловые сеансы, вам необходимо убедиться, что каждый веб-сервер имеет доступ к одной и той же файловой системе для чтения / записи сеансов.

Я бы проверил IP и User Agent, чтобы увидеть, если они меняются

if ($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']
    || $_SESSION['user_ip'] != $_SERVER['REMOTE_ADDR'])
{
    //Something fishy is going on here?
}
Другие вопросы по тегам