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

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


  1. maximw
    20.07.2015 16:12

    Т.е. если я сижу с другом на одном IP у нас будут одинаковые сессии?

    P.S. добрый совет: спрячьте в черновики пока не поздно.


    1. XanderBass Автор
      20.07.2015 16:19
      +3

      session_name изменяет имя сессии, но не идентификатор. Если несколько человек будет сидеть на одном IP, у них будут одинаковые имена кук, грубо говоря, но разные идентификаторы сессий.


      1. maximw
        20.07.2015 16:42

        Да, невнимательно прочитал.
        Плюс вам.


  1. lair
    20.07.2015 16:41
    +3

    1. XanderBass Автор
      20.07.2015 17:04
      -1

      Спасибо за полезную статью. Правда, я пока слабо понимаю, как это может быть применимо к PHP. Ведь для того, чтобы это работало, насколько я понял, клиент должен будет пересылать данные по определённому протоколу. Условно говоря, в сайт придётся встраивать JavaScript с реализацией этой методики.


      1. lair
        20.07.2015 17:05

        Ээээ, что имено «может быть применимо к PHP»?


        1. XanderBass Автор
          20.07.2015 17:29

          Приведённые в статье методики. Если я Вас понял неправильно, поясните прямо, что именно Вы хотели сказать.


          1. lair
            20.07.2015 17:34

            Я хотел сказать, что вы совершаете все те же ошибки, которые описаны в статье, а именно — используете криптографические механизмы, не до конца понимая их работу, предназначение и надежность.


            1. XanderBass Автор
              20.07.2015 17:38

              Данная методика является примером. Никто не мешает вместо MD5 использовать что-либо другое. Здесь важен сам принцип. Кстати, закономерный вопрос к Вам: а лично Вы как реализовали бы подобный механизм? Хотелось бы пример.


              1. lair
                20.07.2015 17:40

                Данная методика является примером. Никто не мешает вместо MD5 использовать что-либо другое.

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

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

                Какой «подобный»?


          1. lair
            20.07.2015 17:40

            PS Ничто не мешает применить HMAC поверх {IP, сессионный ключ} если вам так надо сессию к IP привязать без хранения на стороне сервера.


            1. XanderBass Автор
              20.07.2015 17:45
              -1

              Иными словами вся суть Вашей критики сводится к выбору алгоритма шифрования, я верно понимаю?


              1. lair
                20.07.2015 17:49

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


  1. ollisso
    20.07.2015 17:51
    +4

    Не понял как данный способ может что либо защитить.

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

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

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

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

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

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

    PS: Если вы хотите привязать систему к айпи, то легче просто в сессии хранить айпи клиента, и его сравнивать.


  1. XanderBass Автор
    20.07.2015 18:57
    -1

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

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

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


    1. ollisso
      21.07.2015 08:01

      То есть фактически вы предлагаете таким странным методом защитится от брутфорса, и это вся суть статьи? :)

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

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


  1. dzugaru
    20.07.2015 19:36
    +1

    Держите сессии в базе и храните для них всю возможную метаинформацию (ip, user-agent, срок жизни, и.т.д.).