Не­дав­но я обна­ружил новую для себя раз­новид­ность XSS-уяз­вимос­тей — DOM XSS с помощью Web Messaging. Перечи­тав мно­жес­тво стра­ниц докумен­тации, я решил соз­дать еди­ный матери­ал по экс­плу­ата­ции XSS через эту тех­нологию. Я опи­шу здесь наибо­лее рас­простра­нен­ные недос­татки безопас­ности и методы их экс­плу­ата­ции.
 

Что такое DOM?

DOM (Document Object Model) — не завися­щий от плат­формы и язы­ка прог­рам­мный интерфейс, который поз­воля­ет прог­раммам и скрип­там получать дос­туп к содер­жимому HTML-, XHTML-, XML-докумен­тов, а так­же изме­нять их кон­тент (содер­жимое, струк­туру, офор­мле­ние). DOM-based-уяз­вимос­ти воз­ника­ют, ког­да веб‑сайт содер­жит сце­нарий, который при­нима­ет кон­тро­лиру­емое зло­умыш­ленни­ком зна­чение и переда­ет его небезо­пас­ной фун­кции, называ­емой sink. Один из видов DOM-based-уяз­вимос­тей — DOM-based XSS. Уяз­вимос­ти это­го типа воз­ника­ют, ког­да JavaScript получа­ет дан­ные от поль­зовате­ля и переда­ет их в sink, обла­дающий воз­можностью динами­чес­кого исполне­ния кода, нап­ример eval(), document.write() или innerHTML.

 

Как эксплуатируются DOM-based XSS?

На­ибо­лее популяр­ный источник DOM XSS — URL-стра­ницы. Дос­туп к это­му зна­чению осу­щест­вля­ется с помощью JavaScript через объ­ект window.location. Затем URL обра­баты­вает­ся внут­ри сущес­тву­юще­го на стра­нице легитим­ного скрип­та. В этом слу­чае ата­кующий может соз­дать ссыл­ку с вре­донос­ной наг­рузкой, что­бы затем отпра­вить ее жер­тве. Ког­да жер­тва перей­дет по ссыл­ке, исходный скрипт на стра­нице, исполь­зующий объ­ект window.location, зап­росит адрес текущей стра­ницы и исполнит наг­рузку, которая содер­жится в URL. Вот прос­тей­ший при­мер этой уяз­вимос­ти.

<body>
<script>document.write(location.href);</script>
</body>

При получе­нии такой стра­ницы бра­узер авто­мати­чес­ки выпол­нит скрипт и запишет в тело стра­ницы (document.write) стро­ку, взяв ее зна­чение из location.href (пол­ного адре­са стра­ницы). Одна­ко поль­зователь кон­тро­лиру­ет зна­чение location.href и может помес­тить в него про­изволь­ную стро­ку. Поэто­му для экс­плу­ата­ции XSS-уяз­вимос­ти дос­таточ­но сфор­мировать сле­дующую ссыл­ку, и при ее откры­тии в бра­узе­ре выпол­нится вре­донос­ный скрипт.

http://website.com/index.html#<script>alert(1)</script>
 

Механизмы безопасности кросс-доменного взаимодействия

Пред­ста­вим, что у нас есть стра­ница сай­та, который мы раз­работа­ли. Мы помеща­ем на нее эле­мент <iframe> и ука­зыва­ем в качес­тве его источни­ка про­изволь­ный сайт.

Принципиальная схема iframe
Прин­ципи­аль­ная схе­ма iframe

Ес­ли бы не было механиз­мов безопас­ности, обмен дан­ными меж­ду эле­мен­тами родитель­ской веб‑стра­ницы и веб‑стра­ницы, которая отоб­ража­ется в <iframe>, мог бы быть кри­тичес­ки опас­ным для поль­зователь­ских дан­ных. Любой скрипт, находя­щий­ся на родитель­ской стра­нице, мог бы получить дос­туп к любым дан­ным, раз­мещен­ным внут­ри <iframe>.

Да­вай рас­смот­рим на при­мере. Зло­умыш­ленник помеща­ет на сво­ей стра­нице <iframe> с адре­сом интернет‑бан­ка, в котором поль­зователь был авто­ризо­ван ранее. Затем каким‑то обра­зом замани­вает жер­тву на свою стра­ницу. В резуль­тате зло­умыш­ленник может получить дос­туп к любым поль­зователь­ским дан­ным лич­ного кабине­та интернет‑бан­ка жер­твы. Что­бы не допус­тить подоб­ного, были соз­даны два механиз­ма защиты:

  1. Same Origin Policy (SOP), «полити­ка оди­нако­вого источни­ка», — пре­дот­вра­щает кросс‑домен­ные ата­ки, бло­кируя чте­ние заг­ружа­емых ресур­сов из дру­гого источни­ка. Источник иден­тифици­рует­ся по сле­дующей трой­ке парамет­ров: схе­ма, пол­ное имя хос­та и порт. Ког­да хотя бы один из парамет­ров у источни­ков не сов­пада­ет, обмен дан­ными меж­ду ресур­сами зап­реща­ется. Нап­ример, если стра­ница по адре­су http://example.com/index.html поп­робу­ет отоб­разить дан­ные из источни­ка https://example.com/, то это дей­ствие будет зап­рещено, так как у источни­ков не сов­пада­ет про­токол.

    Same Origin Policy
    Same Origin Policy
  2. Cross-Origin Resource Sharing. Огра­ниче­ния полити­ки оди­нако­вых источни­ков ока­зались слиш­ком жес­тки­ми. Поэто­му для более тон­кой нас­трой­ки дос­тупа к ресур­сам соз­дали «механизм сов­мес­тно­го исполь­зования ресур­сов раз­ными источни­ками» — CORS. Он рег­ламен­тиру­ет три катего­рии сетево­го вза­имо­дей­ствия:

  • за­пись из раз­ных источни­ков. Эта катего­рия рег­ламен­тиру­ет пере­адре­сации, отправ­ки форм и перехо­ды по ссыл­кам. По умол­чанию все эти дей­ствия раз­решены;
  • встав­ка из раз­ных источни­ков. Эта катего­рия рег­ламен­тиру­ет эле­мен­ты, заг­ружа­емые пос­редс­твом тегов <link>, <script>, <img>, <video>, <audio>, <iframe> и дру­гих. По умол­чанию все они раз­решены, одна­ко работос­пособ­ность тега <iframe> может быть допол­нитель­но огра­ниче­на с помощью заголов­ка X-Frame-Options;
  • счи­тыва­ние из раз­ных источни­ков. Эта катего­рия рег­ламен­тиру­ет эле­мен­ты, заг­ружа­емые через AJAX и fetch. По умол­чанию эти воз­можнос­ти заб­локиро­ваны.
 

Web Messaging API

Window.postMessage() — это метод, поз­воля­ющий переда­вать дан­ные меж­ду докумен­тами, которые заг­ружены в раз­ных окнах или фрей­мах, в том чис­ле меж­ду докумен­тами, получен­ными с раз­ных доменов. Если на сай­те кор­рек­тно нас­тро­ены механиз­мы безопас­ности (SOP и CORS), исполь­зование postMessage будет единс­твен­ным дос­тупным спо­собом переда­чи дан­ных меж­ду докумен­тами на раз­ных доменах. Зап­росы, соз­данные с помощью про­чих методов (как, нап­ример, XMLHttpRequest или Fetch API), будут заб­локиро­ваны в соот­ветс­твии с SOP и CORS.

По­иск информа­ции о тех­нологии postMessages при­вел меня к офи­циаль­ной докумен­тации Mozilla. Обыч­но сце­нари­ям из раз­ных источни­ков раз­решен дос­туп друг к дру­гу тог­да и толь­ко тог­да, ког­да они соот­ветс­тву­ют Same Origin Policy (оди­нако­вая схе­ма, имя хос­та и порт), вклю­чая сце­нарии внут­ри фрей­ма, которые обра­щают­ся к родите­лю фрей­ма. Window.postMessage() пре­дос­тавля­ет кон­тро­лиру­емый механизм для безопас­ного обхо­да это­го огра­ниче­ния. Так­же я нашел в докумен­тации спо­собы обес­печения свя­зи меж­ду родитель­ской стра­ницей и стра­ницей внут­ри фрей­ма. В общем виде дочер­ний <iframe> дол­жен быть под­писан на событие «сооб­щение»:

window.addEventListener("message", (event) => {...}, false);

Здесь message — ожи­даемое сооб­щение.

В таком слу­чае родитель­ская стра­ница может передать дочер­нему фрей­му сооб­щение с помощью такого метода:

postMessage(message, targetOrigin, transfer)

Здесь message — отправ­ляемое сооб­щение, эти дан­ные авто­мати­чес­ки сери­али­зуют­ся для переда­чи в дочер­ний фрейм, а targetOrigin ука­зыва­ет источник родитель­ско­го окна.

В качес­тве targetOrigin допус­кает­ся исполь­зовать звез­дочку, которая ука­зыва­ет на то, что получить сооб­щение может кто угод­но. Либо мож­но ука­зать кон­крет­ный URI, который будет про­верен внут­ри слу­шате­ля в дочер­нем фрей­ме. Если Origin стра­ницы не сов­пада­ет с targetOrigin внут­ри этой фун­кции, событие не будет отправ­лено. Этот механизм обес­печива­ет кон­троль над тем, куда отправ­ляют­ся сооб­щения. Нап­ример, если postMessage исполь­зует­ся для отправ­ки пароля, необ­ходимо, что­бы этот аргу­мент соот­ветс­тво­вал целево­му URI. Это поз­волит пре­дот­вра­тить хищение пароля зло­умыш­ленни­ком через недове­рен­ный ресурс.

 

DOM-based XSS через Web Messaging

Да­вай пос­мотрим, как мож­но исполь­зовать веб‑сооб­щения в качес­тве источни­ка для соз­дания и экс­плу­ата­ции DOM XSS на целевой стра­нице. Если целевая стра­ница обра­баты­вает вхо­дящие сооб­щения небезо­пас­ным обра­зом (нап­ример, невер­но про­веряя источник вхо­дящих сооб­щений), то вызыва­емые слу­шате­лем события потен­циаль­но могут стать при­емни­ками небезо­пас­ной наг­рузки и источни­ком XSS.

Нап­ример, зло­умыш­ленник может помес­тить на сво­ей стра­нице вре­донос­ный <iframe> и исполь­зовать метод postMessage() для переда­чи дан­ных с помощью веб‑сооб­щения уяз­вимому слу­шате­лю событий. В даль­нейшем слу­шатель передаст вре­донос­ную наг­рузку в при­емник на дочер­ней стра­нице.

Это зна­чит, что веб‑сооб­щения могут быть исполь­зованы в качес­тве источни­ка наг­рузки для любого из при­емни­ков дочер­ней веб‑стра­ницы. Резуль­тат экс­плу­ата­ции уяз­вимос­ти зависит от того, как целевой документ обра­баты­вает получен­ные сооб­щения.

Ес­ли целевая стра­ница пол­ностью доверя­ет отпра­вите­лю, не про­веря­ет дан­ные, получен­ные от него, и без иска­жений переда­ет их в при­емник, то эта уяз­вимость поз­волит зло­умыш­ленни­ку совер­шить любые дей­ствия от лица поль­зовате­ля в кон­тек­сте целево­го ресур­са (ском­про­мети­ровать поль­зовате­ля).

Да­вай рас­смот­рим раз­ные вари­анты уяз­вимого кода.

 

Origin Verification отсутствует

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии