Где хранятся сессии php
Перейти к содержимому

Где хранятся сессии php

Как найти папку, в которой хранятся файлы сессий

Как известно, файл сессии
– хороший способ раскрутить локальный инклуд, но
как же определить папку в которой они находятся?
Ведь не всегда они хранятся в /tmp. Привожу
излюбленные мной способы поиска заветной папки.

1. Поиск phpinfo() на сайте.
Для этого ищем session.save_handler. Если его
значение установлено в «files» по дефолту,
значит сессии хрантся в файлах, ниже находится
значение session.save_path.

Первое значение – это так называемое Local
Value, уникально значение для конкретной папки и
ее подпапок (либо для конкретного сайта),
устанавливается в .htaccess.

Второе значение – это Master Value , общее
значение для всего сервера, устанавливается в
php.ini.

2. Поиск .htaccess, в этом
файле может быть установлено значение php_value
для session.save_path.

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

/tmp/
/php_sess/
/tmp/phpsess/
/tmp/php/
/tmp/php-sess/
/home/%username%/tmp/
/var/phptemp/
/var/phptmp/
/var/phpsess/
/var/php-sess/
/var/lib/php/
/var/lib/php/session/
/var/lib/php3
/var/lib/php3/session/
/var/lib/php4/
/var/lib/php4/session/
/var/lib/php5/
/var/lib/php5/session/
/var/lib/php6/
/var/lib/php6/session/
/www/phpsession/
C:\Temp
C:\WINDOWS\Temp
C:\PHP\sessiondata

Введение

Поддержка сессий в PHP заключается в способе сохранения некоторых данных между несколькими последовательными доступами.

Каждому посетителю сайта присваивается уникальный идентификатор, называемый идентификатором сессии (session id). Он хранится либо в cookie на стороне пользователя, либо передаётся через URL.

Поддержка сессий позволяет сохранять данные между запросами в суперглобальном массиве $_SESSION . В тот момент, когда посетитель получает доступ к сайту, PHP проверяет автоматически (если session.auto_start установлено в 1) или по запросу (явным образом через вызов session_start() ), был ли определённый идентификатор сессии послан вместе с запросом. Если это так, восстанавливается сохранённое ранее окружение.

При включённом session.auto_start единственным способом помещения объектов в сессию останется загрузка описаний класса с помощью auto_prepend_file. В противном случае придётся выполнить сериализацию ( serialize() ) и десериализацию ( unserialize() ) объекта вручную.

$_SESSION (и все зарегистрированные переменные) сериализуются внутри PHP после выполнения запроса, используя обработчик сериализации, указанный в INI-опции session.serialize_handler. Зарегистрированные, но неопределённые переменные помечаются как неопределённые. При последующем доступе они не определяются сессионным модулем, если пользователь заново не определит их.

Так как сессионные данные сериализуются, то переменные с типом resource не могут храниться в сессиях.

Обработчики сериализации ( php и php_binary ) наследуют ограничения для register_globals. Поэтому нельзя использовать числовые или строковые индексы содержащие специальные символы ( | и ! ). Их использование приведёт к ошибкам по завершении скрипта. У php_serialize такие ограничения отсутствуют.

Замечание:

При работе с сессиями обратите внимание, что запись в сессии не создаётся до тех пор, пока переменная не будет зарегистрирована через функцию session_register() или через добавление нового ключа в суперглобальном массиве $_SESSION . Это правило действует вне зависимости от того, была ли сессия запущена с использованием функции session_start() .

PHP сессии под скальпелем. Как работают PHP сессии изнутри

В Интернете можно найти тысячи туториалов о том, что такое сессии, для чего они нужны и как с ними работать. Но, к сожалению, прочитав их, всё равно остаётся множество вопросов. На мой взгляд, самый простой способ разобраться во всём — это посмотреть, как работают сессии изнутри. Т.е. изучить логи обмена браузера и веб-сервера, а также посмотреть, какие данные сохраняются на стороне клиента и на стороне сервера.

После этого многие моменты становятся куда более понятными, а сам механизм работы — более прозрачным.

Работу сессий будем изучать на следующем стандартном скрипте:

<?php

// блок 1
session_start();

// блок 2
if ( isset ($_SESSION[ ‘views’ ]))
$_SESSION[ ‘views’ ]+ +;
else
$_SESSION[ ‘views’ ] = 1;

// блок 3
echo «<html>
<body>
Количество просмотров: » .$_SESSION[ ‘views’ ]. »
</body>
</html>» ;

