Same origin policy что это

Кросс-доменные ограничения и их обход

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

Более новая информация по этой теме находится на странице https://learn.javascript.ru/cross-window-communication.

Ограничение «Same Origin» («тот же источник») ограничивает доступ окон и фреймов друг к другу, а также влияет на AJAX-запросы к серверу.

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

Концепция Same Origin

Два URL считаются имеющим один источник («same origin»), если у них одинаковый протокол, домен и порт.

Эти URL имеют один источник:

А вот эти – все из других источников:

Существует ряд исключений, позволяющих-таки окнам с разных доменов обмениваться информацией, но прямой вызов методов друг друга и чтение свойств запрещены.

В действии

Если одно окно попытается обратиться к другому, то браузер проверит, из одного ли они источника. Если нет – доступ будет запрещён.

Пример выше выведет ошибку.

Исключение: запись в location

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

Причём читать свойства location нельзя, одно окно не имеет право знать, на каком URL пользователь в другом. А вот запись браузеры считают безопасной.

Исключение: поддомен 3-го уровня

Ещё одно важное исключение касается доменов третьего уровня.

То есть, на всех этих сайтах должен быть код:

Тогда между ними не будет кросс-доменных ограничений.

Таким образом разные подсайты в рамках одного общего проекта могут взаимодействовать без ограничений.

Исключения в IE

В браузере Internet Explorer есть два своих, дополнительных исключения из Same Origin Policy.

Порт не входит в понятие «источник» (origin).

Это иногда используют для общения серверов, использующих один IP-адрес. Но допустимо такое только в IE.

Если сайт находится в зоне «Надёжные узлы», то в Internet Explorer ограничения к нему не применяются.

При этом подразумевается, что для этой зоны в параметрах «Безопасность» включена опция «Доступ к источникам данных за пределами домена».

Итого

Ограничение «одного источника» запрещает окнам и фреймам с разных источников вызывать методы друг друга и читать данные друг из друга.

При этом «из одного источника» означает «совпадают протокол, домен и порт».

У этого подхода ряд существенных исключений:

Источник

Что такое CORS

Многие из нас встречались с подобной ошибкой:

Access to XMLHttpRequest at ‘XXXX’ from origin ‘YYYY’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource..

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Эта статья рассказывает что означает эта ошибка и как от нее избавиться.

Создадим тестовый сайт на Node.js с открытым API и запустим его по адресу http://127.0.0.1:3000.

Пусть там будет примерно такая функция получения GET запроса:

Пусть там будет простая функция входа в систему, где пользователи вводят общее секретное слово secret и им затем ему устанавливается cookie, идентифицируя их как аутентифицированных:

И пусть у нас будет некое приватное API для каких нибудь личных данных в /private, только для аутентифицированных пользователей.

Запрос нашего API через AJAX из других доменов

И допустим у нас есть какое-нибудь клиентское приложение работающее с нашим API. Но учтем что, наше API находится по адресу http://127.0.0.1:3000/public, а наш клиент размещен на http://127.0.0.1:8000, и на клиенте есть следующий код:

И это не будет работать!

Если мы посмотрим на вкладку network в консоле Хрома при обращение c http://127.0.0.1:8000 к http://127.0.0.1:3000 то там не будет ошибок:

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Сам по себе запрос был успешным, но результат оказался не доступен. Описание причины можно найти в консоли JavaScript:

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Ага! Нам не хватает заголовка Access-Control-Allow-Origin. Но зачем он нам и для чего он вообще нужен?

Same-Origin Policy

Например: если вы заходите на sample.org, вы бы не хотели, чтобы этот веб-сайт отправлял запрос к примеру на ваш банковский веб-сайт и получал баланс вашего счета и транзакции.

Same-Origin Policy предотвращает именно это.

«источник (origin)» в этом случае состоит из

Так что http://sample.org и http://www.sample.org и http://sample.org:3000 — это три разных источника.

Пару слов о CSRF

Обратите внимание, что существует класс атак, называемый подделкой межсайтовых запросов (Cross Site Request Forgerycsrf ), от которых не защищает Same-Origin Policy.

При CSRF-атаке злоумышленник отправляет запрос сторонней странице в фоновом режиме, например, отправляя POST запрос на веб-сайт вашего банка. Если у вас в этот момент есть действительный сеанс с вашим банком, любой веб-сайт может сгенерировать запрос в фоновом режиме, который будет выполнен, если ваш банк не использует контрмеры против CSRF.

Так же обратите внимание, что, несмотря на то, что действует Same-Origin Policy, наш пример запроса с сайта secondparty.com на сайте 127.0.0.1:3000 будет успешно выполнен — мы просто не соможем получить доступ к результатам. Но для CSRF нам не нужен результат …

Например, API, которое позволяет отправлять электронные письма, выполняя POST запрос, отправит электронное письмо, если мы предоставим ему правильные данные. Злоумышленнику не нужно заботится о результате, его забота это отправляемое электронное письмо, которое он получит независимо от возможности видеть ответ от API.

Включение CORS для нашего публичного API

Допустим нам нужно разрешить работу JavaScript на сторонних сайтах (например, 127.0.0.1:8000) что бы получать доступ к нашим ответам API. Для этого нам нужно включить CORS в заголовок ответа от сервера. Это делается на стороне сервера:

Здесь мы устанавливаем заголовку Access-Control-Allow-Origin значение *, что означает: что любому хосту разрешен доступ к этому URL и ответу в браузере:

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Непростые запросы и предварительные запросы (preflights)

Предыдущий пример был так называемым простым запросом. Простые запросы — это:

Допустим теперь 127.0.0.1:8000 немного меняет реализацию, и теперь он обрабатывает запросы в формате JSON:

Но это снова все ломает!
На этот раз консоль показывает другую ошибку:

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Любой заголовок, который не разрешен для простых запросов, требует предварительного запроса (preflight request).

Этот механизм позволяет веб-серверам решать, хотят ли они разрешить фактический запрос. Браузер устанавливает заголовки Access-Control-Request-Headers и Access-Control-Request-Method, чтобы сообщить серверу, какой запрос ожидать, и сервер должен ответить соответствующими заголовками.

Но наш сервер еще не отвечает с этими заголовками, поэтому нам нужно добавить их:

Теперь мы снова может получить доступ к ответу.

Credentials и CORS

Теперь давайте предположим, что нам нужно залогинится на 127.0.0.1:3000 что бы получить доступ к /private с конфиденциальной информацией.

При всех наших настройках CORS может ли другой сайт так же получить эту конфиденциальную информацию?

Мы пропустили код реализации входа в на сервер так как он не обязателен для объяснения материала.

Независимо от того, попытаемся ли мы залогинится на 127.0.0.1:3000 или нет, мы увидим «Please login first».

Причина в том, что cookie от 127.0.0.1:3000 не будут отправляться, когда запрос поступает из другого источника. Мы можем попросить браузер отправить файлы cookie клиенту, даже если запрос с других доменов:

Но опять это не будет работать в браузере. И это хорошая новость, на самом деле.

Итак, мы не хотим, чтобы злоумышленник имел доступ к приватным данным, но что, если мы хотим, чтобы 127.0.0.1:8000 имел доступ к /private?
В этом случае нам нужно установить для заголовка Access-Control-Allow-Credentials значение true:

Но это все равно пока еще не сработает. Это опасная практика — разрешать любые аутентифицированные запросы с других источников.

Браузер не позволит нам так легко совершить ошибку.

Если мы хотим разрешить 127.0.0.1:8000 доступ к /private, нам нужно указать точный источник в заголовке:

Теперь http://127.0.0.1:8000 также имеет доступ к приватным данным, в то время как запрос с любого другого сайта будет заблокирован.

Разрешить множественные источники (origin)

Теперь мы разрешили одному источнику делать запросы к другому источнику с данными аутентификации. Но что, если у нас есть несколько других источников?

В этом случае мы, вероятно, хотим использовать белый список:

Опять же: не отправляйте напрямую req.headers.origin в качестве разрешенного заголовка CORS. Это позволит любому веб-сайту получить доступ к приватным данным.
Из этого правила могут быть исключения, но, по крайней мере, дважды подумайте, прежде чем внедрять CORS с учетными данными без белого списка.

Заключение

В этой статье мы рассмотрели Same-Origin Policy и то, как мы можем использовать CORS, чтобы разрешать запросы между источниками, когда это необходимо.

Это требует настройки на стороне сервера и на стороне клиента и в зависимости от запроса вызовет предварительный (preflight) запрос.

При работе с аутентифицированными запросами перекрестного происхождения следует проявлять дополнительную осторожность. Белый список может помочь разрешить нескольким источникам без риска утечки конфиденциальных данных (которые защищены аутентификацией).

Выводы

Источник

Безопасность наглядно: CORS

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

В этой статье я не буду останавливаться на основах HTTP. Скажу лишь, что в своих примерах я использую HTTP/1.1, а не HTTP/2 — на CORS это никак не влияет.

Во фронтенде часто требуется отобразить данные, которые хранятся в другом месте. Перед этим браузер должен направить запрос серверу: клиент отправляет HTTP-запрос со всей информацией, которая нужна серверу, чтобы вернуть данные.

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Что произошло? Мы отправили такой же запрос, но на этот раз браузер выдал странную ошибку. Мы только что увидели CORS в действии. Давайте разберёмся, почему возникла эта ошибка, и что она означает.

Правило одинакового источника (Same-Origin Policy)

Ресурс считается принадлежащим к другому источнику (cross-origin), если он располагается на другом домене/поддомене, протоколе или порте.

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Это, конечно, здорово, но для чего правило одинакового источника вообще существует?

Представим, что это правило не работает, а вы случайно нажали на какую-то вирусную ссылку, которую прислала ваша тётушка на Фейсбуке. Ссылка перенаправляет вас на мошеннический сайт, который с помощью фрейма загружает интерфейс сайта вашего банка и успешно залогинивает вас с помощью сохранённых куки.

Разработчики этого мошеннического сайта сделали так, чтобы он имел доступ к фрейму и мог взаимодействовать с DOM сайта вашего банка — так они смогут переводить деньги на свой счёт от вашего имени.

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Да, это огромная угроза безопасности — мы ведь не хотим, чтобы кто угодно имел доступ к чему угодно.

К счастью, здесь приходит на помощь правило одинакового источника: оно гарантирует, что мы можем получить доступ только к ресурсам из того же самого источника.

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Но какое отношение всё это имеет к CORS?

CORS на стороне клиента

Несмотря на то, что правило одинакового источника применяется исключительно к скриптам, браузеры распространили его и на JavaScript-запросы: по умолчанию можно получить доступ к ресурсам только из одинакового источника.

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Но нам ведь часто нужно обращаться к ресурсам из других источников… Может, тогда фронтенду стоит взаимодействовать с API на бэкенде, чтобы загружать данные? Чтобы обеспечить безопасность запросов к другим источникам, браузеры используют механизм под названием CORS.

Аббревиатура CORS расшифровывается как Cross-Origin Resource Sharing (Технология совместного использования ресурсов между разными источниками). Несмотря на то, что браузеры не позволяют получать доступ к ресурсам из разных источников, можно использовать CORS, чтобы внести небольшие коррективы в эти ограничения и при этом быть уверенным, что доступ будет безопасным.

Пользовательские агенты (к примеру, браузеры) на основе значений определённых заголовков для CORS в HTTP-запросе могут проводить запросы к другим источникам, которые без CORS были бы заблокированы.

Когда происходит запрос к другому источнику, клиент автоматически подставляет дополнительный заголовок Origin в HTTP-запрос. Значение этого заголовка отражает источник запроса.

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Чтобы браузер разрешил доступ к ресурсам из другого источника, он должен получить определённые заголовки в ответе от сервера, которые указывают, разрешает ли сервер запросы из других источников.

CORS на стороне сервера

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Да, теперь CORS выдаёт эту печально известную ошибку, которая иногда всех нас так расстраивает. Но сейчас нам понятно, какой смысл она несет.

