Атрибут песочницы IFRAME блокирует вызовы AJAX

У меня есть приложение (http://localhost/MyApp), где некоторые части отображаются через IFRAMES. Эти iframed части не имеют отношения к остальной части приложения DOM, поэтому я применил атрибут sandbox.

IFRAME объявляется следующим образом:

<iframe src="/MyApp/en/html/action?id=1" sandbox="allow-forms allow-scripts" seamless="seamless"></iframe>

На iframed-странице есть кнопка, которая вызывает вызов AJAX для одного и того же веб-приложения, но вместо того, чтобы HTTP GET, браузер выдает HTTP OPTIONS, который отображается как Cancelled, и возникает ошибка:

XMLHttpRequest cannot load http://localhost/MyApp/en/data/action?id=1. Cannot make any requests from null.
Ajax State 0 Error: HTTP 0 

Если я добавлю атрибут allow-same-origin в атрибут sandbox, он работает. Что касается я читал здесь, это не предполагалось для воздействия на вызовы AJAX.

Почему это происходит? Рассматривает ли путь /MyApp/en/html/action как начало всей IFRAME и блокирует запрос на предыдущие уровни?

Приветствия.

Ответ 1

Причина, по которой это влияет на Ajax, заключается в том, что Ajax управляется правилами Правила одинаковой исходной политики, и когда вы вставляете их в песочницу, вы эффективно сообщаете браузеру о том, t20 > содержимое, как если бы оно происходило из другого источника. Цитирование той же статьи :

  • Уникальная обработка происхождения. Все содержимое обрабатывается по уникальному происхождению. Содержимое не может проходить через DOM или читать информацию cookie.

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

Встраиваемый контент разрешен только для отображения информации. Никакие другие действия не могут быть выполнены внутри IFRAME, которые могут поставить под угрозу хостинг-сайт или воспользоваться доверием пользователей.

Другими словами, если вы опускаете allow-same-origin в атрибуте sandbox, он будет рассматривать изолированную страницу как принадлежащую другому домену (на самом деле она будет относиться как к источнику null). Так как нет смысла делать запросы Ajax на null, изолированные страницы не могут вообще делать вызовы Ajax (если разрешить их использовать localhost, они будут неотличимы от вызовов с родительской страницы, нанеся поражение цели песочницы).

Дополнительная информация

Если вы попытаетесь сделать вызов Ajax в другом домене, он, очевидно, потерпит неудачу:

<script src="http://code.jquery.com/jquery.min.js"></script>
<script>
    console.log(location.host);
    $.post('https://google.com/',{},function() { });
</script>

Однако , как он будет работать, будет зависеть от используемого атрибута песочницы. Если вы вставляете страницу выше в iframe с allow-same-origin, она выведет ее на консоль:

localhost
XMLHttpRequest cannot load https://google.com/. Origin http://localhost is not allowed by Access-Control-Allow-Origin.

... и если вы вставляете его без allow-same-origin:

localhost
XMLHttpRequest cannot load https://google.com/. Cannot make any requests from null.

Обратите внимание, что, хотя оба сообщены location.host как localhost, считается, что начало было http://localhost, а другое считало его null (с тем же сообщением об ошибке, которое вы испытали в вашем примере).

Рассуждение

Почему так важно блокировать вызовы Ajax из изолированного содержимого из того же домена? Как объясняется в статье:

Как бы то ни было, содержание в одном домене должно быть безопасным. Риск здесь в первую очередь связан с созданным пользователем контентом, который повторно размещен в IFRAME.

Давайте составим пример: предположим, что Facebook решает разрешить пользователям размещать небольшие анимации HTML5 на своих страницах. Он хранит их на своих собственных серверах и, при отображении, изолирует их только как allow-scripts (потому что скрипты необходимы для работы анимаций), но оставляют все остальное отказано (в частности allow-same-origin, так как вам не нужен код пользователя испортить родительскую страницу). Что произойдет, если по умолчанию не будут заблокированы вызовы Ajax?

Мэллори создает "анимацию", состоящую из:

  • Выполнение вызова Ajax в Facebook, используя его API (скажем, Открыть график); сервер будет с радостью принимать вызов, так как для всех он знает, что запрос пришел со страницы с https://facebook.com как источник.

  • Создайте URI, указывающий на свой собственный сервер, с возвращаемыми данными в виде строк запроса и установите его как src изображения на песочнице.

Когда Алиса посещает профиль Мэллори и видит анимацию, выполняется script:

  • Вызов Ajax выполняется в браузере Алисы, а Alice вошел в систему; поскольку сервер не знает, откуда приходит вызов (главная страница или встроенная страница), он будет делать все, что просил - включая получение личной информации.

  • Когда элемент img создается с помощью URI Мэллори, браузер будет пытаться загружать "изображение" в обычном режиме, так как изображения освобождаются от той же политики происхождения.

  • Поскольку URI имеет личную информацию Алисы в строке запроса, сервер Мэллори может просто сохранить ее и вернуть любое изображение, которое он хочет. Теперь у Мэллори есть персональная информация Алисы, и Алиса ничего не подозревает.