CORS - Какова мотивация введения предварительных запросов?

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

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

Так что мой вопрос не о том, как работает CORS / preflight, а о причине, по которой я выбрал preflights в качестве нового типа запроса. Я не вижу никакой причины, по которой серверу A необходимо отправлять предварительную проверку (PR) на сервер B, чтобы выяснить, будет ли принят реальный запрос (RR) или нет - B, безусловно, сможет принять / отклонить RR без любой предыдущий пиар.

После долгих поисков я нашел эту информацию на сайте www.w3.org (7.1.5):

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

Я считаю, что это самое трудное для понимания предложение. Моя интерпретация (лучше назвать это "предположение") заключается в том, что речь идет о защите сервера B от запросов от сервера C, который не знает о спецификации.

Может ли кто-нибудь объяснить сценарий / показать проблему, которую PR + RR решает лучше, чем один RR?

9 ответов

Решение

Я провел некоторое время в замешательстве относительно цели предварительного запроса, но я думаю, что получил его сейчас.

Ключевым моментом является то, что предварительные запросы не относятся к безопасности. Скорее, они не меняют правила.

Предварительные запросы не имеют ничего общего с безопасностью, и они не имеют отношения к приложениям, которые разрабатываются сейчас, с учетом CORS. Скорее, механизм предварительной проверки полезен для серверов, которые были разработаны без знания CORS, и он функционирует как проверка работоспособности между клиентом и сервером на предмет того, что они оба поддерживают CORS. Разработчики CORS чувствовали, что существует достаточно серверов, которые полагаются на предположение, что они никогда не получат, например, междоменный запрос DELETE, что они изобрели механизм предварительной проверки, чтобы обе стороны могли принять участие. Они чувствовали, что альтернатива, которая состояла бы в простой активации междоменных вызовов, сломала бы слишком много существующих приложений.

Здесь есть три сценария:

  1. Старые серверы, которые больше не разрабатываются и разработаны до появления CORS. Эти серверы могут делать предположения, что они никогда не получат, например, междоменный запрос DELETE. Этот сценарий является основным бенефициаром предполетного механизма. Да, эти сервисы уже могут быть использованы злонамеренным или несоответствующим пользовательским агентом (и CORS ничего не делает, чтобы изменить это), но в мире с CORS механизм предварительной проверки обеспечивает дополнительную "проверку работоспособности", чтобы клиенты и серверы не могли перерыв, потому что основные правила Интернета изменились.

  2. Серверы, которые еще находятся в стадии разработки, но содержат много старого кода и для которых нецелесообразно / нежелательно проводить аудит всего старого кода, чтобы убедиться, что он работает должным образом в междоменном мире. Этот сценарий позволяет серверам постепенно подключаться к CORS, например, говоря "Теперь я разрешу этот конкретный заголовок", "Теперь я разрешу этот конкретный HTTP-глагол", "Теперь я позволю куки-файлам / информации об аутентификации быть отправлено "и т. д. Этот сценарий использует механизм предварительной проверки.

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

Какова была мотивация введения предварительных запросов?

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

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

Можете ли вы дать мне пример?

Давайте представим, что пользователь браузера вошел на свой банковский сайт по адресу A.com, Когда они переходят к вредоносным B.com, эта страница включает в себя Javascript, который пытается отправить DELETE запросить A.com/account, Поскольку пользователь вошел в A.com этот запрос, если он будет отправлен, будет включать файлы cookie, идентифицирующие пользователя.

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

Браузер может просто отправить DELETE напрямую и оставь все на сервер. Но что, если A.com не знает о протоколе CORS? Это может пойти дальше и выполнить опасный DELETE, Предполагалось, что он никогда не сможет получить такой запрос из-за политики одинакового происхождения браузера, и поэтому он никогда не был предназначен для предотвращения такой атаки.

Для защиты таких серверов, не поддерживающих CORS, протокол требует, чтобы браузер сначала отправил предварительный запрос. Этот новый тип запроса - это то, на что только CORS-осведомленные серверы могут отвечать должным образом, позволяя браузеру знать, безопасно ли отправлять фактический DELETE,

Почему весь этот шум вокруг браузера, не может ли злоумышленник просто отправить DELETE запрос с собственного компьютера?

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

Это звучит как подделка межсайтовых запросов, где форма на сайте B.com Можно POST в A.com с куки пользователя и наносить ущерб.

Вот так. Другой способ это сделать - предварительные запросы были созданы таким образом, чтобы не увеличивать поверхность атаки CSRF для серверов, не поддерживающих CORS.

Но, глядя на требования к "простым" запросам, которые не требуют предварительной проверки, я вижу, что POST все еще разрешено Это может изменить состояние и удалить данные, как DELETE !

Это правда! CORS не защищает ваш сайт от CSRF-атак. Опять же, без CORS вы также не защищены от CSRF-атак. Цель предварительных запросов - просто ограничить воздействие CSRF на то, что уже существовало в мире до CORS.

Вздох. ОК, я неохотно принимаю необходимость предварительных запросов. Но почему мы должны делать это для каждого ресурса (URL) на сервере? Сервер либо обрабатывает CORS, либо нет.

Вы уверены, что? Многочисленные серверы нередко обрабатывают запросы для одного домена. Например, это может быть случай, когда A.com/url1 обрабатываются одним видом сервера и запросы к A.com/url2 обрабатываются другим типом сервера. Как правило, сервер, обрабатывающий один ресурс, не может гарантировать безопасность всех ресурсов этого домена.

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

Отличная идея! На самом деле, заголовок Access-Control-Policy-Path было предложено именно для этой цели. В конечном счете, однако, это было исключено из спецификации, по- видимому, потому что некоторые серверы неправильно реализовали спецификацию URI таким образом, что запросы к путям, которые казались безопасными для браузера, на самом деле не были бы безопасны на сломанных серверах.

Было ли это разумным решением, которое отдавало приоритет безопасности над производительностью, позволяя браузерам немедленно внедрять спецификацию CORS, не подвергая риску существующие серверы? Или было недальновидно обречь интернет на потерю пропускной способности и удвоить задержку только для того, чтобы учесть ошибки на конкретном сервере в определенное время?

Мнения расходятся.

Ну, по крайней мере, браузеры будут кэшировать предпечатную проверку для одного URL?

Да. Хотя, вероятно, не очень долго. В браузерах WebKit максимальное время кеширования перед полетом в настоящее время составляет 10 минут.

Вздох. Что ж, если я знаю, что мои серверы поддерживают CORS и, следовательно, не нуждаются в защите, предоставляемой предварительными запросами, есть ли способ избежать их?

Ваш единственный реальный вариант - убедиться, что вы соответствуете требованиям "простых" запросов. Это может означать исключение пользовательских заголовков, которые вы могли бы включить (например, X-Requested-With лгать о Content-Type, или больше.

Что бы вы ни делали, вы должны убедиться в наличии надлежащих средств защиты CSRF, поскольку в спецификации CORS не рассматриваются отклонения "простых" запросов, в том числе небезопасных. POST, Как сказано в спецификации: "ресурсы, для которых простые запросы имеют значение, отличное от извлечения, должны защищать себя от подделки межсайтовых запросов".

Рассмотрим мир междоменных запросов до CORS. Вы можете сделать стандартную форму POST или использовать script или image тег для выдачи запроса GET. Вы не могли сделать какой-либо другой тип запроса, кроме GET/POST, и не могли выдавать пользовательские заголовки для этих запросов.

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

Таким образом, запросы GET / POST без каких-либо пользовательских заголовков не нуждаются в предварительной проверке, поскольку эти запросы уже были возможны до CORS. Но любой запрос с пользовательскими заголовками или запросы PUT/DELETE требуют предварительной проверки, поскольку они являются новыми для спецификации CORS. Если сервер ничего не знает о CORS, он ответит без заголовков, специфичных для CORS, и фактический запрос не будет выполнен.

Без предварительного запроса серверы могут начать видеть неожиданные запросы от браузеров. Это может привести к проблеме безопасности, если серверы не будут подготовлены к этим типам запросов. Предварительная проверка CORS позволяет безопасно передавать междоменные запросы в Интернете.

CORS позволяет вам указать больше заголовков и типов методов, чем это было возможно ранее с кросс-источником <img src> или же <form action>,

Некоторые серверы могли быть (плохо) защищены с предположением, что браузер не может сделать, например, перекрестного происхождения DELETE запрос или перекрестный запрос с X-Requested-With заголовок, поэтому такие запросы являются "доверенными".

Чтобы убедиться, что сервер действительно-действительно поддерживает CORS, а не просто отвечает на случайные запросы, выполняется предварительная проверка.

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

Сценарии:

1) С предполетным полетом. Злоумышленник подделывает запрос с сайта dummy-forums.com, пока пользователь проходит аутентификацию на safe-bank.com.
Если Сервер не проверяет источник и имеет какой-либо недостаток, браузер выдаст запрос перед полетом, метод OPTION. Сервер не знает ни одного из CORS, которые браузер ожидает в качестве ответа, поэтому браузер не будет работать (никакого вреда)

2) Без предполетного полета. Злоумышленник подделывает запрос в соответствии с тем же сценарием, что и выше, браузер сразу же отправляет запрос POST или PUT, сервер принимает его и может обработать, что может нанести некоторый вред.

Если злоумышленник отправляет запрос напрямую, из разных источников, с какого-то случайного хоста, он, скорее всего, думает о запросе без аутентификации. Это поддельный запрос, но не запрос xsrf. поэтому сервер проверит учетные данные и потерпит неудачу. CORS не пытается помешать злоумышленнику, имеющему учетные данные, выдавать запросы, хотя белый список может помочь уменьшить этот вектор атаки.

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

Вот еще один способ посмотреть на это, используя код:

<!-- hypothetical exploit on evil.com -->
<!-- Targeting banking-website.example.com, which authenticates with a cookie -->
<script>
jQuery.ajax({
  method: "POST",
  url: "https://banking-website.example.com",
  data: JSON.stringify({
    sendMoneyTo: "Dr Evil",
    amount: 1000000
  }),
  contentType: "application/json",
  dataType: "json"
});
</script>

До появления CORS попытка эксплойта, описанная выше, потерпела бы неудачу, поскольку она нарушает политику того же происхождения. Разработанный таким образом API не нуждался в защите XSRF, потому что он был защищен собственной моделью безопасности браузера. Браузер до CORS не мог сгенерировать JSON POST с несколькими источниками.

Теперь на сцену выходит CORS - если не требуется вход в CORS перед полетом, внезапно этот сайт будет иметь огромную уязвимость не по своей вине.

Чтобы объяснить, почему некоторым запросам разрешено пропускать предполёт, на это отвечает спецификация:

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

Чтобы распутать это, GET предварительно не пролетает, потому что это "простой метод", как определено в 7.1.5. (Заголовки также должны быть "простыми", чтобы избежать предполетной подготовки). Основанием для этого является то, что "простой" запрос GET между источниками уже может быть выполнен, например, <script src=""> (так работает JSONP). Поскольку любой элемент с src Атрибут может запускать GET перекрестного происхождения, без предполетного полета, не будет никакой пользы для безопасности, требующей предварительной битвы на "простых" XHR.

В браузере, поддерживающем CORS, запросы на чтение (например, GET) уже защищены политикой того же происхождения: вредоносный веб-сайт, пытающийся сделать аутентифицированный междоменный запрос (например, на веб-сайт интернет-банка жертвы или интерфейс конфигурации маршрутизатора), не будет быть в состоянии прочитать возвращенные данные, потому что банк или маршрутизатор не устанавливает Access-Control-Allow-Origin заголовок.

Однако при написании запросов (например, POST) ущерб наносится, когда запрос поступает на веб-сервер.* Веб-сервер может проверить Origin заголовок, чтобы определить, является ли запрос законным, но эта проверка часто не реализуется, потому что веб-серверу не нужен CORS или веб-сервер старше, чем CORS, и поэтому он предполагает, что междоменные POST полностью запрещены политикой того же происхождения,

Вот почему веб-серверам предоставляется возможность получать междоменные запросы на запись.

* По сути, AJAX-версия CSRF.

Кроме того, для методов HTTP-запроса, которые могут вызывать побочные эффекты для пользовательских данных (в частности, для HTTP-методов, отличных от GET, или для использования POST с определенными типами MIME), спецификация предписывает браузерам "предварительно проверять" запрос

Источник

Предполетные запросы необходимы для запросов, которые могут изменять состояние на сервере. Есть 2 типа запросов -

1) Вызовы, которые не могут изменить состояние на сервере (например, GET). Пользователь может получить ответ на запрос (если сервер не проверяет происхождение), но если запрашивающий домен не добавлен в заголовок ответа Access-Control-Allow-Origin, браузер не показывает данные пользователю, т. Е. Запрос отправляется из браузера, но пользователь не может просмотреть / использовать ответ.

2) Вызовы, которые могут изменять состояние на сервере (например, POST, DELETE) - поскольку в 1) мы видим, что браузер не блокирует запрос, а ответ, вызовы с изменением состояния не должны выполняться без предварительных проверок.. Такие вызовы могут вносить изменения в доверяющий сервер, который не проверяет источник вызовов (так называемая подделка межсайтовых запросов), даже если ответ браузеру может быть неудачным. По этой причине у нас есть концепция предполетных запросов, которые делают вызов OPTIONS до того, как какие-либо вызовы изменения состояния могут быть отправлены на сервер.

Разве заранее не просят о производительности? С помощью предварительно выданных запросов клиент может быстро узнать, разрешена ли операция, прежде чем отправлять большой объем данных, например, в JSON с методом PUT. Или перед перемещением конфиденциальных данных в заголовках аутентификации по проводам.

Факт PUT, DELETE и других методов, кроме пользовательских заголовков, по умолчанию не разрешен (им необходимо явное разрешение с помощью "Access-Control-Request-Methods" и "Access-Control-Request-Headers"), что звучит точно так же, как двойная проверка, потому что эти операции могут иметь больше последствий для пользовательских данных, а не GET-запросов. Итак, это звучит как:

"Я видел, что вы разрешаете межсайтовые запросы с http://foo.example/, НО ВЫ УВЕРЕНЫ, что разрешите УДАЛИТЬ запросы? Рассматривали ли вы влияние, которое эти запросы могут оказать на пользовательские данные?"

Я не понял цитируемой корреляции между предварительно выданными запросами и преимуществами старых серверов. Веб-служба, которая была реализована до CORS или без поддержки CORS, никогда не получит ЛЮБОЙ межсайтовый запрос, потому что сначала их ответ не будет иметь заголовка "Access-Control-Allow-Origin".

Другие вопросы по тегам