В качестве значения разрешённых источников CORS позволяет указать спецсимвол * . Он означает, что доступ к ресурсам открыт из всех источников, поэтому используйте его с осторожностью.

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Если вам интересно почитать о других CORS-заголовках, ознакомьтесь с их списком на MDN.

Предварительные запросы

Существует два типа CORS-запросов: простые и предварительные. Тип запроса зависит от хранящихся в нём значений (не волнуйтесь, здесь не надо будет ничего запоминать).

Если интересно узнать, каким требованиям должен соответствовать запрос, чтобы называться простым, почитайте эту статью на MDN.

Но что означают и почему существуют “предварительные запросы”?

Перед отправкой текущего запроса клиент сначала генерирует предварительный запрос: в своих заголовках Access-Control-Request-* он содержит информацию о текущем запросе. Это позволяет серверу узнать метод, дополнительные заголовки и другие параметры запроса, который браузер пытается отправить.

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Сервер получает этот предварительный запрос и отправляет обратно пустой HTTP-ответ с CORS-заголовками сервера. Браузер в свою очередь получает предварительный ответ (только CORS-заголовки) и проверяет, разрешён ли HTTP-запрос.

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Если всё в порядке, браузер посылает текущий запрос на сервер, а тот в ответ присылает данные, которые мы запрашивали.

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Если же возникает проблема, CORS блокирует предварительный запрос, а текущий вообще уже не будет отправлен. Предварительный запрос — отличный способ уберечь нас от получения доступа или изменения ресурсов на серверах, у которых (пока что) не настроены правила CORS. Сервера защищены от потенциально нежелательных запросов из других источников.

Чтобы уменьшить число обращений к серверу, можно кэшировать предварительные ответы, добавив к CORS-запросам заголовок Access-Control-Max-Age . Так браузеру не придётся каждый раз отправлять новый предварительный запрос.

Учётные данные

Куки, заголовки авторизации, TLS-сертификаты по умолчанию включены только в запросы из одинакового источника. Однако нам может понадобиться использовать учётные данные и в запросах из разных источников. Возможно, мы захотим включить куки в запрос, который сервер сможет использовать для идентификации пользователя.

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Готово — теперь мы можем включать учётные данные в запрос из другого источника.

Думаю, мы все согласимся с тем, что появление ошибок CORS порой расстраивает, но, тем не менее, здорово, что CORS позволяет безопасно отправлять запросы из разных источников в браузере — считаю, что мы должны любить эту технологию чуточку сильнее 🙂

Разумеется, о правиле одинакового источника и CORS можно рассказать гораздо больше, но я просто не смогу уместить всё это в одной статье. К счастью, ресурсов много (к примеру, спецификация W3) — вам будет к чему обратиться, если захотите подробнее изучить эту тему.

Источник

Same-origin policy

Политика одинакового источника (same-origin policy) определяет как документ или скрипт, загруженный из одного источника (origin), может взаимодействовать с ресурсом из другого источника. Это помогает изолировать потенциально вредоносные документы, снижая количество возможных векторов атак.

Определение origin

В следующей таблице даны примеры origin-сравнений с URL http://store.company.com/dir/page.html :

URLOutcomeReason
http://store.company.com/dir2/other.htmlSuccess
http://store.company.com/dir/inner/another.htmlSuccess
https://store.company.com/secure.htmlFailureDifferent protocol
http://store.company.com:81/dir/etc.htmlFailureDifferent port
http://news.company.com/dir/other.htmlFailureDifferent host

Наследование origins

Контент из about:blank и javascript: адреса наследуют источник документа, содержащего этот URL, поскольку они не содержат информации о сервере происхождения.

Например, about:blank часто используется в качестве URL новых, пустых окон в которые родительский скрипт записывает контент (например, с помощью Window.open() (en-US) ). Если это окно также содержит JavaScript, то скрипт будет наследовать то же происхождение, что и его родитель.

data: адреса получают новый, пустой, безопасный контекст.

Исключения в Internet Explorer

