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

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

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

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

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

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

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

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

Ответ 1

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

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

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

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

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

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

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

Ответ 2

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

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

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

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

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

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

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

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

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

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

Это звучит, как Cross-Site Request Подделка, где форма на сайте 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. Как сказано в спецификации: "ресурсы, для которых простые запросы имеют значение, отличное от извлечения, должны защищать себя от подделки межсайтовых запросов".

Ответ 3

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

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

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

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

Ответ 4

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

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

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

Ответ 5

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

<!-- 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>

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

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

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

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

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

Ответ 6

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

Сценарии:

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

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

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

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

Ответ 7

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

Источник

Ответ 8

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

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

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

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

Ответ 9

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

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

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

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