Уязвимости прозрачного проксирования, отмена похорон WebSocket, выдыхаем…

    Прочитав «Веб-сокеты временно отменяются», не смог удержаться и решил ответить.



    Итак, последние новости с фронтов IT. Они шокируют.

    Из-за серьезной незакрытой уязвимости в Adobe Flash от его поддержки отказались все ведущие браузеры. Да, да больше в сети не будет Flash, увы. Об этом заявили все ведущие бабушки, сидящие на скамейке в моем дворе.

    Из-за серьезной незакрытой уязвимости в Internet Explorer всех версий до 9 все пользователи IE отказываются посещать Сеть. Новый кошмар для верстальщиков — больше не нужно поддерживать версии сайта для разных версий IE. Кошмар! Куда девать полученные навыки? Где есть свободное место дворника?

    Из-за серьезной незакрытой уязвимости в Windows все производители браузеров отказываются поддерживать эту платформу. «Да, да, мы переходим на ReactOS», в эксклюзивном интервью подтвердил ведущий разработчик ведущего браузера ведущей фирмы на ведомом рынке.

    Наконец, апофеозом стало заявления руководителя разработки зимних шин в компании Мышлен. «Мы проанализировали 1829783 аварий, произошедших с автомобилями, на которых были установлены наши шины. И пришли к выводу, что на всех из них были круглые колеса. Так как безопасность вождения — это наше все, то мы решили отказаться от круглых колес и переходим на квадратные. „

    Ну пошутили и хватит. Давайте попробуем разобраться.

    Раньше всего, статья Adam Barth озаглавлена “Transparent Proxies: Threat or Menace?». То есть, автор исследует не протокол WebSocket, а «прозрачное проксирование».

    Что это такое? Все просто — если клиент указал прокси явно, то это явный прокси. А если любой запрос браузера (допустим, в каком-то отеле) незаметно перехватывается специальным прокси для фильтрации, то это и есть «прозрачный» прокси.

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

    Мы пока не будем обсуждать это решение с точки зрения «правильности». Предположим, что некоторые прозрачные прокси действительно перенаправят запрос на хост в заголовке Host. Что из этого следует?

    Автор далее ссылается на еще один документ.

    Предположим, что зловредный сайт загрузил в браузер Flash-приложение, которое получило разрешение на использование raw sockets, то есть, попросту говоря, флеш-приложение может использовать TCP/IP соединение с сервером, с которого было загружено. Может прозрачный прокси отличить такое соединение от браузерного? Не может. Если флеш-приложение сформирует и направит корректный HTTP-запрос на сервер через TCP, то прозрачный прокси решит, что этот запрос отправляет браузер. Зловредное флеш-приложение в свой зловредный запрос вставит Host, который укажет на зловредный хост.

    И теперь, если прокси настолько глуп, что пойдет получать ответ к (зловредному) хосту в поле Host, то с этого сервера ему подсунут что угодно, причем прокси будет считать, что ответил ему исходный (хороший) хост (на IP-адрес которого был изначально направлен запрос).

    Получаем две проблемы:

    1. зловредное флеш-приложение теперь может обращаться к любому веб-серверу, а не только к тому, с которого было загружено;

    2. если прокси закэширует ответ, то последующие запросы к хорошему серверу от любого клиента будут получать зловредный закешированный ответ.

    Итак, проблема компроментации кэша прозрачного прокси и нарушения флеш-приложением SOP возникает, если прозрачный прокси перенаправляет запрос к хосту в заголовке Host (вместо использования IP-адреса, на который был отправлен запрос).

    Причем тут Лужков WebSocket? Не при чем. Идем дальше. Заглянем в энциклопедию юных сурков RFC. Нас будет интересовать RFC 1919, который определяет прозрачное проксирование. Читаем:

    4.2.3 DNS requirements

    In transparent proxy configurations, client systems MUST be
    able to resolve server names belonging to remote networks. This
    is critical since the proxy will determine the target server
    from the destination IP address of the packets arriving from
    the client.



    То есть стандарт однозначно утверждает, что надо брать IP адрес запроса, а не из поля Host.

    Опять, вроде бы, WebSocket не виноват. Окей, возвращаемся к исходной статье автора.

    Авторы провели эксперимент. Они раздавали людям рекламный банер, который пытался провернуть подобную схему: отправить HTTP-запрос с «другим» Host. Использовался как флэш, так и Java-приложение. Эксперимент показал, что 2.2% (803 из 36305) запросов использовавших «зловредный» Flash и 3.6% (1212 из 33820) запросов использовавших «зловредный» Java-класс были перенаправлены на Host в заголовке HTTP, а не на IP-адрес.

    Далее, авторы пытаются «обмануть» прокси с использованием протокола WebSocket. Если прозрачный прокси ничего не знает про WebSocket, то клиент может после WebSocket handshake отправить в TCP сообщение вида:

    GET /sensitive-document HTTP/1.1
    Host: victim.com


    Поскольку несчастный прокси ничего не знает про WebSocket, он решит, что это очередной HTTP запрос. Причем он «пойдет» на victim.com и передаст его туда. Эксперимент авторов показал, что так поступили 2.8% прокси (1376 из 49218). Далее, эксперимент по сути повторился.

    Итак, утверждение, что WebSocket небезопасен — неверно.

    Нарушение безопасности возникают из-за того, что прозрачные прокси не знают WebSocket и нарушают RFC 1919.

    Авторы исследования предлагают свое решение: использовать HTTP команду CONNECT для WebSocket. Их эксперимент показал, что _все_ прозрачные прокси «хорошо» отрабатывают CONNECT. Они считают, что внутри будут HTTPS данные и не пытаются их разбирать. Запросы идут на исходный IP.

    Подведем итог.

    Примерно 3% прозрачных прокси рутят HTTP запросы на IP-адреса хоста, указанный в поле Host заголовка запроса. Это нарушение стандарта RFC 1919. Рутить надо на исходный IP-адрес, на который и был отправлен запрос.

    Такое поведение позволяет зловредному Flash-приложению, Java-апплету или скрипту JavaScript обращаться к любым сайтам (нарушение принципа Same Origin Policy) и компроментировать кэш этих прокси.

    Зловредный скрипт JavaScript может навредить только в том случае, если браузер поддерживает WebSockets. Flash-приложение и Java-апплет не нуждаются в поддержке WebSockets браузером, чтобы вредить.

    Переход на команду CONNECT в handshake WebSocket (с некоторыми доработками) позволит «закрыть дыру» в случае WebSocket...

    … НО ИСПОЛЬЗОВАНИЕ ВРЕДОНОСНЫХ FLASH И JAVA ПРИЛОЖЕНИЙ ДЛЯ НАРУШЕНИЯ SOP И КОМПРОМЕНТАЦИИ КЭША ПРОКСИ ОСТАЕТСЯ ВОЗМОЖНЫМ ДО ТЕХ ПОР, ПОКА ПРОЗРАЧНЫЕ ПРОКСИ НАРУШАЮТ RCF 1919.

    Картинка для отвлечения внимания.

    image

    PS

    Забыл добавить. Разработчикам Оперы и FireFox надо саечку за испуг понимать, что следование безопасности должно быть системным, то есть последовательным.

    Если проблема прозрачных прокси их так беспокоит, то следует запретить и Flash, и Java.

    А так это выглядит как дешевый PR-трюк:

    «Посмотрите мы заботимся о безопасности. Мы оставили дырявый Flash в нашем браузере, но зато мы отключили WebSocket и теперь Вы — в безопасности.»

    PSS

    Немного подправил. Надеюсь стало еще ясней…

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 26

      +4
      Да нет же. Прокси идёт по IP-адресу. А вот кэширует по Host. Соответствие при этом не проверяется.
        +4
        ну так это в любом случае проблема прокси-сервера, а не протокола. Или как?
          +3
          Да, насколько я понимаю, это поведение не специфично для web sockets.
          Для обычного сайта можно спастись, используя HTTPS, не в курсе, доступен ли какой-нибудь аналог для web sockets.

          Я, собственно, лишь хотел указать, что автор исходную статью понял неправильно.
            +2
            wss не? уже удалили вместе с сокетами

            ЗЫ скоро в хабре надо будет группировать топики: топик начало, топик опровержние, топик расширенный коммент и тп
              0
              Ну и отдельно топик предсказание будущего Хабра, начинающийся со слов «Скоро на Хабре все топики будут ляляля» или «Скоро Хабр будет ляляляля wikileaks» :)
            +4
            Я начинаю смутно догадываться, что суть описанной проблемы в следующем:

            1) есть ряд прокси серверов, уязвимых для cache poisoning
            2) всунуть свой мусор в кеш не проблема — реализацию любой программист настрочит за пару минут
            3) но сделать это можно только находясь позади прокси. снаружи этот фокус не пройдёт
            4) т.е. для злоумышленнику нужно либо самому сидеть за этим прокси или же подсунуть свою программу-троян кому-нибудь (заставить запустить, использовать уязвимости системы и т.п.)
            5) а вот вебсокеты позволяют это сделать без проблем: достаточно пользователю за уязвимым прокси открыть URL :)

            Поправьте меня, если неправ.
              +4
              ну так и флеш и java позволяют.
              достаточно открыть URL
              или я не прав?
                +2
                флеш и жава — это, все ж таки, плагины.
                и разработчики браузеров не шибко много с ними сделать могут.
                а тут получилось, они сами еще один вектор атаки создают.
                вот и засуетились.
                  +3
                  Ключевая фраза, на которую автору топика нужно обратить внимание.
                  Flash и Java — это сторонние плагины.
                  WebSocket же это часть браузера, за которую отвечают непосредственно разработчики браузера. От сюда и становится понятна их реакция.

                  Но, я согласен с автором в том что, если можно допилить WebSocket, то пусть допиливают.
                    0
                    ну, с таким подходом достаточно сделать кнопочку «отключить WebSockets», и проблема безопасности решена. (типа)
                      0
                      Нет, кнопочку «включить WebSockets», плагины же нужно самостоятельно поставить. Они так и сделали, в FF можно включить их обратно.
            +2
            Нет, все именно так, как я написал.

            There are two common ways a transparent proxy will relay a user’s request to an end destination.

            Approach A: Use the destination IP from the client
            The first involves receiving a request from a client, inspecting the http payload, then forwarding this
            HTTP payload to the ‘destination IP' specified by the client. In this configuration the transparent proxy
            routes requests much like a standard router by basing its routing decisions off of the network layer
            (layer 3).

            Approach B: Inspect application layer data
            The second involves identifying the end destination based on the HTTP payload instead of the client
            destination IP by inspecting the HTTP 'Host' header or request URI. In this configuration the transparent
            proxy is determining IP destinations based on the application protocol (layer 7) instead of IP (layer 3).

            Due to the socket capabilities of browser plug-ins (flash/etc) this second architecture can be exploited
            by an attacker to gain access to any destination accessible by the proxy.

            «Плохой» прокси идет по IP адресу хоста из запроса.
              +5
              Да, я недопонял проблему.

              Итак, есть java, flash и web sockets. Все они используют схему защиты same-origin, т.е. можно обращаться лишь к тому серверу, с которого получен апплет/флэш/скрипт. «Тот же сервер» определяется как «тот же IP», так как сравнение серверов по hostname подвержено DNS rebinding attack (подробности в исходной статье, если нужно — разверну здесь).

              Такое ограничение слишком строго, поэтому есть механизмы повышения привилегий. В частности, если Flash-апплет пытается соединиться с левым сервером, то Flash сначала качает файл правил с этого сервера и позволяет соединение, если сайт, с которого загружен обращающийся скрипт, содержится в списке правил.

              Подобные механизмы расслабления ограничений есть также для XMLHttpRequest и для web sockets. Но для web sockets есть особенность — запрос разрешения на общение идет в рамках того же соединения, по которому потом пойдут данные.

              Пусть пользователь за прозрачным прокси зашел на attacker.com и получил страничку с флешкой. Если прокси определяет IP-адрес сервера исходя из значения заголовка Host, то происходит следующее:
              * флешка запрашивает соединение до attacker.com
              * флеш грузит правила с attacker.com
              * на attacker.com лежат правила, позволяющие соединяться кому угодно и откуда угодно
              * флеш успешно устанавливает соединение до attacker.com
              * теперь через установленное соединение передаем данные, которые выглядят, как начало нового HTTP-запроса, причём с заголовком Host: google.com
              * данные успешно передаются, так как флеш знает, что соединена флешка с attacker.com, а туда можно коннектиться
              * но тупая прозрачная прокси видит начало запроса и подсоединяется к серверу, указанному в заголовке Host

              Итог: смогли загрузить содержимое с совершенно левого сервера.
              А используя метод CONNECT, можно даже заставить прокси открыть RAW connection на указанный хост, так как по команде CONNECT прокси перестает искать HTTP-запросы в потоке данных.

              Это описана атака на прокси, использующие заголовок Host для маршрутизации.

              Но некоторые прокси, использующие IP адрес, также уязвимы! Это как раз то, про что я писал в самом первом комментарии.
              Открываем соединение до своего сервера attacker.com, это либо разрешено по умолчанию (Java), либо можно разрешить с помощью файла правил (SWF). Затем отправляем запрос, но указывает Host: google.com. Если проки кеширует запросы по заголовку Host, то содержимое, загруженное с attacker.com, будет помечено как загруженное с google.com и его получат следующие клиенты прокси.
              Если наполнить таким образом вредоносными скриптами кэш для google-analytics, то потом из кэша его получат очень многие, так как google analytics используется на 57% страниц!

              Причем здесь web sockets? Да собственно, они позволяют сделать то же самое — передать произвольные данные, которые прокси воспримет как начало нового соединения.

              Итог: не все прокси, которые используют IP-адрес — хорошие.
                0
                Что-то я увлекся и перепечатал половину статьи :-) Так что читайте только итог.
            0
            Все правильно сказал [x]
            • UFO just landed and posted this here
                –1
                Я ничего не понял из вашего объяснения:
                И теперь, если прокси настолько глуп, что пойдет получать ответ к (зловредному) хосту в поле Host, то с этого сервера ему подсунут что угодно, причем прокси будет считать, что ответил ему исходный (хороший) хост.
                «исходный (хороший) хост» — это что? Я вижу тут один хост, который запрошен, а какой считается исходным?
                В чем опасность того, что клиент отправит host: evil.com, на ip-адрес сайта good.com? Прокси переведет запрос в соответствии с заголовком host на ip-адрес evil.com. Получится обчный запрос к evil.com, а при обращении к good.com будет выдаваться хороший ответ.

                Другое дело, что если все будет наоборот:
                Клиент пошлет на IP-адрес evil.com запрос с host: good.com и evil.com вернет ему ответ, который закешируется для хоста good.com (такой хост был указан при запросе).
                  +1
                  Запрос клиент направляет на некий IP. Это IP адрес «правильного» сервера.
                  Внутри запроса прописан в Host «неправильный» сервер.
                  Глупый прокси отправляет запрос на «неправильный» сервер. И при это считает, что его исполнил «правильный» сервер.

                  И т.д.
                  0
                  После прочтения статьи почему то вспомнились две фразы — «вот на эти 2% я и живу» и «ложечки нашлись но осадочек остался»
                    +4
                    Ну наконец-то первый разумный комментарий на эту тему, а то уже сам писать собирался :)
                    Действуют прямо как белки-истерички: «а, смотрите, это проки, ааа, это уязвимость!»
                      +2
                      Вообще, иногда мне кажется, что прокси — это такой узаконенный man-in-the-middle. Просто по определению. Человек, который перехватывает ваш трафик. Поэтому нужно быть морально готовым к тому, что у него может оказаться кривое ПО.
                        +1
                        Более того, в некоторых злобных местах единственная возможность доступа к https ресурсам — через т.н. терминирующий https прокси злого (или просто слишком доброго) дяди. :)
                        0
                        Если проблема прозрачных прокси их так беспокоит, то следует запретить и Flash, и Java

                        Если Flash и Java были бы сырыми черновиками будущего стандарта, а не технологиями, используемыми в течении многих лет огромным количеством сайтов и пользователей, то отключили бы и Flash с Java.
                          0
                          Спасибо, что растолковали. Сразу подозревал, что не в этом дело :)
                            +2
                            К слову, веб-сокеты никто не хоронил ;)

                            Разработчики FF и Opera сказали, что все вернут, как только допилят протокол. А сами веб-сокеты в браузере не выпиливают, а отключают. Насколько я понимаю, их можно вручную включить для продолжения экспериментов.
                              0
                              насколько я понимаю, типичная связка squid + iptables подвержена этой проблеме, т.к. squid не лазит в ядро за исходным IP-адресом назначения. Или лазит?

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