Как обойти запрет на XSS

Владимир | | Ajax, htaccess, HTML, PHP, Web разработка.

apache mod_proxy

Думаю, ни для кого не секрет, что разработчики браузеров стараются сделать серфинг в интернете максимально безопасным. Цель, конечно, прекрасная, но достигается она обычно за счет введения различного рода ограничений, которые усложняют жизнь не только мошенникам.

Приведу небольшой пример. Недавно я рассказывал об использовании Яндекс.Карт и сервиса IPLoc.

Для получения данных от IPLoc пришлось использовать PHP, хотя, как совершенно справедливо заметил Big_Shark, было бы гораздо удобнее отправить этот запрос с помощью JavaScript. Но кросс-доменный JavaScript запрещен политиками безопасности браузеров.

Тем не менее, мне стало интересно, можно ли обойти это ограничения без использования серверных скриптов (PHP). И решение, конечно, нашлось 😉 Правда, оно имеет свои недостатки, но об этом чуть ниже.

Примечание. По каким-то причинам сервис IPLoc на момент написания этой статьи недоступен. Но есть альтернативные варианты – например, WIPmania.com (), который имеет очень похожий API.

Для начала рассмотрим, как происходит обработка запроса и формирование страницы с использованием PHP.

xss_php

Как видите, серверный скрипт должен отправить запрос сервису WIPmania, получить от него ответ, сформировать страницу и вернуть её браузеру.

Гораздо интереснее было бы отправить AJAX запрос сервису WIPmania и показать его ответ на странице. При этом необходимость в использовании PHP отпала бы.

Но, как я уже говорил, AJAX запрос может быть отправлен только тому серверу, с которого был загружен скрипт. Т.к. изменить поведение браузера мы не можем, то нужно, чтобы наш сервер перенаправил запрос на нужный ресурс (в данном примере WIPmania).

Если в качестве web сервера используется Apache, то для решения этой задачи можно использовать mod_proxy.

Из названия можно догадаться, что этот модуль позволяет использовать Apache в качестве прокси сервера.

Сразу хочу обратить ваше внимание на возможную угрозу безопасности. Нужно максимально ограничить возможность использования прокси. Например, в данном случае, можно разрешить доступ через него только к одному сайту – WIPmania.

На следующей диаграмме показан порядок обработки запросов в этом случае.

xss_mod_proxy

Как видите, в этом случае ajax запрос отправляется браузером web серверу, который получает необходимые данные от WIPmania.

Теперь посмотрим как это реализовать.

1) Включаем mod_proxy. Для этого в конфиге apache (httpd.conf) удаляем комментарии перед строками.

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

2) Сразу же запрещаем использовать apache в качестве обычного прокси сервера (forward proxy).

ProxyRequests Off

Вообще-то эта опция включена по-умолчанию, но перестраховка не повредит.

3) Указываем куда нужно отправить запрос. Допустим, нам нужно, чтобы в ответ на все запросы вида http://simplecoding.org/wipmania... сервер возвращал соответствующий ответ от сервиса WIPmania.

Создаем в корне сайта файл .htaccess со следующим содержимым.

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wipmania(.*) http://api.wipmania.com/$1 [P]
</IfModule>

Наибольший интерес здесь представляет 4-ая строка. Во всех запросах, в которых после адреса блога идет слово wipmania, мы первую часть заменяем на http://api.wipmania.com/. Оставшуюся часть запроса оставляем без изменений (нужно для передачи параметров).

Сформированный запрос отправляется через прокси (флаг [P]) серверу api.wipmania.com.

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

Так что этот метод будет 100% работать не зависимо от версии браузера и его настроек безопасности (вариант с запретом доступа в интернет вообще я не рассматриваю).

Теперь о недостатках.

Главный минус – нужен доступ к конфигу апача. Т.е. shared хостинг отпадает.

К тому же возрастает нагрузка на сервер, т.к. все запросы идут через него.

И, конечно, скорость загрузки данных будет зависеть от скорости сервиса с которым вы работаете. Например, тот же IPLoc сейчас просто недоступен (надеюсь, это временно).

Но есть и положительный момент.

Если вы можете реализовать весь функционал с помощью сторонних сервисов и JavaScript, то вам не нужна поддержка PHP (или другого языка).

Как видите, обойти запрет на XSS совсем не сложно 😉 Если у вас возникли вопросы, пишите, постараюсь ответить.

Небольшое объявление.

HighLoad-проекту требуется Senior PHP Developer

На проект fotostrana.ru требуется сильный PHP-разработчик:

* Опыт веб-разработки от трех лет;
* Профессиональное владение web-технологиями: PHP 5.0 + MySQL 5.0 + JS + AJAX и инструментами;
* Опыт работы с высоконагрузочными (highload) проектами;
* Участие в создании посещаемых проектов;
* Умение работать самостоятельно, быстро и на результат;
* Владение Zend Framework.

Работа в г.Санкт-Петербург. Подробнее на http://job.fotostrana.ru

  • Идея интересная.

    То, что к API нельзя достучаться прямым ajax запросом — недоработка API. Насколько я помню JSONP создан именно для таких потребностей… Нужно только в API предусмотреть возможность его использования.

    • К сожалению, ситуация немного сложнее чем просто «недоработка API». Кросс-доменные запросы (с использованием JSONP или без него) можно реализовать если сервис предоставляет свой JS код. Например, так делают Google Maps и Яндекс.Карты.
      Т.е. вы вставляете на страницу их скрипт, через который и происходит работа с сервисом. Только по-сути эти запросы не кросс-доменные, т.к. их скрипты обращаются к доменам с которых они были загружены.
      И тут возникает проблема безопасности. Если Google и Яндексу доверять можно, то выполнять на своем сайте код малоизвестных разработчиков очень не хочется.

      IPLoc и WIPmania не предоставляют своих JS скриптов. Вы просто отправляете запрос на указанный адрес, а в ответ получаете текстовую строку, которую можете обрабатывать так как сочтете нужным.

  • Идея интересная.

    То, что к API нельзя достучаться прямым ajax запросом — недоработка API. Насколько я помню JSONP создан именно для таких потребностей… Нужно только в API предусмотреть возможность его использования.

    • К сожалению, ситуация немного сложнее чем просто «недоработка API». Кросс-доменные запросы (с использованием JSONP или без него) можно реализовать если сервис предоставляет свой JS код. Например, так делают Google Maps и Яндекс.Карты.
      Т.е. вы вставляете на страницу их скрипт, через который и происходит работа с сервисом. Только по-сути эти запросы не кросс-доменные, т.к. их скрипты обращаются к доменам с которых они были загружены.
      И тут возникает проблема безопасности. Если Google и Яндексу доверять можно, то выполнять на своем сайте код малоизвестных разработчиков очень не хочется.

      IPLoc и WIPmania не предоставляют своих JS скриптов. Вы просто отправляете запрос на указанный адрес, а в ответ получаете текстовую строку, которую можете обрабатывать так как сочтете нужным.

  • В большинстве браузеров в ближайшее время повится возможноть делать ajax запросы на другие домены. А так способ действительно неплох.

    • А можно ссылку на источник? Хочется подробнее почитать на эту тему.

  • В большинстве браузеров в ближайшее время повится возможноть делать ajax запросы на другие домены. А так способ действительно неплох.

    • А можно ссылку на источник? Хочется подробнее почитать на эту тему.

  • Очень интересно! Спасибо за полезную информацию.

  • Очень интересно! Спасибо за полезную информацию.

  • хоть у этого метода и хватает недостатков но тем не менее он может пригодиться, спасибо

  • хоть у этого метода и хватает недостатков но тем не менее он может пригодиться, спасибо

  • Для таких случаев на WIPmania предусмотрен небольшой JavaScript, который можно вставить в свою страничку и в браузере получить такой объект(совместимый с объектом гугла):
    WIPlocation = {«latitude»:»51.0993",»longitude»:»10.4537",»zoom»:5,»address»:{«city»:»-«,»country»:»Germany»,»country_code»:»DE»,»region»:»-«}};
    Здесь все подробней:
    http://www.wipmania.com/ru/blog/google-geolocation-api/

    • И сразу возникает вопрос: откуда берутся широта и долгота? В базе их нет.

      • Эти данные используются на картах как здесь
        http://www.wipmania.com/ru/map/UA/
        т.к. у нас базы только по странам, то приминение таких координат(где указан центр страны) имеет смысл только для показа всей страны на гугл мапсе. Все остальные параметры сделаны пустыми для сохранения совместимости с гугловым объектом.

  • Для таких случаев на WIPmania предусмотрен небольшой JavaScript, который можно вставить в свою страничку и в браузере получить такой объект(совместимый с объектом гугла):
    WIPlocation = {«latitude»:»51.0993",»longitude»:»10.4537",»zoom»:5,»address»:{«city»:»-«,»country»:»Germany»,»country_code»:»DE»,»region»:»-«}};
    Здесь все подробней:
    http://www.wipmania.com/ru/blog/google-geolocation-api/

    • И сразу возникает вопрос: откуда берутся широта и долгота? В базе их нет.

      • Эти данные используются на картах как здесь
        http://www.wipmania.com/ru/map/UA/
        т.к. у нас базы только по странам, то приминение таких координат(где указан центр страны) имеет смысл только для показа всей страны на гугл мапсе. Все остальные параметры сделаны пустыми для сохранения совместимости с гугловым объектом.

  • Pingback: Linkdump #6 | CTAPbIu_MABP's BLOG()

  • Pingback: Cross Site Scripting » Blog Archive » Как обойти запрет на Xss()

  • Big_Shark

    Хм по мне так вы через чур все только усложнили.
    Барузеры нормально передают информацию через JSON по средством библиотеки jQuery
    Вот тому пример
    http://docs.jquery.com/Ajax/jQuery.getJSON#urldatacallback
    Также скорее всего не один нормальный браузер не будет делать столь строгие правила для предотвращения XSS атак так как тогда и простую загрузку яваскрипта с другого домена необходимо будет закрыть как еще более опасную.
    В результате чего мы больше никогда не cможем использовать неодин JS API.
    Еще 1 пример загрузки скриптов через getJSON в jQuery http://code.google.com/apis/ajax/playground/?exp=feeds#jquery
    Я считаю что если такие монстры как гугл используют загрузку скриптов с других доменов и не бояться что их прижмут разработчики браузеров то и нам не стоит.
    Не вижу особой разницы между этим способом и способом описанным ранее и там и там задействуется наш сервер на запрос к стороннему ресурсу.

    • Big_Shark

      Вот пример ( http://stoyki.avtorazborka.ru/test/ ) скрипта который забирает данные с http://api.wipmania.com/wip.js и выводит на экран.
      Если у кого не показывается пишите будем смотреть почему.
      Очень слабое api на мой взгляд у wipmania хотя возможно я просто сильно не углублялся в его изучения.

      Сейчас пишу 2 версию которая будет забирать данные через JSON

      • Big_Shark

        2 версия провалилась.
        Так как по запросу http://api.wipmania.com/wip.js он возвращает объект а не данные вида JSON

      • хм…чем апи слабое? главная функция — определение правильной страны по IP.
        предложите что еще сделать и в каком виде хотелось бы. я пока не вижу для чего может понадобиться в других видах, например в JSON

        • Big_Shark

          А как же город?
          а как же возможность получить информацию о любом ip а не только о ip запросившего скрипт пользователя?
          Да те же часовые пояса можно было бы прикрутить к api и стало бы уже по лучше.
          Много всего можно сделать и придумать было бы желания.

        • чем апи слабое?

          Нужна поддержка JSONP 🙂 Как раз сочиняю пост на эту тему.

  • Big_Shark

    Хм по мне так вы через чур все только усложнили.
    Барузеры нормально передают информацию через JSON по средством библиотеки jQuery
    Вот тому пример
    http://docs.jquery.com/Ajax/jQuery.getJSON#urldatacallback
    Также скорее всего не один нормальный браузер не будет делать столь строгие правила для предотвращения XSS атак так как тогда и простую загрузку яваскрипта с другого домена необходимо будет закрыть как еще более опасную.
    В результате чего мы больше никогда не cможем использовать неодин JS API.
    Еще 1 пример загрузки скриптов через getJSON в jQuery http://code.google.com/apis/ajax/playground/?exp=feeds#jquery
    Я считаю что если такие монстры как гугл используют загрузку скриптов с других доменов и не бояться что их прижмут разработчики браузеров то и нам не стоит.
    Не вижу особой разницы между этим способом и способом описанным ранее и там и там задействуется наш сервер на запрос к стороннему ресурсу.

    • Big_Shark

      Вот пример ( http://stoyki.avtorazborka.ru/test/ ) скрипта который забирает данные с http://api.wipmania.com/wip.js и выводит на экран.
      Если у кого не показывается пишите будем смотреть почему.
      Очень слабое api на мой взгляд у wipmania хотя возможно я просто сильно не углублялся в его изучения.

      Сейчас пишу 2 версию которая будет забирать данные через JSON

      • Big_Shark

        2 версия провалилась.
        Так как по запросу http://api.wipmania.com/wip.js он возвращает объект а не данные вида JSON

      • хм…чем апи слабое? главная функция — определение правильной страны по IP.
        предложите что еще сделать и в каком виде хотелось бы. я пока не вижу для чего может понадобиться в других видах, например в JSON

        • Big_Shark

          А как же город?
          а как же возможность получить информацию о любом ip а не только о ip запросившего скрипт пользователя?
          Да те же часовые пояса можно было бы прикрутить к api и стало бы уже по лучше.
          Много всего можно сделать и придумать было бы желания.

        • чем апи слабое?

          Нужна поддержка JSONP 🙂 Как раз сочиняю пост на эту тему.

  • этим постом вы решили облегчить жизнь мошенникам?

  • этим постом вы решили облегчить жизнь мошенникам?

  • Big_Shark

    2Бильтерьер
    Советую вникнуть в суть прежде чем писать комментарии.

  • Big_Shark

    2Бильтерьер
    Советую вникнуть в суть прежде чем писать комментарии.

  • Подробно ответить в комментариях у меня не получилось. Поэтому пришлось написать отдельный пост 🙂 Предлагаю перенести обсуждение туда.

    2 Бильтерьер
    Основная задача мошенника — вставить свой код на чужой сайт. В этой статье речь идет о ситуации когда разработчику сайта нужно получать данные с других доменов, которым он доверяет. Поэтому вряд ли эта статья очень поможет мошенникам 😉

  • Подробно ответить в комментариях у меня не получилось. Поэтому пришлось написать отдельный пост 🙂 Предлагаю перенести обсуждение туда.

    2 Бильтерьер
    Основная задача мошенника — вставить свой код на чужой сайт. В этой статье речь идет о ситуации когда разработчику сайта нужно получать данные с других доменов, которым он доверяет. Поэтому вряд ли эта статья очень поможет мошенникам 😉

  • Pingback: Как показать на Google Maps объекты, находящиеся в заданной области | Pr.ogmaster()