Remkomplekty.ru

IT Новости из мира ПК
5 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Ошибка доступ запрещен возможна csrf атака

Атака CSRF

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

Нельзя говорить про AJAX и не упомянуть про важнейшую деталь его реализации – защиту от CSRF-атак.

CSRF (Cross-Site Request Forgery, также XSRF) – опаснейшая атака, которая приводит к тому, что хакер может выполнить на неподготовленном сайте массу различных действий от имени других, зарегистрированных посетителей.

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

Злая форма

«Классический» сценарий атаки таков:

Вася является залогиненным на сайт, допустим, mail.com . У него есть сессия в куках.

Вася попал на «злую страницу», например хакер пригласил его сделать это письмом или как-то иначе.

На злой странице находится форма такого вида:

При заходе на злую страницу JavaScript вызывает form.submit , отправляя таким образом форму на mail.com .

Сайт mail.com проверяет куки, видит, что посетитель авторизован и обрабатывает форму. В данном примере форма предполагает посылку сообщения.

Итог атаки – Вася, зайдя на злую страницу, ненароком отправил письмо от своего имени. Содержимое письма сформировано хакером.

Защита

В примере выше атака использовала слабое звено авторизации.

Куки позволяют сайту mail.com проверить, что пришёл именно Вася, но ничего не говорят про данные, которые он отправляет.

Иначе говоря, куки не гарантируют, что форму создал именно Вася. Они только удостоверяют личность, но не данные.

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

Затем на основе ключа генерируется «токен» ( token ). Токен делается так, чтобы с одной стороны он был отличен от ключа, в частности, может быть много токенов для одного ключа, с другой – чтобы было легко проверить по токену, сгенерирован ли он на основе данного ключа или нет.

Для каждого токена нужно дополнительное случайное значение, которое называют «соль» salt .

Формула вычисления токена:

  1. В сессии хранится secret=»abcdef» , это значение создаётся один раз.
  2. Для нового токена сгенерируем salt , например пусть salt=»1234″ .
  3. token = «1234» + «:» + MD5(«1234» + «:» + «abcdef») = «1234:5ad02792a3285252e524ccadeeda3401» .

Это значение – с одной стороны, случайное, с другой – имея такой token , мы можем взять его первую часть 1234 в качестве salt и, зная secret , проверить по формуле, верно ли он вычислен.

Не зная secret , невозможно сгенерировать token, который сервер воспримет как правильный.

Далее, токен добавляется в качестве скрытого поля к каждой форме, генерируемой на сервере.

То есть, «честная» форма для отсылки сообщений, созданная на http://mail.com , будет выглядеть так:

При её отправке сервер проверит поле csrf , удостоверится в правильности токена, и лишь после этого отошлёт сообщение.

«Злая страница» при всём желании не сможет сгенерировать подобную форму, так как не владеет secret , и токен будет неверным.

Такой токен также называют «подписью» формы, которая удостоверяет, что форма сгенерирована именно на сервере.

Эта подпись говорит о том, что автор формы – сервер, но ничего не гарантирует относительно её содержания.

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

При отправке формы сервер проверит подпись, подставив в неё известный ему secret и присланное значение fields.money . При несовпадении либо secret не тот (хакер), либо fields.money изменено.

Токен и AJAX

Теперь перейдём к AJAX-запросам.

Что если посылка сообщений в нашем интерфейсе реализуется через XMLHttpRequest?

Как и в случае с формой, мы должны «подписать» запрос токеном, чтобы гарантировать, что его содержимое прислано на сервер именно интерфейсом сайта, а не «злой страницей».

Здесь возможны варианты, самый простой – это дополнительная кука.

При авторизации сервер устанавливает куку с именем CSRF-TOKEN , и пишет в неё токен.

Код, осуществляющий XMLHttpRequest, получает куку и ставит заголовок X-CSRF-TOKEN с ней:

Сервер проверяет, есть ли заголовок и содержит ли он правильный токен.

Защита действует потому, что прочитать куку может только JavaScript с того же домена. «Злая страница» не сможет «переложить» куку в заголовок.

Если нужно сделать не XMLHttpRequest, а, к примеру, динамически сгенерировать форму из JavaScript – она также подписывается аналогичным образом, скрытое поле или дополнительный URL-параметр генерируется по куке.

Итого

CSRF-атака – это когда «злая страница» отправляет форму или запрос на сайт, где посетитель, предположительно, залогинен.

Если сайт проверяет только куки, то он такую форму принимает. А делать это не следует, так как её сгенерировал злой хакер.

Для защиты от атаки формы, которые генерирует mail.com , подписываются специальным токеном. Можно не все формы, а только те, которые осуществляют действия от имени посетителя, то есть могут служить объектом атаки.

Для подписи XMLHttpRequest токен дополнительно записывается в куку. Тогда JavaScript с домена mail.com сможет прочитать её и добавить в заголовок, а сервер – проверить, что заголовок есть и содержит корректный токен.

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

Атака CSRF

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

Нельзя говорить про AJAX и не упомянуть про важнейшую деталь его реализации – защиту от CSRF-атак.

CSRF (Cross-Site Request Forgery, также XSRF) – опаснейшая атака, которая приводит к тому, что хакер может выполнить на неподготовленном сайте массу различных действий от имени других, зарегистрированных посетителей.

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

Злая форма

«Классический» сценарий атаки таков:

Вася является залогиненным на сайт, допустим, mail.com . У него есть сессия в куках.

Вася попал на «злую страницу», например хакер пригласил его сделать это письмом или как-то иначе.

На злой странице находится форма такого вида:

При заходе на злую страницу JavaScript вызывает form.submit , отправляя таким образом форму на mail.com .

Сайт mail.com проверяет куки, видит, что посетитель авторизован и обрабатывает форму. В данном примере форма предполагает посылку сообщения.

Итог атаки – Вася, зайдя на злую страницу, ненароком отправил письмо от своего имени. Содержимое письма сформировано хакером.

Защита

В примере выше атака использовала слабое звено авторизации.

Куки позволяют сайту mail.com проверить, что пришёл именно Вася, но ничего не говорят про данные, которые он отправляет.

Читать еще:  Ошибка subscript out of range

Иначе говоря, куки не гарантируют, что форму создал именно Вася. Они только удостоверяют личность, но не данные.

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

Затем на основе ключа генерируется «токен» ( token ). Токен делается так, чтобы с одной стороны он был отличен от ключа, в частности, может быть много токенов для одного ключа, с другой – чтобы было легко проверить по токену, сгенерирован ли он на основе данного ключа или нет.

Для каждого токена нужно дополнительное случайное значение, которое называют «соль» salt .

Формула вычисления токена:

  1. В сессии хранится secret=»abcdef» , это значение создаётся один раз.
  2. Для нового токена сгенерируем salt , например пусть salt=»1234″ .
  3. token = «1234» + «:» + MD5(«1234» + «:» + «abcdef») = «1234:5ad02792a3285252e524ccadeeda3401» .

Это значение – с одной стороны, случайное, с другой – имея такой token , мы можем взять его первую часть 1234 в качестве salt и, зная secret , проверить по формуле, верно ли он вычислен.

Не зная secret , невозможно сгенерировать token, который сервер воспримет как правильный.

Далее, токен добавляется в качестве скрытого поля к каждой форме, генерируемой на сервере.

То есть, «честная» форма для отсылки сообщений, созданная на http://mail.com , будет выглядеть так:

При её отправке сервер проверит поле csrf , удостоверится в правильности токена, и лишь после этого отошлёт сообщение.

«Злая страница» при всём желании не сможет сгенерировать подобную форму, так как не владеет secret , и токен будет неверным.

