Типичная ошибка при установке COOKIE в PHP

    Хочу поделиться одной особенностью при установке значений COOKIE, которую очень часто забывают веб-разработчики.
    В моей практике исследования веб-приложений на уязвимости, за 2009-2011 года, данная ошибка встретилась в 87% веб-приложений, написанных на PHP.
    Чтобы как-то уменьшить данный показатель, решил написать этот текст.

    Речь пойдет даже не о httpOnly флаге, хотя его использование не менее важно и обязательно к применению.

    Рассмотрим пример кода:
    <?php
    setcookie('foo','bar1');
    header('Set-cookie: foo1=bar11');
    ?>
    


    Данный код, очевидно, устанавливает два значения COOKIE с именами foo и foo1.
    Теперь главный вопрос — для какого домена и с какими флагами?

    Обратимся к первоисточнику — HTTP-ответу веб-сервера:
    image

    Как видно, сервер ничего не говорит ни о домене, ни о флагах.
    Тогда вопрос переходит в другую плоскость — какой домен и флаги выберет браузер для такого заголовка?

    В случае с Chrome (актуальная версия 18.0.1025.168), все будет более чем хорошо и домен будет ровно такой, с которого пришел запрос. В моем примере — foo.bar.com:
    image

    Если бы все было так хорошо, наверное, здесь бы не было текста…

    Проверим Internet Explorer. Так как красивых плагинов для просмотра COOKIE для него я не знаю, проставим куки для домена foo.com и выведем document.cookie с домена bar.foo.com:
    image

    Это очень печально. И забавно с другой стороны.
    При получении в НТТР-ответе сервера
    Set-cookie: foo=bar
    Internet Explorer ставит foo=bar для ВСЕХ поддоменов, то есть *.foo.com в моем примере без всяких флагов, таких как httpOnly.


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

    А как же остальные браузеры?
    Firefox 12.0 httpOnly wildcard
    Safari 5.1.5 httpOnly wildcard
    Opera 11.62 httpOnly wildcard


    Таким образом, используя конструкции
    setcookie('foo','bar1');
    

    и
    header('Set-cookie: foo1=bar11');
    

    в случае использования клиентом Internet Explorer (8-9), вы проставляете COOKIE на ВСЕ поддомены от данного.

    Помните об этом!
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 40

      +19
      Я думаю вы с нетерпением ждете этот вопрос:
      Каково по вашему правильное решение данной проблемы?
      (* RFC 6265 / Пункты 5.1.3, 4.1.2.3 и др*)
        +1
        Обязательное использование $domain аргумента функции setcooke() php.net/manual/ru/function.setcookie.php
          +5
          И какое значение должно быть у этого параметра? Посмотрите пожалуйста на серый текст в моем предыдущем комментарии.
            –1
            должен быть текущий домен. да, RFC. но браузеры, они такие браузеры… В RFC прямо описание этой ошибки, вы правы: «WARNING: Some existing user agents treat an absent Domain
            attribute as if the Domain attribute were present and contained
            the current host name. For example, if example.com returns a Set-
            Cookie header without a Domain attribute, these user agents will
            erroneously send the cookie to www.example.com as well»
              0
              В приведенном вами «warning» говорится о поведениях браузера при отсутствии данного параметра (как раз те самые различия между хромом и ie).
              Мы же с вами обсуждаем уже присутствие параметра Domen и то каким он должен быть, чтобы поддомены не получали куки.
                0
                Да, в этом WARNING по-сути все то, что в этом топике сжато написано.
                Если вопрос в том, что указывать в домене — то ответ простой:
                «domain.com», без ведущей точки впереди.
                  +2
                  Проверьте пожалуйста это, например в Chrome.
                    +6
                    Хорошо. Если не хотите пробовать, то вот вам пример из указанного RFC:
                    The server can alter the default scope of the cookie using the Path
                    and Domain attributes. For example, the server can instruct the user
                    agent to return the cookie to every path and every subdomain of
                    example.com.

                    Set-Cookie: SID=31d4d96e407aad42; Path=/; Domain=example.com
          +11
          В скриншоте wireshark'e foo.bar.com,
          а в тексте статьи про хром foo.com
          а в скриншоте хрома bar.com
          а в скриншоте ie bar.foo.com

          Это я неправильно понял смысл статьи, или автор запутался в foo и bar?
            –1
            Напомнило это :)
              0
              Правильно. По хрому скриншот переделал. Спасибо!
                +3
                Вы толко что сочинили четверостишье :)
                +3
                cookie-неделя на хабре
                  0
                  Вот, кстати. Как Вы думаете, сколько кук для одного домена можно проставить, и что будет, когда это число закончится?
                    0
                    Не больше 4 кило, а потом затираться начнет…
                      +2
                      Все не по RFC реализовано )
                      chrome 180 (после отправки первого запроса без кук их станет уже 150)
                      safari ~2800/LEN(cookie_name+cookie_val)
                      opera 60
                      firefox 149
                      iexplore 49
                  • UFO just landed and posted this here
                    +2
                    причем если поставить куку с адреса www.site.com, то она будет в реквест заголовках на адресе site.com, но надежно стереть ее получится только опять же с www.site.com Надежно, это значит не теоретически, а практически для всех браузеров
                      +18
                      Статью можно сжать до одного предложения: «при установке cookie без указания домена, IE, в отличие от других браузеров, проставляет cookie для всех поддоменов».
                      • UFO just landed and posted this here
                          +1
                          Не совсем понял. Это в каких случаях опасно? Правильно ли я понимаю, что в случае когда все поддомены мои, это не так критично?
                            0
                            Это опасно, так как дает возможность атаковать основной домен с поддоменов. Это не опасно, когда на поддоменах нет уязвимостей.
                              +4
                              Согласно RFC 2011 года поддомены всегда получают куки указанного домена. (Если только сам браузер не пойдет против RFC).
                              Поэтому указанная в топике «опасность» будет даже если указывать домен.
                              Правильней было бы написать, что не указывая домен мы отдаем определение охватываемых доменов на усмотрение браузера.
                              Наличие же заданного домена никак не влияет на поддомены. (В старом RFC и браузерах влияло). Но автор меня игнорирует =)
                                +1
                                Не игнорирую — проверяю. Хром у меня точно ничего не ставит на поддомены.
                                  +2
                                  Вы проверяли на какой домен ставится или проверяли передаются ли куки на поддомены?
                                  0
                                  Все проверил — никто не ставит на поддомены. Вы на чем проверяли?
                                    0
                                    Chromium 18.0.1025.151, Firefox 12.0
                                      +1
                                      Действительно, это так. Спасибо! При указании даже прямого домена, браузер все-равно проставяет на все поддомены. Новый RFC работает именно так. Надо думать…
                                        +1
                                        Браузер не «проставляет на все домены» — это бредовое предположение.

                                        Браузер передаёт куки с родительского домена на запросы к поддоменам.

                                        Это нормально и это сделано специально.
                                0
                                Стоит тогда наверное упомянуть и про куки сессии, по умолчанию при открытии сессии поставятся куки без всяких параметров.
                                Нужно использовать session_set_cookie_params
                                  +1
                                  Если честно — вообще не понял смысла поста. Рассказывается о том, что и так понятно.
                                  Даже если программер укажет создание куки для отдельного домена — ничего не мешает мне создать куки для другого домена.
                                  Единственная защита — это фильтрация куков, а не думать, что куки можно получить только от сервера и их нельзя изменить или создать свои.
                                    –1
                                    Единственная защита — это фильтрация куков

                                    What? o_O
                                      0
                                      Проверять входящие данные от клиента, а не как написал автор получать XSS.
                                        +1
                                        Топик о том, что если ваш сайт ставит куку без указания домена, то зайдя на соседний домен (не ваш) и отыскав XSS можно увести у пользователя куку (и значит учетку) вашего «секьюрного» сайта.
                                          0
                                          Не совсем
                                          > Проверим Internet Explorer. Так как красивых плагинов для просмотра COOKIE
                                          > для него я не знаю, проставим куки для домена foo.com
                                          > и выведем document.cookie с домена bar.foo.com
                                          Если foo.com ваш, то и под-домен bar.foo.com, видимо, тоже ваш.

                                          Другое дело, если б вы куки выставляли с abc.foo.com, а получали на xyz.foo.com — но такого не происходит.
                                    0
                                    Что означает слово SOP в тегах?
                                    Это слово не встречается в тексте и по этому тегу нет других статей.
                                    0
                                    На мой взгляд, RFC 2109и RFC 2965 написаны более понятным языком, по крайней мере я так и не нашел в RFC 6265 критериев установки атрибутов.
                                    Если кто-то более более внимательно прочитал стандарт прошу разъясните эту ситуацию.
                                      0
                                      Так а какая версия IE?

                                    Only users with full accounts can post comments. Log in, please.