2013-03-13 7 views
228

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

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

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

После поиска немного я нашел this piece информации на www.w3.org (7.1.5):

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

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

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

ответ

220

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

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

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

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

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

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

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

+9

Если это так, то почему оно отправляется по каждому запросу? Один запрос на сервер должен быть достаточным, чтобы определить, знает ли сервер о CORS. –

+3

Спецификация включает [preflight-result-cache] (http://www.w3.org/TR/cors/#preflight-result-cache) в браузере. Таким образом, несмотря на то, что он по-прежнему чувствует себя неаккуратно и неэффективно, кажется, что можно настроить новые серверы на кеш-кеш неограниченно. –

+5

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

27

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

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

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

+9

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

+1

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

+1

@FabioBeltramini Вправо, не-браузеры могут отправлять все, что захотят. Тем не менее, атаки через браузеры являются особенными, потому что вы можете сделать браузеры других людей делать что-то из своего собственного IP-адреса с их собственными куки-файлами и т. Д. – Kornel

3

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

Source

43

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

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

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

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

+0

Как вы делаете запрос POST с помощью тега script/img? – freakish

+1

Вы не можете. Я имел в виду, что вы можете либо сделать форму POST, либо OR * сделать GET, используя script/img. Я отредактировал сообщение, чтобы, надеюсь, прояснить это. – monsur

+0

Я вижу. В этом есть смысл. – freakish

1

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

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

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

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

+3

Вы недопонимаете Access-Control-Allow-Origin. Отсутствие этого заголовка не препятствует отправке браузером запросов, это просто мешает JS быть в состоянии прочитать данные в ответе. –

+0

Не могли бы вы объяснить это? Отсутствие этого заголовка не мешает браузеру отправлять запросы, это просто мешает JS быть в состоянии прочитать данные в ответе 'снова, я не получу его полностью. – SiddharthBhagwan

+0

@ DylanTack Хорошая точка. Это заставляет меня задаться вопросом, почему же GET xhr не является предполетным? Хотя маловероятно, запросы GET могут быть вредными/мутациями данных. Кроме того, поскольку все это можно решить с помощью CSRF, мне кажется, что браузер чрезмерно защищает серверы, которые слишком небрежны для реализации общих практик безопасности. – Peleg

7

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

Сценарии:

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

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

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

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

+0

Согласитесь, проблема с CSRF-атакой, которая по-прежнему возможна в отношении «новых серверов», упомянутых в ответе @ Майкла-Илеса. –

+0

Это полезное описание, которое, вероятно, стоит записать в другом месте. Может быть, стоит добавить его на одну из страниц MDN? – sideshowbarker

+0

Но почему некоторые запросы, такие как POST с текстом Content-Type/plain, не выполняют предварительный запрос? В моей голове каждый запрос «написать» (POST, PUT, DELETE) должен иметь этот предполетный запрос, если проблема безопасности. –

12

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

<!-- 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 через предполетный рейс не требуется, внезапно этот сайт будет иметь огромную уязвимость, не по своей вине.

Чтобы объяснить, почему некоторые запросы могут пропустить перед полетом, this is answered by the spec:

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

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

+1

@MilesRout: Telnet не является частью модели угрозы, целью которой является преследование. Предполетная документация имеет отношение к браузерам, которые 1) полагаются на сохраненные, «окружающая среда» (например, файлы cookie) и 2) могут быть обмануты неправильным использованием этого права третьей стороной (например, подделкой запроса на межсайтовый запрос). Обобщенная модель известна как [запутанная проблема заместителя] (https://en.wikipedia.org/wiki/Confused_deputy_problem). –

+0

Это проблема с окружающей властью, но вы всегда можете ее оскорблять. –

36

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

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

Спецификация puts it this way: «Для защиты ресурсов от запросов кросс-происхождения, которые не могли исходить от определенных пользовательских агентов до того, как эта спецификация существовала, предпродажный запрос делается для обеспечения того, чтобы ресурс знал об этой спецификации».

Можете ли вы привести мне пример?

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

А что, если банковский сайт на A.com не знает о CORS? Он может с радостью выполнить DELETE. Он не был предназначен для предотвращения этой атаки, потому что до того, как существовала CORS, политика одинакового происхождения браузера не позволила бы ей отправить такой запрос. Сервер полагается на это предположение.

В отличие от этого, если браузер сначала отправляет запрос перед полетом, сервер не сможет правильно ответить. Это говорит браузеру, что этот сервер не участвует в CORS, и поэтому он не должен отправлять потенциально опасные DELETE.

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

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

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

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

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

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

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

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

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

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

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

Мнения разные.

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

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

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

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

В любом случае, вы должны убедиться, что у вас есть надлежащая защита CSRF, поскольку спецификация CORS не касается отклонения «простых» запросов, в том числе небезопасных POST. As the specification puts it: «Ресурсы, для которых простые запросы имеют значение, отличные от поиска, должны защищать себя от подделки запросов на межсайтовый запрос».

+3

Это лучший вводный материал, который я прочитал на CORS. Спасибо! – kiv

1

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

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

Именно поэтому веб-серверам предоставляется возможность отказаться от приема запросов на междоменную запись.

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