Такой токен также называют «подписью» формы, которая удостоверяет, что форма сгенерирована именно на сервере.

Эта подпись говорит о том, что автор формы – сервер, но ничего не гарантирует относительно её содержания.

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

При отправке формы сервер проверит подпись, подставив в неё известный ему secret и присланное значение fields.money . При несовпадении либо secret не тот (хакер), либо fields.money изменено.

Токен и AJAX

Теперь перейдём к AJAX-запросам.

Что если посылка сообщений в нашем интерфейсе реализуется через XMLHttpRequest?

Как и в случае с формой, мы должны «подписать» запрос токеном, чтобы гарантировать, что его содержимое прислано на сервер именно интерфейсом сайта, а не «злой страницей».

Здесь возможны варианты, самый простой – это дополнительная кука.

При авторизации сервер устанавливает куку с именем CSRF-TOKEN , и пишет в неё токен.

Код, осуществляющий XMLHttpRequest, получает куку и ставит заголовок X-CSRF-TOKEN с ней:

Сервер проверяет, есть ли заголовок и содержит ли он правильный токен.

Защита действует потому, что прочитать куку может только JavaScript с того же домена. «Злая страница» не сможет «переложить» куку в заголовок.

Если нужно сделать не XMLHttpRequest, а, к примеру, динамически сгенерировать форму из JavaScript – она также подписывается аналогичным образом, скрытое поле или дополнительный URL-параметр генерируется по куке.

Итого

CSRF-атака – это когда «злая страница» отправляет форму или запрос на сайт, где посетитель, предположительно, залогинен.

Если сайт проверяет только куки, то он такую форму принимает. А делать это не следует, так как её сгенерировал злой хакер.

Для защиты от атаки формы, которые генерирует mail.com , подписываются специальным токеном. Можно не все формы, а только те, которые осуществляют действия от имени посетителя, то есть могут служить объектом атаки.

Для подписи XMLHttpRequest токен дополнительно записывается в куку. Тогда JavaScript с домена mail.com сможет прочитать её и добавить в заголовок, а сервер – проверить, что заголовок есть и содержит корректный токен.

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

Приложение запрашивает код

Приложение направляет пользователя на страницу Яндекс.OAuth , где он может разрешить доступ к своим данным .

Пользователь разрешает доступ приложению.

Яндекс.OAuth перенаправляет пользователя на адрес, указанный в поле Callback URL при регистрации приложения. Код подтверждения (или описание ошибки) передается в параметре URL перенаправления.

Приложение получает адрес перенаправления и извлекает код подтверждения.

Яндекс.OAuth возвращает токен в теле ответа.

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

Запрос кода подтверждения

Приложение должно направить пользователя на Яндекс.OAuth по следующему адресу:

При запросе кода подтверждения следует указать значение «code» .

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

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

Идентификатор должен быть не короче 6 символов и не длиннее 50. Допускается использовать только печатаемые ASCII-символы (с кодами от 32 до 126).

Подробнее о токенах для отдельных устройств читайте на странице Токен для устройства.

Имя устройства, которое следует показывать пользователям. Не длиннее 100 символов.

Для мобильных устройств рекомендуется передавать имя устройства, заданное пользователем. Если такого имени нет, его можно собрать из модели устройства, названия и версии ОС и т. д.

Если параметр device_name передан без параметра device_id , он будет проигнорирован. Яндекс.OAuth сможет выдать только обычный токен, не привязанный к устройству.

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

URL, на который нужно перенаправить пользователя после того, как он разрешил или отказал приложению в доступе. По умолчанию используется первый Callback URI, указанный в настройках приложения ( Платформы → Веб-сервисы → Callback URI ).

В значении параметра допустимо указывать только те адреса, которые перечислены в настройках приложения. Если совпадение неточное, параметр игнорируется.

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

Параметр позволяет помочь пользователю авторизоваться на Яндексе с тем аккаунтом, к которому нужен доступ приложению. Получив параметр, Яндекс.OAuth проверяет авторизацию пользователя:

Если пользователь уже авторизован с нужным аккаунтом, Яндекс.OAuth просто запрашивает разрешение на доступ.

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

Читать еще:  Ошибка ваш уровень фильтрации

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

Список необходимых приложению в данный момент прав доступа, разделенных пробелом. Права должны запрашиваться из перечня, определенного при регистрации приложения. Узнать допустимые права можно по ссылке https://oauth.yandex.ru/client/ /info, указав вместо идентификатор приложения.

Если параметры scope и optional_scope не переданы, то токен будет выдан с правами, указанными при регистрации приложения.

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

Список разделенных пробелом опциональных прав доступа, без которых приложение может обойтись. Опциональные права запрашиваются в дополнение к правам, указанным в параметре scope . Опциональные права должны запрашиваться из перечня, определенного при регистрации приложения. Узнать допустимые права можно по ссылке https://oauth.yandex.ru/client/ /info, указав вместо идентификатор приложения.

Если параметры scope и optional_scope не переданы, то токен будет выдан с правами, указанными при регистрации приложения.

Пользователь самостоятельно решает, какие из запрошенных опциональных прав предоставить, а какие нет. Токен будет выдан с правами, указанными в параметре scope , и правами, выбранными пользователем из указанных в параметре optional_scope .

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

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

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

Параметр обрабатывается, если для него указано значение «yes» , «true» или «1» . При любом другом значении параметр игнорируется.

Строка состояния, которую Яндекс.OAuth возвращает без изменения. Максимальная допустимая длина строки — 1024 символа.

Можно использовать, например, для защиты от CSRF-атак или идентификации пользователя, для которого запрашивается токен.

Защита сайта от CSRF атак

Дата публикации: 2017-02-23

От автора: поводом к записи данного урока послужил вопрос на нашем форуме, который звучал следующим образом — как защитить сайт от CSRF -атак? Конечно мы сразу же ответили по данной теме и привели небольшой алгоритм по реализации механизма защиты. Но так как, скорее всего форум читают, далеко не все наши читатели я решил записать отдельный урок по вышеуказанному вопросу.

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

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

Бесплатный курс по PHP программированию

Освойте курс и узнайте, как создать динамичный сайт на PHP и MySQL с полного нуля, используя модель MVC

В курсе 39 уроков | 15 часов видео | исходники для каждого урока

CSRF – это аббревиатура образованная английскими словами Cross-Site Request Forgery, что означает межсайтовая подделка запросов. Данный термин введен уже достаточно давно еще 2001 году Питером Воткинсом, но говорить о возможных атаках подобного рода начали еще в далеком 1988 году. При этом заметьте, прошло уже достаточное количество времени, но все же данной атаке подвергается большая часть веб-сайтов интернета. Сразу же возникает вопрос – почему так? И ответ довольно прост и заключается в том, что уязвимость к атакам CSRF — это не ошибка кода приложения, а следствие вполне обычной работы браузера и веб-сервера.

Суть атаки заключается в том, что злоумышленник может выполнить на незащищенном сайте различные действия от имени другого зарегистрированного (авторизированного) пользователя. Другими словами данный тип атаки предусматривает посещение пользователем сайта злоумышленника, что в свою очередь приводит к тому, что незаметно для него выполняются некоторые заранее прописанные действия на другом сайте или сервисе, на котором этот пользователь в данный момент авторизован.

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

Теперь давайте рассмотрим действие указанной атаки на примере тестового сайта.

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

Данная страница вполне обычная, но в глаза бросается чек-бокс “Member”, который используется для сохранения данный авторизации в куках браузера. Собственно данный механизм очень удобен пользователям, так как упрощает повторный доступ к странице, но крайне не желателен с точки зрения безопасности. Но все же ради посетителей часто приходится идти на определенные уступки.

Код отправки сообщений двумя методами (GET и POST) выглядит примерно следующим образом:

Бесплатный курс по PHP программированию

Освойте курс и узнайте, как создать динамичный сайт на PHP и MySQL с полного нуля, используя модель MVC

В курсе 39 уроков | 15 часов видео | исходники для каждого урока

Что такое CORS

Многие из нас встречались с подобной ошибкой:

Access to XMLHttpRequest at ‘XXXX’ from origin ‘YYYY’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource..

Эта статья рассказывает что означает эта ошибка и как от нее избавиться.

Создадим тестовый сайт на Node.js с открытым API и запустим его по адресу http://127.0.0.1:3000.

Пусть там будет примерно такая функция получения GET запроса:

Пусть там будет простая функция входа в систему, где пользователи вводят общее секретное слово secret и им затем ему устанавливается cookie, идентифицируя их как аутентифицированных:

И пусть у нас будет некое приватное API для каких нибудь личных данных в /private, только для аутентифицированных пользователей.

Читать еще:  Ошибка system net webexception

Запрос нашего API через AJAX из других доменов

И допустим у нас есть какое-нибудь клиентское приложение работающее с нашим API. Но учтем что, наше API находится по адресу http://127.0.0.1:3000/public, а наш клиент размещен на http://127.0.0.1:8000, и на клиенте есть следующий код:

И это не будет работать!

Если мы посмотрим на вкладку network в консоле Хрома при обращение c http://127.0.0.1:8000 к http://127.0.0.1:3000 то там не будет ошибок:

Сам по себе запрос был успешным, но результат оказался не доступен. Описание причины можно найти в консоли JavaScript:

Ага! Нам не хватает заголовка Access-Control-Allow-Origin. Но зачем он нам и для чего он вообще нужен?

Same-Origin Policy

Причиной, по которой мы не получим ответ в JavaScript, является Same-Origin Policy. Эта ограничительная мера была придумана разработчиками браузеров что бы веб-сайт не мог получить ответ на сгенерированный AJAX запрос к другому веб-сайту находящемуся по другому адресу .

Например: если вы заходите на sample.org, вы бы не хотели, чтобы этот веб-сайт отправлял запрос к примеру на ваш банковский веб-сайт и получал баланс вашего счета и транзакции.

Same-Origin Policy предотвращает именно это.

«источник (origin)» в этом случае состоит из

  • протокол (например http )
  • хост (например example.com )
  • порт (например 8000 )

Так что http://sample.org и http://www.sample.org и http://sample.org:3000 – это три разных источника.

Пару слов о CSRF

Обратите внимание, что существует класс атак, называемый подделкой межсайтовых запросов (Cross Site Request Forgerycsrf ), от которых не защищает Same-Origin Policy.

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

Так же обратите внимание, что, несмотря на то, что действует Same-Origin Policy, наш пример запроса с сайта secondparty.com на сайте 127.0.0.1:3000 будет успешно выполнен – мы просто не соможем получить доступ к результатам. Но для CSRF нам не нужен результат …

Например, API, которое позволяет отправлять электронные письма, выполняя POST запрос, отправит электронное письмо, если мы предоставим ему правильные данные. Злоумышленнику не нужно заботится о результате, его забота это отправляемое электронное письмо, которое он получит независимо от возможности видеть ответ от API.

Включение CORS для нашего публичного API

Допустим нам нужно разрешить работу JavaScript на сторонних сайтах (например, 127.0.0.1:8000) что бы получать доступ к нашим ответам API. Для этого нам нужно включить CORS в заголовок ответа от сервера. Это делается на стороне сервера:

Здесь мы устанавливаем заголовку Access-Control-Allow-Origin значение *, что означает: что любому хосту разрешен доступ к этому URL и ответу в браузере:

Непростые запросы и предварительные запросы (preflights)

