Прошлый пост «Как обойти запрет на XSS» вызвал довольно интересное обсуждение. Я сначала пробовал сразу отвечать на комментарии, но потом понял, что развернутые ответы больше напоминают статьи, а краткие – только всё запутывают.
И, что хуже всего, я почувствовал, что не могу внятно ответить на часть комментариев, а значит нужно подробнее разобраться в ситуации 🙂
В общем, я провел небольшую серию экспериментов и хочу рассказать о результатах.
На всяких случай напомню, что в прошлый раз речь шла об использовании XSS (cross site scripting), т.е. межсайтовых запросах.
В первую очередь я решил проверить, как работают самые простые запросы. Для этого создал простенькую тестовую страничку на локальном сервере (localhost) и подключил библиотеку jQuery.
1) Метод load.
$().load("http://api.wipmania.com/wip.js", {}, function() { alert('OK!'); });
Этот скрипт пытается получить содержимое файла wip.js
с сервера api.wipmania.com
.
В результате получаем ошибку Access to restricted URI denied
Как видите, FireFox заблокировал этот запрос.
2) Попробовал использовать getJSON – та же самая ошибка
$.getJSON("http://api.wipmania.com/wip.js", {}, function() { alert('OK!'); });
На данном этапе всё работает именно так, как и должно. Браузер придерживается Same Origin Policy, т.е. политики безопасности, которая запрещает с помощью JavaScript получать данные из источника отличного от того, с которого был загружен сам скрипт.
В данном случае это означает, что раз скрипт загружен с localhost
, то получить данные с api.wipmania.com
он не может.
Продолжаю эксперименты.
3) В этот я раз решил посмотреть, как работает метод getScript. Дело в том, что Big_Shark привел пример рабочего скрипта, который получает данные с помощью XSS.
$.getScript("http://api.wipmania.com/wip.js", function() { alert(WIPlocation.address.country); });
Тут всё гораздо интереснее. Приведенный скрипт отлично работает и на первый взгляд складывается впечатление, что Same Origin Policy не применяется.
Но это не так. Просто метод getScript
выполняет несколько дополнительных операций. В этом легко убедиться, если с помощью отладчика (я использовал Firebug) остановить выполнение скрипта на 3-ей строке.
Если в этот момент переключиться на вкладку HTML, то увидим такую картину.
Внутри заголовка страницы появился новый тег script
с данными от wipmania
. Обратите внимание, на его атрибут src
. Т.е. получается, что из этого скрипта можно отправлять запросы на сервер api.wipmania.com
и при этом будет соблюдаться Same Origin Policy.
Примечание. В данном примере отправлять запросы из этого скрипта нет смысла, т.к. он сам по себе содержит все необходимые данные.
После завершения работы функции jQuery этот тег удаляет.
4) В последнем эксперименте я решил использовать JSONP.
Подробно о его результатах и вообще об этом формате я напишу в одном из следующих постов. Сейчас только расскажу о тех моментах, которые касаются XSS.
В принципе, ситуация аналогична предыдущему примеру. jQuery использует дополнительный тег script
с помощью которого и обеспечивается доступ к другому домену.
Кстати, формат очень удобный, особенно учитывая то, что он поддерживается многими JavaScript библиотеками.
Вам нужно только отправить запрос и написать обработчик (функцию), который получит ответ сервера, а всё остальное библиотека сделает за вас. Создаст тег script
с соответствующим атрибутом src
, отследит момент получения данных, вызовет ваш обработчик и удалит script
.
Таким образом, получить данные с другого хоста можно следующими способами.
1) С помощью прокси (метод описан в статье «Как обойти запрет на XSS» (https://www.simplecoding.org/kak-obojti-zapret-na-xss.html)).
2) С помощью Flash. Сам я не пробовал, но надежные источники утверждают, что этот так. По идее должно работать и для Silverlight.
3) С помощью тега script. Если вам нужно обращаться к какому-нибудь серверу, то придется добавить скрипт с этого сервера на свою страницу. Т.е. всё будет работать в рамках Same Origin Policy. Кстати, именно так работают Google Maps и Яндекс.Карты.
Может быть, существуют и другие варианты. Если есть идеи – пишите в комментариях, обсудим 😉