В процессе разработки своего фреймворка я столкнулся с классической проблемой защиты сессии. Изначально сессии беззащитны перед похищением своего идентификатора. Грубо говоря, если хакер каким-то образом узнал идентификатор сессии, он может взять идентификатор сессии (PHPSESSID в самом тупом случае) и подставив оный в свою куку, получить доступ к сессии пользователя. Если изменить имя сессии на произвольное, это лишь чуть-чуть осложнит автоматизацию взлома такого рода. Достаточно будет узнать идентификатор сессии конкретного проекта и сложность взлома опять сводится до похищения идентификатора сессии. В качестве превентивной защиты можно привязывать сессию к IP пользователя, но опять-таки же IP при желании можно подделать.
Сразу говорю: речь идёт об имени переменной сессии, а не об идентификаторе оной. В качестве пояснения ищем мануал по функции PHP session_name.
Для начала усложним задачу хакеру, выбрав в качестве имени сессии IP пользователя, зашифрованный при помощи, скажем, MD5. Соответственно, для каждого IP будет своё уникальное имя сессии. И для того, чтобы использовать идентификатор сессии, нужно знать IP этого идентификатора.
$sessName = md5($_SERVER['REMOTE_ADDR']);
session_name($sessName);
session_start();
Однако, как я уже говорил выше, IP при желании можно узнать. Поэтому добавляем к IP-адресу «соль» — псевдослучайное, специфичное для каждого проекта сочетание букв и цифр. Таким образом даже если хакер угадает IP пользователя, он не сможет сгенерировать имя сессии без знания «соли».
$salt = 'dbfbvfkkjfklfkjhfkhk'; // Тупо постучал по клавиатуре
$sessName = md5($salt.$_SERVER['REMOTE_ADDR']);
session_name($sessName);
session_start();
В итоге получается, что даже если хакер свистнет идентификатор сессии и IP-адрес у незадачливого пользователя, использовать его будет большой проблемой. Для дополнительной безопасности пользователей необходимо скрыть их IP-адреса.
Сразу оговорюсь, что от непосредственного похищения куки такой способ не покатит. Но вот от брутфорса, описанного тут — вполне.
Спасибо за внимание к моему очередному велосипеду!
Комментарии (17)
lair
20.07.2015 16:41+3XanderBass Автор
20.07.2015 17:04-1Спасибо за полезную статью. Правда, я пока слабо понимаю, как это может быть применимо к PHP. Ведь для того, чтобы это работало, насколько я понял, клиент должен будет пересылать данные по определённому протоколу. Условно говоря, в сайт придётся встраивать JavaScript с реализацией этой методики.
lair
20.07.2015 17:05Ээээ, что имено «может быть применимо к PHP»?
XanderBass Автор
20.07.2015 17:29Приведённые в статье методики. Если я Вас понял неправильно, поясните прямо, что именно Вы хотели сказать.
lair
20.07.2015 17:34Я хотел сказать, что вы совершаете все те же ошибки, которые описаны в статье, а именно — используете криптографические механизмы, не до конца понимая их работу, предназначение и надежность.
XanderBass Автор
20.07.2015 17:38Данная методика является примером. Никто не мешает вместо MD5 использовать что-либо другое. Здесь важен сам принцип. Кстати, закономерный вопрос к Вам: а лично Вы как реализовали бы подобный механизм? Хотелось бы пример.
lair
20.07.2015 17:40Данная методика является примером. Никто не мешает вместо MD5 использовать что-либо другое.
Не надо в примерах давать заведомо неправильные решения.
Кстати, закономерный вопрос к Вам: а лично Вы как реализовали бы подобный механизм?
Какой «подобный»?
lair
20.07.2015 17:40PS Ничто не мешает применить HMAC поверх {IP, сессионный ключ} если вам так надо сессию к IP привязать без хранения на стороне сервера.
XanderBass Автор
20.07.2015 17:45-1Иными словами вся суть Вашей критики сводится к выбору алгоритма шифрования, я верно понимаю?
lair
20.07.2015 17:49Нет, суть моей критики описана в (жаль, что не моей) статье — вы выбираете какое-то решение «для повышения безопасности», не описываете, от чего оно защищает (в частности, оно остается уязвимо к типичной атаке в публичных сетях), но при этом усложняете жизнь пользователю (если у него «прыгнет» ip, он потеряет сессию на пустом месте).
ollisso
20.07.2015 17:51+4Не понял как данный способ может что либо защитить.
Расматриваем ситуацию, в которой атакующий может украсть куку.
Раньше: он знал название куки
Теперь: ему нужно украсть все куки, и просто выбрать нужную.
Я думаю все способы воровства кук — позволяют это сделать. И MITM атака, и JS позволяет украсть все куки.
В чём защита? :)
А после того как украли все куки, то кто мешает атакеру, скопировать значение куки, но при этом изменить название куки?
Плюс у вас не решена проблема с тем, что айпи меняется. Вы будете очень сильно удивлены, насколько часто у людей меняется айпи, с учётом разных Opera Turbo и подобных систем.
PS: Если вы хотите привязать систему к айпи, то легче просто в сессии хранить айпи клиента, и его сравнивать.
XanderBass Автор
20.07.2015 18:57-1Привязка по IP в данном случае рассматривается, как мера безопасности. Я не буду удивлён, ибо на анонимайзеры безопасные системы не рассчитаны. Это во-первых. К слову, пользователь может быть авторизован на нескольких устройствах. И авторизация пройдёт на всех устройствах, если пользователь легитимно авторизовался. Мультисессионность, знаете ли. Во-вторых, Вы, простите, невнимательно читали статью, а точнее то, что было написано в конце. Цитирую.
> Сразу оговорюсь, что от непосредственного похищения куки такой способ не покатит. Но вот от брутфорса, описанного тут — вполне.
Этот способ позволяет избежать перебора session_id, брутфорс иными словами. Перебирать ID сессий, зная точно имя переменной проще некуда. Тут главное вовремя определять в чью сессию попал. А вот от изменения куки этот способ вполне прокатит, например, если на стороне сервера осуществлять проверку существования сессии в БД (у меня в движке это так и делается).ollisso
21.07.2015 08:01То есть фактически вы предлагаете таким странным методом защитится от брутфорса, и это вся суть статьи? :)
Тогда можно просто сделать session_id из 128 случайных символов, или же по маске: XXXX_md5(ip) где XXXX это случайные 80 символов (буквы и цифры)
Добавить хранение в сессии айпи юзера и проверять его, и все.
Только это защита через obscurity. От атакера сильно не поможет. Перебирать айди сессии брутфорсом, если они еще и живут 1-3 часа, это безсмысленно.
dzugaru
20.07.2015 19:36+1Держите сессии в базе и храните для них всю возможную метаинформацию (ip, user-agent, срок жизни, и.т.д.).
maximw
Т.е. если я сижу с другом на одном IP у нас будут одинаковые сессии?
P.S. добрый совет: спрячьте в черновики пока не поздно.
XanderBass Автор
session_name изменяет имя сессии, но не идентификатор. Если несколько человек будет сидеть на одном IP, у них будут одинаковые имена кук, грубо говоря, но разные идентификаторы сессий.
maximw
Да, невнимательно прочитал.
Плюс вам.