Предыдущий пример был так называемым простым запросом. Простые запросы – это:

  • Запросы: GET,POST
  • Тип содержимого следующего:
    • text/plain
    • application/x-www-form-urlencoded
    • multipart/form-data

Допустим теперь 127.0.0.1:8000 немного меняет реализацию, и теперь он обрабатывает запросы в формате JSON:

Но это снова все ломает!
На этот раз консоль показывает другую ошибку:

Любой заголовок, который не разрешен для простых запросов, требует предварительного запроса (preflight request).

Этот механизм позволяет веб-серверам решать, хотят ли они разрешить фактический запрос. Браузер устанавливает заголовки Access-Control-Request-Headers и Access-Control-Request-Method, чтобы сообщить серверу, какой запрос ожидать, и сервер должен ответить соответствующими заголовками.

Но наш сервер еще не отвечает с этими заголовками, поэтому нам нужно добавить их:

Теперь мы снова может получить доступ к ответу.

Credentials и CORS

Теперь давайте предположим, что нам нужно залогинится на 127.0.0.1:3000 что бы получить доступ к /private с конфиденциальной информацией.

При всех наших настройках CORS может ли другой сайт так же получить эту конфиденциальную информацию?

Мы пропустили код реализации входа в на сервер так как он не обязателен для объяснения материала.

Независимо от того, попытаемся ли мы залогинится на 127.0.0.1:3000 или нет, мы увидим «Please login first».

Причина в том, что cookie от 127.0.0.1:3000 не будут отправляться, когда запрос поступает из другого источника. Мы можем попросить браузер отправить файлы cookie клиенту, даже если запрос с других доменов:

Но опять это не будет работать в браузере. И это хорошая новость, на самом деле.

Итак, мы не хотим, чтобы злоумышленник имел доступ к приватным данным, но что, если мы хотим, чтобы 127.0.0.1:8000 имел доступ к /private?
В этом случае нам нужно установить для заголовка Access-Control-Allow-Credentials значение true:

Но это все равно пока еще не сработает. Это опасная практика – разрешать любые аутентифицированные запросы с других источников.

Браузер не позволит нам так легко совершить ошибку.

Если мы хотим разрешить 127.0.0.1:8000 доступ к /private, нам нужно указать точный источник в заголовке:

Теперь http://127.0.0.1:8000 также имеет доступ к приватным данным, в то время как запрос с любого другого сайта будет заблокирован.

Разрешить множественные источники (origin)

Теперь мы разрешили одному источнику делать запросы к другому источнику с данными аутентификации. Но что, если у нас есть несколько других источников?

В этом случае мы, вероятно, хотим использовать белый список:

Опять же: не отправляйте напрямую req.headers.origin в качестве разрешенного заголовка CORS. Это позволит любому веб-сайту получить доступ к приватным данным.
Из этого правила могут быть исключения, но, по крайней мере, дважды подумайте, прежде чем внедрять CORS с учетными данными без белого списка.

Заключение

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

Это требует настройки на стороне сервера и на стороне клиента и в зависимости от запроса вызовет предварительный (preflight) запрос.

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

Выводы

  • Браузер использует Same-origin policy, чтобы не обрабатывать AJAX ответы от веб-сайтов расположенных на адресах отличных от адреса с которого была загружена веб страница.
  • Same-origin policy не запрещает генерировать запросы к другим сайтам, но запрещает обрабатывать от них ответ.
  • CORS (Cross-Origin Resource Sharing) механизм, который использует дополнительные заголовки HTTP, чтобы дать браузерам указание предоставить веб-приложению, работающему в одном источнике, доступ к ответу на запрос к ресурсам из другого источника.
  • CORS вместе с credentials (с данными аутентификации) требует осторожности.
  • CORS это браузерная политика. Другие приложения не затрагиваются этим понятием.
Ссылка на основную публикацию
ВсеИнструменты
Adblock
detector
×
×