XSS и Same Origin Policy

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

Прошлый пост «Как обойти запрет на 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

access_restricted_load

Как видите, 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, то увидим такую картину.

getscript

Внутри заголовка страницы появился новый тег 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 и Яндекс.Карты.

Может быть, существуют и другие варианты. Если есть идеи – пишите в комментариях, обсудим 😉