?>

Он работает следующим образом:

Блок 1. Функция session_start() создаёт новую сессию или загружает старую, используя уникальный идентификатор сессии PHPSESSID.

Блок 2. Если удалось восстановить сессию, то значение $_SESSION[‘views’] увеличивается на единицу. Если нет — инициализируется единицей.

Блок 3. Выводится количество просмотров данной страницы.

По идее, если в браузере включена поддержка кук, механизм должен работать и при каждом обновлении страницы значение счётчика будет увеличиваться на единицу.

Первая загрузка скрипта

Заголовки запроса
Заголовки ответа
Комментарий

В исходном запросе браузер не идентифицировал себя никаким образом, поэтому механизм сессий PHP сгенерировал новый уникальный идентификатор сессии и скомандовал браузеру создать куку, в которой будет храниться этот самый идентификатор.

Сторона сервера

В результате работы скрипта на стороне сервера создаётся файл sess_k33en6ccgcia7125mitj5te4u6 следующего содержания:

Сторона клиента

На стороне клиента создаётся кука PHPSESSID, в которой хранится значение уникального идентификатора сессии.

Примечание. При настройках PHP по умолчанию, время жизни куки PHPSESSID — до закрытия браузера. Т.е. как только браузер будет закрыт, кука будет удалена, а соответственно будет потеряна сессия. Время жизни куки PHPSESSID можно менять, варьируя значение session.cookie_lifetime.

Результат работы скрипта

Вторая загрузка скрипта

Заголовки запроса
Заголовки ответа
Комментарий

Браузер отправляет веб-серверу куку PHPSESSID, используя которую PHP инициализирует массив $_SESSION значениями из файла sess_k33en6ccgcia7125mitj5te4u6. Соответственно, в блоке 2 отрабатывает ветка IF (прямая).

Сторона сервера

В результате работы скрипта содержимое файла sess_k33en6ccgcia7125mitj5te4u6 меняется:

Сторона клиента

На стороне клиента ничего не меняется.

Результат работы скрипта

Что дальше?

Последующие загрузки страницы до закрытия браузера будут работать по аналогии с тем, как работала вторая загрузка скрипта.

Т.к. время жизни куки было ограничено текущей сессией браузера, то после его закрытия уникальный идентификатор сессии будет утерян и при перезапуске процесс пойдёт по новой.

Тем не менее можно вернуться к сохранённой сессии, если явно указать PHPSESSID в качестве параметра скрипта:

Возвращение к сессии довольно условное, т.к. в результате работы скрипта в данном случае кука не создаётся. Заголовки ответа сервера:

Т.е. для поддержания работы именно с этой сессией ко всем ссылкам придётся приписывать ?PHPSESSID=k33en6ccgcia7125mitj5te4u6.

Примечание. Можно указать PHP, чтобы уникальный идентификатор сессии передавался только через куку. Для этого нужно установить session.use_only_cookies в значение 1. В этом случае трюк, продемонстрированный выше, не пройдёт.

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

Небольшой вопросник (FAQ)

Где физически хранятся данные сессий?

Данные сессий хранятся на сервере. По умолчанию они записываются в файлы, но можно задать свой собственный механизм хранения данных сессий (например с использованием базы данных). Если хотите подробностей, смотрите функцию session_set_save_handler.

Кто генерирует уникальный идентификатор сессии?

Уникальный идентификатор сессии (PHPSESSID) генерирует сервер.

Можно ли написать собственный механизм сессий?

Да, это вполне возможно. Как видите, PHP не использует ничего сверхъестественного — идентификатор сохраняется между запросами с помощью кук, данные сессий хранятся в файлах на сервере.

Например, собственный механизм работы с сессиями есть в популярном фреймворке CodeIgniter.

Насколько безопасен механизм сессий?

Сессия идентифицируется только с помощью уникального идентификатора сессии, поэтому в общем случае злоумышленнику достаточно украсть его, чтобы запутать сервер. Возьмём тестовый скрипт, который мы использовали выше. Если обращение к нему будет с другого IP (по отношению к создавшему сессию), но PHPSESSID будет передаваться тот же самый, то сессия будет успешно восстановлена и счётчик будет увеличиваться с предыдущего сохранённого значения.

Обеспечивать дополнительную защиту придётся вам самим. Например:

    Можно сохранять в данных сессии IP и User-Agent клиента (будет храниться на стороне сервера), а затем при каждом обращении проверять, что актуальные значения совпадают с сохранёнными. В данном случае приходится искать компромисс между безопасностью и удобством работы пользователя.

