Безопасность сеанса PHP

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

Ответов (13)

Решение

Чтобы обеспечить безопасность сеанса, нужно сделать несколько вещей:

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

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

if ($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']
    || $_SESSION['user_ip'] != $_SERVER['REMOTE_ADDR'])
{
    //Something fishy is going on here?
}

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

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

По этой теме есть небольшая, но хорошая книга Криса Шифлетта Essential PHP Security .

Основная безопасность PHP http://shiflett.org/images/essential-php-security-small.png

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

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

php.ini

session.cookie_httponly = 1
change session name from default PHPSESSID

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

X-XSS-Protection    1

Одно из указаний - вызывать 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-адреса - не лучшая идея. Например; В моем офисе два IP-адреса, которые используются в зависимости от нагрузки, и мы постоянно сталкиваемся с проблемами при использовании IP-адресов.

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

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

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

Вы должны быть уверены, что данные сеанса в безопасности. Посмотрев на свой php.ini или используя phpinfo (), вы можете найти настройки сеанса. _session.save_path_ сообщает вам, где они сохранены.

Проверьте разрешение папки и ее родителей. Он не должен быть общедоступным (/ tmp) или быть доступным для других веб-сайтов на вашем общем сервере.

Предполагая, что вы все еще хотите использовать сеанс php, вы можете настроить php для использования другой папки, изменив _session.save_path_, или сохранить данные в базе данных, изменив _session.save_handler_.

Вы можете быть в состоянии установить _session.save_path_ в вашем php.ini (некоторые провайдеры позволяют это) или для апача + mod_php, в файле .htaccess в корневой папке сайта: php_value session.save_path "/home/example.com/html/session" . Вы также можете установить его во время выполнения с помощью _session_save_path () _.

Проверьте учебник Криса Шифлетта или Zend_Session_SaveHandler_DbTable, чтобы установить альтернативный обработчик сеанса.

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

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

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

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