Что такое same origin policy
Same-origin policy
Политика одинакового источника (same-origin policy) определяет как документ или скрипт, загруженный из одного источника (origin), может взаимодействовать с ресурсом из другого источника. Это помогает изолировать потенциально вредоносные документы, снижая количество возможных векторов атак.
Определение origin
В следующей таблице даны примеры origin-сравнений с URL http://store.company.com/dir/page.html :
URL | Outcome | Reason |
---|---|---|
http://store.company.com/dir2/other.html | Success | |
http://store.company.com/dir/inner/another.html | Success | |
https://store.company.com/secure.html | Failure | Different protocol |
http://store.company.com:81/dir/etc.html | Failure | Different port |
http://news.company.com/dir/other.html | Failure | Different 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.
Безопасность наглядно: CORS
В этой статье я не буду останавливаться на основах HTTP. Скажу лишь, что в своих примерах я использую HTTP/1.1, а не HTTP/2 — на CORS это никак не влияет.
Во фронтенде часто требуется отобразить данные, которые хранятся в другом месте. Перед этим браузер должен направить запрос серверу: клиент отправляет HTTP-запрос со всей информацией, которая нужна серверу, чтобы вернуть данные.
Что произошло? Мы отправили такой же запрос, но на этот раз браузер выдал странную ошибку. Мы только что увидели CORS в действии. Давайте разберёмся, почему возникла эта ошибка, и что она означает.
Правило одинакового источника (Same-Origin Policy)
Ресурс считается принадлежащим к другому источнику (cross-origin), если он располагается на другом домене/поддомене, протоколе или порте.
Это, конечно, здорово, но для чего правило одинакового источника вообще существует?
Представим, что это правило не работает, а вы случайно нажали на какую-то вирусную ссылку, которую прислала ваша тётушка на Фейсбуке. Ссылка перенаправляет вас на мошеннический сайт, который с помощью фрейма загружает интерфейс сайта вашего банка и успешно залогинивает вас с помощью сохранённых куки.
Разработчики этого мошеннического сайта сделали так, чтобы он имел доступ к фрейму и мог взаимодействовать с DOM сайта вашего банка — так они смогут переводить деньги на свой счёт от вашего имени.
Да, это огромная угроза безопасности — мы ведь не хотим, чтобы кто угодно имел доступ к чему угодно.
К счастью, здесь приходит на помощь правило одинакового источника: оно гарантирует, что мы можем получить доступ только к ресурсам из того же самого источника.
Но какое отношение всё это имеет к CORS?
CORS на стороне клиента
Несмотря на то, что правило одинакового источника применяется исключительно к скриптам, браузеры распространили его и на JavaScript-запросы: по умолчанию можно получить доступ к ресурсам только из одинакового источника.
Но нам ведь часто нужно обращаться к ресурсам из других источников… Может, тогда фронтенду стоит взаимодействовать с API на бэкенде, чтобы загружать данные? Чтобы обеспечить безопасность запросов к другим источникам, браузеры используют механизм под названием CORS.
Аббревиатура CORS расшифровывается как Cross-Origin Resource Sharing (Технология совместного использования ресурсов между разными источниками). Несмотря на то, что браузеры не позволяют получать доступ к ресурсам из разных источников, можно использовать CORS, чтобы внести небольшие коррективы в эти ограничения и при этом быть уверенным, что доступ будет безопасным.
Пользовательские агенты (к примеру, браузеры) на основе значений определённых заголовков для CORS в HTTP-запросе могут проводить запросы к другим источникам, которые без CORS были бы заблокированы.
Когда происходит запрос к другому источнику, клиент автоматически подставляет дополнительный заголовок Origin в HTTP-запрос. Значение этого заголовка отражает источник запроса.
Чтобы браузер разрешил доступ к ресурсам из другого источника, он должен получить определённые заголовки в ответе от сервера, которые указывают, разрешает ли сервер запросы из других источников.
CORS на стороне сервера
Да, теперь CORS выдаёт эту печально известную ошибку, которая иногда всех нас так расстраивает. Но сейчас нам понятно, какой смысл она несет.
В качестве значения разрешённых источников CORS позволяет указать спецсимвол * . Он означает, что доступ к ресурсам открыт из всех источников, поэтому используйте его с осторожностью.
Если вам интересно почитать о других CORS-заголовках, ознакомьтесь с их списком на MDN.
Предварительные запросы
Существует два типа CORS-запросов: простые и предварительные. Тип запроса зависит от хранящихся в нём значений (не волнуйтесь, здесь не надо будет ничего запоминать).
Если интересно узнать, каким требованиям должен соответствовать запрос, чтобы называться простым, почитайте эту статью на MDN.
Но что означают и почему существуют “предварительные запросы”?
Перед отправкой текущего запроса клиент сначала генерирует предварительный запрос: в своих заголовках Access-Control-Request-* он содержит информацию о текущем запросе. Это позволяет серверу узнать метод, дополнительные заголовки и другие параметры запроса, который браузер пытается отправить.
Сервер получает этот предварительный запрос и отправляет обратно пустой HTTP-ответ с CORS-заголовками сервера. Браузер в свою очередь получает предварительный ответ (только CORS-заголовки) и проверяет, разрешён ли HTTP-запрос.
Если всё в порядке, браузер посылает текущий запрос на сервер, а тот в ответ присылает данные, которые мы запрашивали.
Если же возникает проблема, CORS блокирует предварительный запрос, а текущий вообще уже не будет отправлен. Предварительный запрос — отличный способ уберечь нас от получения доступа или изменения ресурсов на серверах, у которых (пока что) не настроены правила CORS. Сервера защищены от потенциально нежелательных запросов из других источников.
Чтобы уменьшить число обращений к серверу, можно кэшировать предварительные ответы, добавив к CORS-запросам заголовок Access-Control-Max-Age . Так браузеру не придётся каждый раз отправлять новый предварительный запрос.
Учётные данные
Куки, заголовки авторизации, TLS-сертификаты по умолчанию включены только в запросы из одинакового источника. Однако нам может понадобиться использовать учётные данные и в запросах из разных источников. Возможно, мы захотим включить куки в запрос, который сервер сможет использовать для идентификации пользователя.
Готово — теперь мы можем включать учётные данные в запрос из другого источника.
Думаю, мы все согласимся с тем, что появление ошибок CORS порой расстраивает, но, тем не менее, здорово, что CORS позволяет безопасно отправлять запросы из разных источников в браузере — считаю, что мы должны любить эту технологию чуточку сильнее 🙂
Разумеется, о правиле одинакового источника и CORS можно рассказать гораздо больше, но я просто не смогу уместить всё это в одной статье. К счастью, ресурсов много (к примеру, спецификация W3) — вам будет к чему обратиться, если захотите подробнее изучить эту тему.
CORS для чайников: история возникновения, как устроен и оптимальные методы работы
В этой статье подробно разобрана история и эволюция политики одинакового источника и CORS, а также расписаны разные типы доступа между различными источниками, а также несколько оптимальных решений работы с ними.
Если вы давно хотели разобраться в CORS и вас достали постоянные ошибки, добро пожаловать под кат.
Ошибка в консоли вашего браузера
No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://example.com/
Access to fetch at ‘https://example.com’ from origin ‘http://localhost:3000’ has been blocked by CORS policy.
Я уверен, вам уже доводилось видеть похожие сообщения об ошибках в консоли вашего браузера. Если нет, не волнуйтесь, скоро увидите. Все программисты достаточно часто натыкаются на CORS-ошибки.
Эти всплывающие ошибки в процессе разработки просто раздражают. Но на самом деле, CORS — это невероятно полезный механизм в мире неправильно настроенных веб серверов, злоумышленников, орудующих в интернете и организаций, продвигающих веб-стандарты.
Но давайте-ка пойдем к истокам…
В начале был первый субресурс
Верни мне мой 1993 г.
Источники & cross-origin
Источник идентифицируется следующей тройкой параметров: схема, полностью определенное имя хоста и порт. Например, и имеют разные источники: первый использует схему http, а второй https. Вдобавок, портом для http по умолчанию является 80, тогда как для https — 443. Следовательно, в данном примере 2 источника отличаются схемой и портом, тогда как хост один и тот же (example.com).
Таким образом, если хотя бы один из трех элементов у двух ресурсов отличается, то источник ресурсов также считается разным.
Если, к примеру, мы будем сравнивать источник с другими источниками, то мы получим следующие результаты:
URL | Результат | Причина |
Тот же | Отличается только путь | |
Тот же | Отличается только путь | |
Отличен | Разные протоколы | |
Отличен | Отличается порт (https:// порт является по умолчанию 443) | |
Отличен | Разный хост |
Пример запроса между различными источниками: когда ресурс (то есть, страница) типа попробует отобразить тег из источника (заметьте, что схема поменялась!).
Слишком много опасностей запроса между различными источниками
Теперь, когда мы определились, что такое совместное использования ресурсов между разными и одинаковыми источниками, давайте посмотрим, в чем же дело.
Когда тег появился во Всемирной Паутине, мы тем самым открыли ящик Пандоры. Некоторое время спустя в Сети появились теги
Кросс-доменные ограничения и их обход
Материал на этой странице устарел, поэтому скрыт из оглавления сайта.
Более новая информация по этой теме находится на странице 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 ограничения к нему не применяются.
При этом подразумевается, что для этой зоны в параметрах «Безопасность» включена опция «Доступ к источникам данных за пределами домена».
Итого
Ограничение «одного источника» запрещает окнам и фреймам с разных источников вызывать методы друг друга и читать данные друг из друга.
При этом «из одного источника» означает «совпадают протокол, домен и порт».
У этого подхода ряд существенных исключений:
Этот механизм имеет особое значение для современных веб-приложений, которые во многом зависят от файлов cookie HTTP для поддержания аутентифицированных пользовательских сеансов, поскольку серверы действуют на основе информации cookie HTTP, чтобы раскрыть конфиденциальную информацию или предпринять действия, изменяющие состояние. На стороне клиента должно поддерживаться строгое разделение контента, предоставляемого несвязанными сайтами, чтобы предотвратить потерю конфиденциальности или целостности данных.
Очень важно помнить, что политика одного и того же происхождения применяется только к скриптам. Это означает, что к таким ресурсам, как изображения, CSS и динамически загружаемые скрипты, можно получить доступ из разных источников через соответствующие теги HTML (заметным исключением являются шрифты). Атаки используют тот факт, что одна и та же политика происхождения не применяется к тегам HTML.
СОДЕРЖАНИЕ
История
Концепция политики одинакового происхождения была введена Netscape Navigator 2.02 в 1995 году, вскоре после появления JavaScript в Netscape 2.0. JavaScript позволяет создавать сценарии на веб-страницах и, в частности, программный доступ к объектной модели документа (DOM).
Изначально политика была разработана для защиты доступа к модели DOM, но с тех пор была расширена для защиты конфиденциальных частей глобального объекта JavaScript.
Реализация
Правила определения происхождения
Для иллюстрации в следующей таблице представлен обзор типичных результатов проверок по URL-адресу « http://www.example.com/dir/page.html ».
Сравните URL | Исход | Причина |
---|---|---|
http://www.example.com /dir/page2.html | Успех | Та же схема, хост и порт |
http://www.example.com /dir2/other.html | Успех | Та же схема, хост и порт |
http: // имя пользователя: пароль @ www.example.com /dir2/other.html | Успех | Та же схема, хост и порт |
http://www.example.com: 81 /dir/other.html | Отказ | Та же схема и хост, но другой порт |
https : //www.example.com/dir/other.html | Отказ | Другая схема |
http: // en.example.com /dir/other.html | Отказ | Другой хост |
http: // example.com /dir/other.html | Отказ | Другой хост (требуется точное соответствие) |
http: // v2.www.example.com /dir/other.html | Отказ | Другой хост (требуется точное соответствие) |
http://www.example.com: 80 /dir/other.html | Зависит от | Порт явный. Зависит от реализации в браузере. |
В отличие от других браузеров, Internet Explorer не включает порт в вычисление источника, используя вместо него Зону безопасности.
Доступ для чтения к конфиденциальным ответам из разных источников с помощью многоразовой аутентификации
Политика одного и того же происхождения защищает от повторного использования аутентифицированных сеансов в разных источниках. В следующем примере показана потенциальная угроза безопасности, которая может возникнуть без политики одного и того же происхождения. Предположим, что пользователь посещает веб-сайт банка и не выходит из системы. Затем пользователь переходит на другой сайт с вредоносным кодом JavaScript, который запрашивает данные с сайта банка. Поскольку пользователь по-прежнему авторизован на сайте банка, вредоносный код может делать все, что пользователь может сделать на сайте банка. Например, он может получить список последних транзакций пользователя, создать новую транзакцию и т. Д. Это связано с тем, что в исходном духе всемирной паутины браузеры должны помечать детали аутентификации, такие как файлы cookie сеанса и платформенные. виды уровня заголовка запроса авторизации к сайту банка в зависимости от домена сайта банка.
Владельцы сайтов банка ожидают, что обычные браузеры пользователей, посещающих вредоносный сайт, не позволят коду, загруженному с вредоносного сайта, получить доступ к cookie банковского сеанса или авторизации на уровне платформы. Хотя это правда, что JavaScript не имеет прямого доступа к куки-файлу банковской сессии, он все же может отправлять и получать запросы на банковский сайт с помощью куки-файла сеанса банковского сайта. Политика одинакового происхождения была введена как требование для браузеров, ориентированных на безопасность, чтобы запретить доступ для чтения к ответам из разных источников, с предположением, что большинство пользователей предпочитают использовать совместимые браузеры. Политика не запрещает пишет. Противодействие злоупотреблению разрешением на запись требует дополнительной защиты CSRF со стороны целевых сайтов.
Ослабление политики одинакового происхождения
Заражение данных
document.domain свойство
Если два окна (или фрейма) содержат сценарии, устанавливающие для домена одно и то же значение, политика одного и того же происхождения ослабляется для этих двух окон, и каждое окно может взаимодействовать с другим. Например, совместные скрипты в документах, загруженных с orders.example.com и catalog.example.com, могут установить свои document.domain свойства на «example.com», тем самым создавая впечатление, что документы имеют одно и то же происхождение, и позволяя каждому документу читать свойства Другие. Установка этого свойства неявно устанавливает для порта значение null, которое большинство браузеров будет интерпретировать иначе, чем порт 80 или даже неуказанный порт. Чтобы гарантировать, что доступ будет разрешен браузером, установите свойство document.domain на обеих страницах.
Эта document.domain концепция была представлена как часть Netscape Navigator 3, выпущенного в 1996 году.
Совместное использование ресурсов между источниками
Другой метод ослабления политики одинакового происхождения стандартизирован под названием Cross-Origin Resource Sharing (CORS). Этот стандарт расширяет HTTP с новым заголовком запроса Origin и новым заголовком ответа Access-Control-Allow-Origin. Это позволяет серверам использовать заголовок для явного перечисления источников, которые могут запрашивать файл, или использовать подстановочный знак и разрешать запрос файла любым сайтом. Браузеры, такие как Firefox 3.5, Safari 4 и Internet Explorer 10, используют этот заголовок, чтобы разрешить HTTP-запросы с разными источниками с XMLHttpRequest, которые в противном случае были бы запрещены политикой того же происхождения.
Обмен сообщениями между документами
Другой метод, обмен сообщениями между документами, позволяет сценарию с одной страницы передавать текстовые сообщения сценарию на другой странице независимо от происхождения сценария. Вызов метода postMessage () для объекта Window асинхронно запускает событие «onmessage» в этом окне, вызывая любые определенные пользователем обработчики событий. Сценарий на одной странице по-прежнему не может напрямую обращаться к методам или переменным на другой странице, но они могут безопасно взаимодействовать с помощью этой техники передачи сообщений.