Web Messaging — легальный XSS

Еще одной проблемой, решаемой в традиционном вебе с помощью нагромождения различных изящных трюков, в народе поэтично прозванных костылями, является обмен сообщениями между страницами, фреймами, окнами или вкладками браузера, да и вообще взаимодействие скрипта на веб-странице с неким произвольным источником. На произвольном домене. Почему тут возникают сложности? Все дело в ограничениях, которые производители браузеров накладывают по соображениям небезопасности. Действительно, при свободном обмене сообщениями клиент не застрахован от чтения содержимого своего браузера злоумышленницами, ну а об опасности выполнения javaScript, пришедшего с непроверенного сервера, можно и не говорить.

Но, несмотря на все опасности, потребность в такого рода общении в современных веб-приложениях довольно высока, и техническое решение, безопасно осуществляющее такое взаимодействие, давно было востребовано. В конце концов, производители браузеров и смотрители стандартов выработали новую спецификацию — Cross Document Messages, в рамках которой выработан Web Messaging API — средство общения между документами, свободное от междо-менных ограничений. Пользоваться им очень просто, и начнем мы прямо сейчас:

<script>

Window. SostMessage("Hello", "http://remotehost. com"}) </script>

Мы послали сообщение «Hello» скрипту, находящемуся в домене remotehost. com.

Для принятия сообщений следует привязать к событию message функцию обратного вызова:

Window. addEventListener("message", messageHadler, false);

Она получает в качестве аргумента объект события, из которого можно извлечь не только данные, но и их источник, обеспечив таким образом безопасность:

Function messageHadler(e){

If(e. origin == "http://htmotehost"){ alert(e. origin+" "+e. data);

}

}

Разберем небольшой пример. Пусть у нас будет следующая HTML-разметка:

<html>

<meta charset="cp1251" />

<body>

<iframe src="Http://localhost/cdm/frame. html" id="target_frame"></iframe> form id="form1">

<input type="text" id="msg" placeholder="Введите ваше сообщение"/> <input type="submit"/>

</form>

<script>

Var target_win = document. getElementById("target_frame").contentWindow;

Document. getElementById("form1"). onsubmit = function(){ target_win. fostMessage(

Document. get ElementById("msg").value,

"Http://localhost"

);

Return false:

}

</script>

</body>

</html>

Тут, как следует из адреса, и фрейм, и исходная страница расположены на одном домене, а именно на Http://localhost, то есть прямо на машине, где пишутся эти строки. Это сделано для того, чтобы вам было легче воспроизвести все эксперименты. Разумеется, в реальности адреса и домены будут разные.

Теперь код фрейма frame. html:

<html>

<body>

<meta charset="cp1251" />

<div id="test">Сообщения:</div>

<script>

Window. addEventListener("message", postListener, false);

Function postListener(e){

If (event. origin!== "http://localhost"){

Alert("AAAAAAAAAAAAA! Galaxy in danger!");

Return:

Var content = document. getElementById("test");

Content. innerHTML = content. innerHTML+"<br />"+event. origin + ": " + event

. data:

}

</script>

</body>

</html>

Код в фрейме выполняет проверку источника пришедшего сообщения на соответствие доверенному домену и в случае успешной проверки вставляет текст сообщения в тело страницы. Работу всего этого можно увидеть на рис. 87.

Рис. 87. «Общение» с фреймом посредством postMessages

Вопрос, заданный на перлюстрации, вполне закономерен — общение с фреймом идет в одном направлении. Исправим это обстоятельство, ведь окно — источник сообщений — доступно во фрейме через объект event. Дополним код фрейма:

Content. innerHTML = content. innerHTML+"<br />"+event. origin + ": " + event. data; var win = e. source: win. postMessage(

"Сообщение получено тчк целую тчк ваш фрейм",

"Http://localhost"

);

Теперь организуем прием сообщений на странице-источнике:

Window. addEventListener("message", postListener, false); function postListener(e){ alert(e. data);

Рис. 88. Фрейм отвечает

Впрочем, это не единственное предназначение Web Messaging. Этот интерфейс является средством реализации спецификаций WebWorkers и WebSockets (обо всем этом разговор еще впереди) и уже рассмотренного нами Server-Sent Events. В общем, он вполне претендует на роль универсального программного интерфейса для объектов HTML5.

Проверяем — рис. 88. Все работает, мы научились общаться с фреймами.



?

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *