Совместное использование ресурсов различными источниками (CORS) – это ключ к тому, чтобы сайты работали так, как мы хотим. Как оно защищает нас от кибератак?
Если коротко – никак.
Вы когда-нибудь встречались с такой ошибкой?
Сообщение об ошибке CORS
Обычно после этого разработчики вбивают в поисковую строку что-то вроде: «Как отключить CORS в Chrome». Они часто делают это во время разработки, потому что CORS встаёт у них на пути. Также существует сразу несколько заблуждений о том, как CORS связан с различными типами кибератак.
Чтобы прояснить ситуацию, CORS сам по себе не предотвращает кибератаки и не защищает от них. Он не останавливает XSS-атаки (межсайтовый скриптинг). На самом деле CORS открывает закрытую мерами безопасности дверь, которая называется политикой одинакового источника (SOP).
Политика одинакового источника (SOP) – это концепция, которую браузеры используют для предотвращения доступа одной веб-страницы к конфиденциальным данным другой. Такой тип кибератаки называется «межсайтовая подделка запроса» (CSRF или XSRF). Вот основные пункты:
- Вы авторизуетесь на сайте, которому доверяете (например, на сайте вашего банка). Вы проходите аутентификацию, используя свое имя пользователя, пароль и, возможно, 2FA. Сеанс сохраняется в вашем браузере в виде файла cookie.
- Когда вы загружаете другие страницы на сайте вашего банка или совершаете действия, находясь в своём аккаунте (например, переводите деньги), браузер использует AJAX-запрос для доступа к конечной точке REST, чтобы получить личные данные или внести изменения в вашу учетную запись.
- Вы открываете вредоносный сайт на новой вкладке браузера. Этот сайт предназначен для отправки AJAX-запросов в конечную точку REST API вашего банка (обычно это происходит в фоновом режиме, поэтому вы не заметите ничего особенного). Браузер отправляет запрос с банковским файлом cookie вашего действующего сеанса.
Существует большое количество разновидностей этого типа атак и множество рассуждений насчет предварительных запросов, выбора между GET и POST и т. д. В обычном случае SOP не позволит сделать что-то с конечной точкой REST вашего банка. Когда вредоносный сайт отправляет AJAX- запрос в конечную точку, браузер проверяет, совпадает ли источник, выполняющий запрос (вредоносный сайт), с источником, в который отправляется запрос (банк). Если они не совпадают javascript-код на вредоносном сайте не получает доступ к ответу.
Теперь давайте изменим сценарий. В указанном выше первом пункте сайт банка — www.bank.com, а конечная точка REST, которую использует банк, – api.bank.com. SOP рассматривает их как разные источники. Сайт банка не будет работать, потому что SOP не даёт ему доступ к конечной точке REST.
Как же нам сделать так, чтобы www.bank.com получил доступ к api.bank.com, блокируя при этом всех остальных? Используем CORS.
Используя CORS, мы можем сообщить браузерам, какие межсайтовые запросы безопасны. В нашем сценарии мы добавляем в конечную точку api.bank.com HTTP-заголовки CORS, которые сообщают браузеру следующее:
Когда веб-страница, расположенная по адресу www.bank.com, пытается отправить мне AJAX-запрос, разрешить его. Если это кто-то еще, заблокировать его.
Всё это можно настроить с помощью заголовка Access-Control-Allow-Origin. Каждый ответ от api.bank.com должен содержать следующий заголовок:
Access-Control-Allow-Origin: https://www.bank.com
Как правильно осуществить редирект с HTTP на HTTPS?
Сейчас мы использовали CORS для того, чтобы открыть дверь, которую закрывает SOP, но только для проверенных доменов. Заметьте, что заголовки CORS применяются к конечной точке REST, а не к самой веб-станице банка. Как разработчикам, нам часто приходится добавлять заголовок с Wildcard-сертификатом, просто чтобы приложение работало. Эта конфигурация разрешает доступ к вашей конечной точке REST из любого источника. В зависимости от функций вашего приложения, в рабочей среде такой вариант может быть очень плох.
//не используйте его в рабочей среде, если вы в нем не разбираетесь Access-Control-Allow-Origin: *
Политика одинакового источника позволяет вредоносным сайтам отправлять запрос на получение учетных данных
Содержание статьи:
Применение SOP не запрещает вредоносным сайтам отправлять запросы в конечную точку REST с реальными учетными данными, хранящимися в вашем браузере в виде файлов cookie. Оно не позволяет этим сайтам прочитать ответ. Это интересный нюанс. CSRF-атаки запускают вредоносный код в браузере пользователя. Получив разрешение, подобный вредоносный код может выполнять непреднамеренные действия от имени пользователя на выбранном сайте (то есть в указанном выше банке) или отправить злоумышленнику информацию о сеансе пользователя. Потом злоумышленник может использовать учетные данные из этого сеанса, чтобы авторизоваться как пользователь и делать от его имени всё что угодно.
Зачем серверу отправлять запрос, если он знает, что источники не совпадают?
Он это делает, потому что межсайтовые запросы довольно распространены. Они делают интернет быстрым, эффективным и удобным для нас. На самом деле, для определенных типов запросов, если семантика REST использована правильно, никаких проблем с безопасностью нет (в частности, в отношении безопасности CORS – не бывает такой ситуации, чтобы проблем с безопасностью не было вообще). Изображения, шрифты, CSS и т. д. можно без проблем загружать из разных источников.
Простые и предварительные запросы CORS
Что такое кэширование сайта и почему это важно
Простые запросы существуют только потому, что они использовались до появления CORS. Спецификация CORS содержит очень подробное определение того, какие типы запросов считаются простыми. Запросы GET и POST (при определенных условиях) считаются «простыми».
Запросы GET используются, когда не должно возникать опасности при отправке запроса «как есть». Если API спроектирован правильно, состояние запросов GET на сервере никогда не изменится. Они должны быть идемпотентными (то есть их можно отправить один или несколько раз без изменения результата). Для сравнения, запросы POST или PUT можно отправить только один раз, так как предполагается, что они меняют свое состояние на сервере. Если бы вы продолжали отправлять запросы POST на перевод денег, на вашем банковском счету не осталось бы ничего!
Для браузера безопасно сразу отправлять запрос GET. Получив его, сервер проверяет наличие у источника разрешения и ваши учетные данные в запросе, затем отправляет ответ с заголовком Access-Control-Allow-Origin.
Если заголовок не совпадает с источником страницы, браузер блокирует ответ для запрашивающей страницы.
Но разве злоумышленник не может создать запрос к вашей конечной точке REST с любым заголовком источника (Origin) и страницы-адресата (Host), каким он захочет?
Да, он может. Кто угодно может создать HTTP-запрос и отправить его на вашу конечную точку с помощью браузеров или других инструментов (например, curl). Злоумышленник может настроить источник таким образом, чтобы он соответствовал разрешенному (то есть, установить заголовок источника https://www.bank.com и отправить запрос на http://api.bank.com), чтобы сделать какую-то гадость. Но ничего не получится, потому что у злоумышленника нет ваших учетных данных. Помните, что атаки CSRF работают только потому, что злоумышленнику нужно, чтобы ваш браузер отправил ваши файлы cookie с запросом на api.bank.com.
Для запросов, которые не подходят под понятие «простых», спецификация CORS требует предварительной проверки. Это дополнительное рукопожатие между браузером и сервером с использованием HTTP метода OPTIONS, чтобы определить, совместим ли фактический запрос между источниками. Это означает, что браузер не будет отправлять настоящий POST или PUT запрос, если предварительная проверка не была пройдена.
В этом примере показано, как предварительная проверка защищает пользователя в приведенном выше сценарии. Если пользователь авторизовался на сайте своего банка и посетил сайт злоумышленников на другой вкладке браузере, возможна CSRF-атака. Здесь мы видим, что браузер отправляет запрос злоумышленников на api.bank.com, но терпит неудачу, потому чтоисточник (badguy.com) не соответствует заголовку Access-Control-Allow-Origin, возвращаемому банком. Заметьте, что CORS использует некоторые другие заголовки, такие как Access-Control-Allow-Headers и Access-Control-Max-Age, но я не показывал их на схемах, чтобы было проще.
В идеале предварительная проверка должна осуществляться при каждом запросе из разных источников, но это требует дополнительного времени. Кроме того, до сих пор существуют устаревшие системы, которые будут несовместимы. Независимо от того, использует ли браузер предварительную проверку или нет, сервер всегда должен проверять, разрешен ли каждый конкретный запрос, полученный из разных источников, а также проверять учетные данные пользователя перед изменением или отправкой какой-либо информации.
Спасибо за внимание!
Источник: www.internet-technologies.ru