Internet Explorer два основных исключения из политики одно происхождения:

Trust Zones (Зоны доверия) Если оба домена находятся в зоне высокого доверия (например, зоны корпоративной интрасети), то ограничения на одно и то же происхождение не применяется. Порт IE не включает порт в same-origin проверку. Следовательно, https://company.com:81/index.html и https://company.com/index.html являются адресами одного происхождения и ограничения действовать не будут.

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

Изменение origin

Страница может изменить свой оригинальный origin с некоторыми ограничениями. Скрипт может установить значение document.domain на текущий домен или супердомен текущего домена. Если значение будет установлено на супердомен текущего домена, более короткий домен будет использован для последующей проверки origin’а. Например, предполагается, что скрипт в документе по адресу http://store.company.com/dir/other.html выполняется следующим выражением:

Замечание: Когда используется document.domain для разрешения поддомена для родительского доступа к нему, вы должны установить document.domain в такое же значение, как в родительском домене, так и в поддомене. Это необходимо, даже если при этом просто восстанавливается исходное значение родительского домена. Несоблюдение этого правила может привести к ошибкам разрешений.

Cross-origin network access

The same-origin policy controls interactions between two different origins, such as when you use XMLHttpRequest or an element. These interactions are typically placed into three categories:

Here are some examples of resources which may be embedded cross-origin:

How to allow cross-origin access

Use CORS to allow cross-origin access.

How to block cross-origin access

Use CORS to allow cross-origin access.

Источник

Доступ к контенту iFrame с другого домена

Сегодня я хочу рассказать о том, как мы в своем проекте indexisto.com сделали аналог инструмента Google Webmaster Marker. Напомню, что Marker это инструмент в кабинете Google Webmaster, который позволяет аннотировать ваши страницы Open Graph тегами. Для этого вы просто выделяете мышкой кусок текста на странице и указываете что это title, а это рейтинг. Ваша страница при этом грузится в Iframe в кабинете вебмастера.

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Теперь Google, встретив подобную страницу на вашем сайте, уже знает, что за контент на ней опубликован, и как его красиво распарсить в сущность (статью, товар, видео..)

Нам был нужен подобный функционал. Задача казалась несложной и исключительно клиентсайд. Однако на практике решение лежит на стыке клиентсайда и серверсайда («чистые» JS программисты могу ничего не знать про различные прокси серверы и очень долго подходить к снаряду). При этом я не нашел в интернетах статью которая описывала бы всю технологию от начала до конца. Также хочется сказать спасибо пользователю BeLove и нашим безопасникам за помощь.

В нашем случае хотелось чтобы вебмастер мог удобно (пометив мышкой) получить значение xPath к определенным элементам на своей странице.

Iframe «Same Origin»

И так в нашей админке человек должен ввести URL страницы своего сайта, мы отобразим ее в iFrame, человек тыкнет мышкой куда надо, мы получим искомый xPath. Все бы ОК, но у нас нет доступа к контенту страницы с другого домена загруженной в iframe в нашей админке (наш домен), из за политики безопасности браузера.

CORS — Cross origin resource sharing

Одни люди мне посоветовали использовать CORS. Модная технология которая решает множество проблем с доступом к контенту с другого домена в браузере и позволяет обойти same origin policy ограничения.
Сайт который хочет дать доступ к своему контенту на страницах чужого домена просто пишет в http заголовок:

А в заголовоке http запроса идущего со страницы другого домена из браузера должно быть поле origin:

понятно что поле origin к запросу браузер дописывает сам. Плюсанем статью на Хабре и увидим что современные браузеры добавляют Origin даже к запросу на тот же самый домен:
Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Iframe sandbox

Еще одна модная технология. Sandbox это атрибут тега Iframe. В качестве одного из значений этого атрибута можно выставить значение allow-same-origin. До того как я начал копать эту тему я не знал что точно делает этот аттрибут, а звучало очень заманчиво. Однако атрибут sandbox просто ограничивает то, что может делать страница загруженная в iframe и не имеет отношения к проблеме доступа из родительского документа к содержимому фрейма.

Конкретно значение allow-same-origin (вернее его отсутствие) всего лишь говорит что iframe нужно всегда расценивать как загруженный с чужого домена (нельзя например из такого фрейма послать AJAX запрос на домен родительского документа)

Посмотрим как сделано у Google

Время рисеча того, как сделано у большого брата
Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Обратим внимание на аттрибут src элемента iframe: src=»https://wmthighlighter.googleusercontent.com/webmasters/data-highlighter/RenderFrame/007.» — наша страница грузится в админку с домена Google. Далее еще более сурово: даже скрипты и картинки в исходном документе прогоняются через прокси. Все src, href… заменены в html на проксированные. Примерно вот так:

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Все ресурсы которые использует ваша страница еще и сохраняются на прокси серверах Гугл. Вот например наш логотип на прокси сервере Google.

CGIProxy?

Visit the script’s URL to start a browsing session. Once you’ve gotten a page through the proxy, everything it links to will automatically go through the proxy. You can bookmark pages you browse to, and your bookmarks will go through the proxy as they did the first time.

Свой Proxy!

Однако, если сузить задачу, написать простой proxy намного проще самому. Дело в том, что делать так делает Google, прогоняя весь контент страницы через прокси совершенно не обязательно. Нам просто нужно чтобы html любой страницы отдавался с нашего домена, а ресурсы можно подгрузить и из оригинального домена. Https мы пока отбросили.
Задача супер производительности или удобств настроек здесь не стоит, и сделать это можно по быстрому и на чем угодно, от node.js до php. Мы написали сервлет на Java.

Качаем страницу

Что должен делать прокси сервлет? Через get параметр получаем url страницы которую нужно загрузить, далее качаем страницу.

Обязательно определяем кодировку страницы (через http ответ или charset в html) — наш прокси должен ответить в той же кодировке что и страница которую мы загрузили. Так же определим Content-Type на всякий случай, хотя и так понятно что мы получаем страницу в text/html и отдадим ее так же.

*Для любителей оценить чужой код: у нас в команде у всех одинаковые настройки форматирования кода eclicpse, и при сохранении файла эклипс сам дописывает ко всем переменным final если они более нигде не меняются. Что кстати довольно удобно в итоге.

Меняем относительные URL на абсолютные в коде страницы

Надо пройтись по всем атрибутам с src и href в странице (пути файлов стилей, картинки), и заменить относительные урлы на абсолютные. Иначе страница будет пытаться загрузить картинки с каких-то папок на нашем прокси, которых у нас естественно нет. В любом языке есть готовые классы или можно найти сниппеты кода для этого дела на stackoverflow:

Отсылаем html

Вот и все, прокси сервлет готов. Посылаем ответ, выставив нужную кодировку и mime.

Деплоим и тестим

Деплоим наш прокси сервлет на том же адресе, что и админка adminpanel.indexisto.com, грузим в наш iframe страницу сайта вебмастера через прокси и все кроссдоменные проблемы исчезают.
Наш прокси работает по адресу

— вот так хабр загрузится с нашего домена. Отдаем этот адрес в iframe и пробуем получить доступ к DOM дереву хабра через JS в админке — все работает. CSRF естественно не пройдет так как страница загружена с нашего прокси у которого нет куки.

Проблемка SSRF

Загрузим в наш iframe сайт с адресом «localhost» — опа, вот стартовая страница нашего nginx. Попробуем какой-нибудь внутренний (не видный наружу) ресурс в той же сети, что и наш прокси сервер. Например secured_crm.indexisto.com — все на месте.
Конечно пытаемся запретить эти вещи в нашем прокси, в случае если кто-то пытается запроксировать localhost мы выходим ничего не возвращая:

но всех ресурсов сети мы здесь явно не перечислим. Значит надо вынести прокси в совершенно изолированную среду, чтобы машина ничего не видела кроме интернета, себя самой и нашего прокси. Выделяем машину, настраиваем и заводим наш сервлет там.

Проблемка XSS

Загрузим в наш iframe свою страничку на которой напишем:

Приплыли, мы разломали наше собственное решение с обходом кроссдоменных ограничений. Теперь мы снова не можем достучаться до контента iframe.

Интересная мысль.

Продолжая ресечить решение от гугла я открыл нашу страницу отдающуюся через прокси в отдельном окне

Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

и обратил внимание на странную ошибку в консоли.

Стало ясно что все организованно сложнее, чем просто загрузить страницу в iframe со своего домена. Страницы общаются между собой. Соответственно двигаемся в сторону window.postMessage

Post Message

Заставлять внедрять вебмастера в свою страницу наш скрипт который бы обеспечивал выделение элементов страницы мышкой, а потом бы отсылал xPath этих элементов к нам в родительский документ через postMessage было не гуманно. Однако никто не мешает нашему прокси внедрить любые скрипты на загружаемую в iFrame страницу.
Все необходимые для внедрения скрипты сохраняем в файл, и вставляем их перед закрывающим body:

для пробы вставляем alert — все работает.

JS часть — подсвечиваем дом элемент под мышкой и получаем xpath

Окей, переходим собственно к JS который мы вставили на страницу вебмастера.
Нам необходимо подсвечивать dom элементы над которыми человек водит мышкой. Лучше делать это с помощью shadow так как тогда элемент не будет смещаться, а вся страница прыгать. Вешаем onmouseover на body и смотрим на target события. В этом же обработчике я вычисляю xpath элемента. Вычислять xPath элемента лучше на клик, но никаких тормозов и в такой реализации я не заметил.

Я не привожу здесь реализацию получения xPath элемента DOM. Существует множество сниппетов того как это сделать. Эти сниппеты можно модифицировать под свои задачи, например вам нужны в xpath только тэги. Или вам нужны id если они есть и классы если нет id — у всех свои требования.

JS часть — обрабатываем клик

Клик человека на странице в iframe сразу же «гасится» (перехода по ссылке в iframe не произойдет). А так же мы посылаем в родительское окно строку полученного xPath (мы его сохранили еще на этапе вождения мышкой над элементом)

Profit!

Вот и все, теперь в нашей админке вебмастер может намного проще быстро получить xpath пути к элементам на своих страницах.
Same origin policy что это. Смотреть фото Same origin policy что это. Смотреть картинку Same origin policy что это. Картинка про Same origin policy что это. Фото Same origin policy что это

Добавим еще секьюрности

Окей, у нас все заработало, однако есть момент с тем, что наш прокси смотрит в мир совершенно незащищенный. Кто угодно может запроксировать что угодно.

Ставим перед прокси nginx, он слушает 80 порт, сам прокси убираем на другой порт. Все другие порты кроме 80 закрываем от внешнего мира.

Теперь сделаем так чтобы прокси работал только через панель администратора. В момент когда вебмастер вводит URL своего сайта мы быстро бегаем на сервер где генерим md5 хэш от текущего TimeStamp + 1 час, самой URL и суперсекретного когда:

Так же обратите внимание что в коде мы получачаем md5 строку не как привычный hex, а в base64 кодировке, плюс в полученном md5 мы делаем странные замены символов слэша и плюса на подчеркивание и тире.
Дело в том что ngnix использует base64 Filename Safe Alphabet tools.ietf.org/html/rfc3548#page-6
А Java дает каноничсекий base64.

Получив в нашей админке ответ от сервера с секьюрной md5, мы пытаемся загрузить в iframe вот такой url:
highlighter.indexisto.com/?md5=Dr4u2Yeb3NrBQLgyDAFrHg==&url=http%3A%2F%2Fhabrahabr.ru&expires=1389791582

Теперь настраиваем модуль nginx HttpSecureLinkModule. Этот модуль сверяет md5 всех параметров которые к нему пришли (в модуле прописан тот же секретный ключ что и в сервлете админки), проверяет не проэкпарйилась ли ссылка и только в этом случае пробрасывает запрос на наш прокси сервлет.

Теперь никто не может воспользоваться нашим прокси не из админки, а так же не может куда-нибудь вставить запроксированную на наш сервер картинку — она все равно умрет через час.

Источник

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

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