К примеру, если у пользователя динамический IP и вы используете сессии для поддержания авторизации, но при этом проверяете совпадение IP, то при каждой смене адреса пользователю придётся заново вводить логин и пароль.

Работа сессий с повторной генерацией идентификатора в разрезе

Скрипт

<?php

// блок 1
session_start();
if ( isset ($_SESSION[ ‘initiated’ ]))
session_regenerate_id();
else
$_SESSION[ ‘initiated’ ] = true ;

// блок 2
if ( isset ($_SESSION[ ‘views’ ]))
$_SESSION[ ‘views’ ]++ ;
else
$_SESSION[ ‘views’ ] = 1;

// блок 3
echo «<html>
< body>
Количество просмотров : «. $_SESSION[ ‘views’].»
</body>
</html>» ;

?>

Комментарий

В блоке 1 появляется вызов функции session_regenerate_id с аргументом true, который говорит серверу удалять старые данные сессии при повторной генерации идентификатора. Это вовсе не означает, что данные будут потеряны — они будут доступны с использованием нового идентификатора. При обращении со старым PHPSESSID, сессия восстановлена не будет, а вместо этого будет создана новая.

Примечание. Переменная $_SESSION[‘initiated’] позволяет отслеживать, была ли сессия только что инициирована или же восстановлена. Проверка if(isset($_SESSION[‘views’])) необходима для того, чтобы избежать лишней перегенерации идентификатора и отправки двух кук в случае, если сессия только что создана. Если проверки не делать, произойдёт следующее (заголовки ответа сервера):

Первая загрузка скрипта

Заголовки запроса
Заголовки ответа
Комментарий

В исходном запросе браузер не идентифицировал себя никаким образом, поэтому механизм сессий PHP сгенерировал новый уникальный идентификатор сессии и скомандовал браузеру создать куку, в которой будет храниться этот самый идентификатор.

Сторона сервера

В результате работы скрипта на стороне сервера создаётся файл sess_fbbjvmj4ie6tm0sb81hp7jim05 следующего содержания:

Сторона клиента

На стороне клиента создаётся кука PHPSESSID=fbbjvmj4ie6tm0sb81hp7jim05, в которой хранится значение уникального идентификатора сессии.

Результат работы скрипта

Вторая загрузка скрипта

Заголовки запроса
Заголовки ответа
Комментарий

Браузер отправляет серверу куку, тот восстанавливает сессию, видит, что установлен флаг $_SESSION[‘initiated’] и поэтому генерирует новый идентификатор. Браузеру отдаётся команда установить новую куку.

Сторона сервера

В результате работы скрипта на стороне сервера файл sess_fbbjvmj4ie6tm0sb81hp7jim05, содержащий данные сессии, удаляется. Вместо него создаётся новый файл sess_tj86ptptn95vla890b1ag70au7 следующего содержания:

Сторона клиента

На стороне клиента обновляется кука PHPSESSID. Новое значение PHPSESSID= tj86ptptn95vla890b1ag70au7.

Результат работы скрипта

Далее всё повторяется по сценарию второй загрузки скрипта. При попытке использовать один из старых идентификаторов, сервер не найдёт соответствующий файл и будет создана новая сессия.

В работе использовались

  1. Веб-сервер Apache 2.2.13 (http://httpd.apache.org/).
  2. PHP 5.2.10 (http://www.php.net/)
  3. Mozilla Firefox 6.0.2 (http://www.mozilla.org/ru/firefox/). 1.8.3 для просмотра логов передачи данных между браузером и веб-сервером. (Спасибо Adil за подсказку.)
  4. Far Manager (http://www.farmanager.com/).
  5. Веб-сервис Bertal.ru для симуляции воровства кук.
  6. Eclipse PDT 2.2.0 All In Ones для симпатичной подсветки синтаксиса PHP (http://www.eclipse.org/projects/project.php?id=tools.pdt).

Реклама

Комментарии

Спасибо! Очень полезная статья все, что называется наглядно и по полочкам. Смущает один момент. При повторной генерации все же есть возможности перехватить идентификатор сессии и использовать в своих коварных целях. Риск конечно снижен за счет постоянного обновления этого идентифекатора, а привязка к ip и юзерагентам будет доставлять неудобства пользователям, но может быть существуют еще более надежные способы засчиты от хака сессий?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *