СоХабр закрыт.

С 13.05.2019 изменения постов больше не отслеживаются, и новые посты не сохраняются.

| сохранено

H Сессии: заметка о параноидальной защите в черновиках Recovery Mode

PHP
Доброго всем здравия!

В процессе разработки своего фреймворка я столкнулся с классической проблемой защиты сессии. Изначально сессии беззащитны перед похищением своего идентификатора. Грубо говоря, если хакер каким-то образом узнал идентификатор сессии, он может взять идентификатор сессии (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)

0
+5 –5
maximw ,   * (был изменён)
Т.е. если я сижу с другом на одном IP у нас будут одинаковые сессии?

P.S. добрый совет: спрячьте в черновики пока не поздно.
+3
+4 –1
XanderBass ,  
session_name изменяет имя сессии, но не идентификатор. Если несколько человек будет сидеть на одном IP, у них будут одинаковые имена кук, грубо говоря, но разные идентификаторы сессий.
0
+1 –1
maximw ,  
Да, невнимательно прочитал.
Плюс вам.
+3
lair ,  
–1
XanderBass ,  
Спасибо за полезную статью. Правда, я пока слабо понимаю, как это может быть применимо к PHP. Ведь для того, чтобы это работало, насколько я понял, клиент должен будет пересылать данные по определённому протоколу. Условно говоря, в сайт придётся встраивать JavaScript с реализацией этой методики.
0
lair ,  
Ээээ, что имено «может быть применимо к PHP»?
0
XanderBass ,  
Приведённые в статье методики. Если я Вас понял неправильно, поясните прямо, что именно Вы хотели сказать.
0
lair ,  
Я хотел сказать, что вы совершаете все те же ошибки, которые описаны в статье, а именно — используете криптографические механизмы, не до конца понимая их работу, предназначение и надежность.
0
XanderBass ,  
Данная методика является примером. Никто не мешает вместо MD5 использовать что-либо другое. Здесь важен сам принцип. Кстати, закономерный вопрос к Вам: а лично Вы как реализовали бы подобный механизм? Хотелось бы пример.
0
lair ,  
Данная методика является примером. Никто не мешает вместо MD5 использовать что-либо другое.

Не надо в примерах давать заведомо неправильные решения.

Кстати, закономерный вопрос к Вам: а лично Вы как реализовали бы подобный механизм?

Какой «подобный»?
0
lair ,  
PS Ничто не мешает применить HMAC поверх {IP, сессионный ключ} если вам так надо сессию к IP привязать без хранения на стороне сервера.
–1
XanderBass ,  
Иными словами вся суть Вашей критики сводится к выбору алгоритма шифрования, я верно понимаю?
0
lair ,  
Нет, суть моей критики описана в (жаль, что не моей) статье — вы выбираете какое-то решение «для повышения безопасности», не описываете, от чего оно защищает (в частности, оно остается уязвимо к типичной атаке в публичных сетях), но при этом усложняете жизнь пользователю (если у него «прыгнет» ip, он потеряет сессию на пустом месте).
+4
ollisso ,   * (был изменён)
Не понял как данный способ может что либо защитить.

Расматриваем ситуацию, в которой атакующий может украсть куку.

Раньше: он знал название куки
Теперь: ему нужно украсть все куки, и просто выбрать нужную.

Я думаю все способы воровства кук — позволяют это сделать. И MITM атака, и JS позволяет украсть все куки.

В чём защита? :)

А после того как украли все куки, то кто мешает атакеру, скопировать значение куки, но при этом изменить название куки?

Плюс у вас не решена проблема с тем, что айпи меняется. Вы будете очень сильно удивлены, насколько часто у людей меняется айпи, с учётом разных Opera Turbo и подобных систем.

PS: Если вы хотите привязать систему к айпи, то легче просто в сессии хранить айпи клиента, и его сравнивать.
–1
XanderBass ,  
Привязка по IP в данном случае рассматривается, как мера безопасности. Я не буду удивлён, ибо на анонимайзеры безопасные системы не рассчитаны. Это во-первых. К слову, пользователь может быть авторизован на нескольких устройствах. И авторизация пройдёт на всех устройствах, если пользователь легитимно авторизовался. Мультисессионность, знаете ли. Во-вторых, Вы, простите, невнимательно читали статью, а точнее то, что было написано в конце. Цитирую.

> Сразу оговорюсь, что от непосредственного похищения куки такой способ не покатит. Но вот от брутфорса, описанного тут — вполне.

Этот способ позволяет избежать перебора session_id, брутфорс иными словами. Перебирать ID сессий, зная точно имя переменной проще некуда. Тут главное вовремя определять в чью сессию попал. А вот от изменения куки этот способ вполне прокатит, например, если на стороне сервера осуществлять проверку существования сессии в БД (у меня в движке это так и делается).
0
ollisso ,  
То есть фактически вы предлагаете таким странным методом защитится от брутфорса, и это вся суть статьи? :)

Тогда можно просто сделать session_id из 128 случайных символов, или же по маске: XXXX_md5(ip) где XXXX это случайные 80 символов (буквы и цифры)

Добавить хранение в сессии айпи юзера и проверять его, и все.
Только это защита через obscurity. От атакера сильно не поможет. Перебирать айди сессии брутфорсом, если они еще и живут 1-3 часа, это безсмысленно.
+1
dzugaru ,  
Держите сессии в базе и храните для них всю возможную метаинформацию (ip, user-agent, срок жизни, и.т.д.).