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

282

Совместное использование ресурсов ресурсов - это механизм, позволяющий веб-странице создавать XMLHttpRequests в другом домене (от wikipedia), и это очень важно (от меня:.)

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

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

После небольшого поиска я нашел эту часть информации на www.w3.org(7.1.5):

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

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

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

Теги:
http
cors
preflight

9 ответов

273
Лучший ответ

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

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

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

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

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

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

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

  • 11
    Если это так, почему он отправляется на каждый запрос? Одного запроса на сервер должно быть достаточно, чтобы определить, знает ли сервер о CORS.
  • 3
    Спецификация включает в себя preflight-result-cache в браузере. Таким образом, несмотря на то, что он все еще чувствует себя неряшливым и неэффективным в плане безопасности, представляется возможным настроить новые серверы так, чтобы предварительная проверка кэшировалась бесконечно.
Показать ещё 9 комментариев
110

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

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

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

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

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

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

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

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

  • 9
    Это лучшая вводная часть, которую я читал на CORS. Спасибо!
  • 2
    Потрясающе объяснил.
Показать ещё 2 комментария
46

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

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

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

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

  • 0
    Как сделать запрос POST через скрипт / тег img?
  • 1
    Ты не можешь Я имел в виду , что вы можете либо сделать форму POST, или сделать GET с помощью сценария / IMG. Я отредактировал пост, чтобы уточнить это.
Показать ещё 5 комментариев
30

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

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

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

  • 9
    Это должен был быть принятый ответ. Это самый однозначный и точный. По сути, единственной точкой предварительных запросов является интеграция веб-стандартов до CORS с веб-стандартами после CORS.
  • 1
    Мне нравится этот ответ, но я чувствую, что это не может быть полной причиной ... «предположение о доверии» должно относиться только к вещам, которые может делать только браузер (в частности, отправка информации о пользователе браузера, ограниченной его доменом - то есть печенье). Если это не было частью предположения, то что-либо, что может сделать запрос браузера с разными источниками, может уже быть выполнено сторонним, не браузерным агентом, верно?
Показать ещё 1 комментарий
14

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

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

  • 1
    @MilesRout: Telnet не является частью модели угроз, которая предварительно направлена на смягчение последствий. Предварительная проверка имеет отношение к браузерам, которые 1) полагаются на сохраненные «окружающие права» (например, куки-файлы) и 2) могут быть обмануты в злоупотреблении этими полномочиями третьей стороной (например, подделка межсайтовых запросов). Обобщенная модель известна как проблема запутанного депутата .
  • 0
    Это проблема с окружающим авторитетом, тем не менее, вы всегда можете злоупотреблять этим.
11

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

Сценарии:

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

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

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

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

  • 0
    Согласитесь с проблемой атаки CSRF, которая все еще возможна против "новых серверов", упомянутых в ответе @ michael-iles.
  • 0
    Это полезное описание, которое, вероятно, стоит записать в другом месте. Может быть, стоит добавить его на одну из страниц MDN?
Показать ещё 3 комментария
3

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

Источник

1

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

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

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

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

1

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

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

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

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

  • 4
    Вы неправильно понимаете Access-Control-Allow-Origin. Отсутствие этого заголовка не мешает браузеру отправлять запросы, оно просто мешает JS читать данные в ответе.
  • 0
    Не могли бы вы объяснить это: «Отсутствие этого заголовка не мешает браузеру отправлять запросы, оно просто лишает JS возможности читать данные в ответе» снова, я не получаю его полностью.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню