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

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

Но, несмотря на все опасности, потребность в такого рода общении в современных веб-приложениях довольно высока, и техническое решение, безопасно осуществляющее такое взаимодействие, давно было востребовано. В конце концов, производители браузеров и смотрители стандартов выработали новую спецификацию — 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 не будет опубликован. Обязательные поля помечены *