Регистрация  Забыли пароль?
logo   Блоги рядом:  Вовка, football, Quest Pistols

Ни о чем ;)

записки программиста

devblog-avatar2.jpg

Styx  25.04.2008 23:41:56

Баг в PHP с сессиями

 Сегодня обнаружили очень неприятный баг в PHP.

Коротко: при создании файла сессии PHP не проверяет на наличие уже существующего файла с таким именем :(

Длинно:

При открытии сессии PHP:

1. генерит "уникальное" имя сессии, например sess_01234567890abcdef и сохраняет файлик в папку сессий, указанных в php.ini, например в /tmp

2. пишет браузеру куку с именем PHPSESSID и значением "0123456789abcdef".

3. при приходе браузера с кукой PHPSESSID - из нее берется идентификатор сессии ("0123456789abcdef") и сопоставляется с файликом на сервере (sess_0123456789abcdef)

Наверняка, все знают идеологическую дыру в этой системе: если я утяну куку PHPSESSID с чужого браузера и подсуну в свой - сервер будет сопоставлять оба браузера с одним файлом сессии.

Так вот. Сегодня обнаружилось, что при создании сессии PHP совсем не задается вопросом "а есть ли уже сессия с таким идентификатором?". В итоге, PHP может создать сессию (и послать браузеру куку PHPSESSID) с уже имеющимся идентификатором. Немного непонятно, как так получается, по заверениям разработчиков генерируемый SESSID должен быть уникальным. Однако даже md5(microtime(true)) - всего лишь псевдоуникальность, обусловленная спецификой алгоритма хэширования...

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

Как решается эта проблема? На самом деле, очень просто:

Мы вообще отказываемся от механизма сессий в PHP, и используем свой. Генерируем SESSID путем хэширования (лучше sha1) некоторых данных пользователя (user_id вполне подойдет) и случайных данных (например, /dev/urandom). Хранить сессии можно в файлах (обязательно проверяем созданный SESSID на уникальность ;) ), а можно - в БД. Табличка с TYPE=MEMORY вполне сойдет. Попутно можно хранить некую специфическую информацию, связанную с сессией, например, User-agent, IP и т.д. для улучшения персонализации.

Комментариев: 9

 
Контрольное число

при создании файла сессии PHP не проверяет на наличие уже существующего файла с таким именем

А как вы это обнаружили?

spacer 20

Совершенно случайно.

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

Однако вчера случилась такая ситуация:

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

Минут 5 мы с коллегой были в ступоре, потом кинулись искать причины этого. Оказалось, нам обоим (мне и тому сотруднику саппорта, далее - СТП) PHP записал одинаковую куку PHPSESSID, которая указывала на один и тот же файл сессии на сервере.

Что теперь получается: я выхожу из админки - СТП выкидывает тоже. Он заходит в админку - я обновляю страницу админки - оказываюсь залогиненным  под ним. Но самое страшное: я логинюсь в админку - СТП обновляет админку - оказывается залогиненным подо мной (а у меня все возможные права).

Вот такая неприятная фигня.

 

spacer 30

А вы можете привести куски кода, отвечающие за сессию? (И версию PHP.) Мне кажется, что такую примитивную ошибку давно бы исправили…

Ого, цікаво цікаво. Взагалі я теж чув частенько негативні відгуки про пхп-шні сесії, хоча зачасту автори не конкретизували чому їм неподобається.

А вы можете привести куски кода, отвечающие за сессию? (И версию PHP.) Мне кажется, что такую примитивную ошибку давно бы исправили…

spacer 20

Куски кода приводить нет смысла, там все нормально. Уверены на 99%, что бага в пыхпыхе.

PHP 5.2.5 (litespeed) (built: Jan 9 2008 21:38:48) Copyright (c) 1997-2004 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies

spacer 30

А с другой стороны, не пойман — не вор.

spacer 40

Не осилил...

spacer 30

случайно забрел, но могу подтвердить - есть такая бага. сперва сам не поверил, но коллективный разум - вещь сильная, скриптов понаваяли тестовых - проверили - точно баг. сопоставление информации дает такую картину: бага проявилась только на cgi (на mod`e ее нет) и только на 2-х серверах, версия пыха - 5.2.5, пробовали играться с положением старта сесссии - не дает результатов. проверено серверов - 18, проблема только с двумя. там нет ничего серьезного, а посему забил и забыл. нет ни времени, ни желания копать, да и версия пыха на смену уже есть. хотя, вопрос относительно безопасности конкретно меня озадачил. эх, пых....