CORS и заголовок ответа Access-Control-Allow-Origin
Спецификация совместного использования ресурсов между источниками (CORS) обеспечивает контролируемое смягчение политики единого источника (Same-origin policy) для HTTP-запросов к одному домену веб-сайтов от другого за счёт использования набора HTTP заголовков. Браузеры разрешают доступ к ответам на запросы из разных источников на основе этих инструкций в заголовке.
Что такое заголовок ответа Access-Control-Allow-Origin
Заголовок Access-Control-Allow-Origin включается в ответ одного веб-сайта на запрос, исходящий с другого веб-сайта, и определяет разрешённый источник запроса. Веб-браузер сравнивает Access-Control-Allow-Origin с источником запрашивающего веб-сайта и разрешает доступ к ответу, если они совпадают.
Реализация простого совместного использования ресурсов между источниками
Спецификация совместного использования ресурсов между источниками (CORS) предписывает обмен содержимым заголовков между веб-серверами и браузерами, который ограничивает источники запросов веб-ресурсов за пределами исходного домена. Спецификация CORS определяет набор заголовков протокола, из которых Access-Control-Allow-Origin является наиболее важным. Этот заголовок возвращается сервером, когда веб-сайт запрашивает междоменный ресурс с заголовком Origin, добавленным браузером.
Предположим, что веб-сайт с источником normal-website.com вызывает следующий междоменный запрос:
GET /data HTTP/1.1
Host: robust-website.com
Origin : https://normal-website.comСервер на сайте robust-website.com возвращает следующий ответ:
HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://normal-website.comБраузер позволит коду, запущенному на normal-website.com получить доступ к ответу, потому что источники совпадают.
Спецификация Access-Control-Allow-Origin допускает несколько источников, значение null или подстановочный знак *. Однако ни один браузер не поддерживает несколько источников, и существуют ограничения на использование подстановочного знака *.
Обработка запросов ресурсов из разных источников с учётными данными
Поведение по умолчанию для запроса ресурсов из разных источников заключается в том, что запросы передаются без учётных данных, таких как файлы cookie и заголовок авторизации. Однако междоменный сервер может разрешить чтение ответа, когда ему передаются учётные данные, установив для заголовка CORS Access-Control-Allow-Credentials значение true. Теперь, если запрашивающий веб-сайт использует JavaScript, чтобы объявить, что он отправляет файлы cookie с запросом:
GET /data HTTP/1.1
Host: robust-website.com
...
Origin: https://normal-website.com
Cookie: JSESSIONID=<value>И ответ на запрос:
HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://normal-website.com
Access-Control-Allow-Credentials: trueЗатем браузер разрешит запрашивающему веб-сайту прочитать ответ, потому что для заголовка ответа Access-Control-Allow-Credentials установлено значение true. В противном случае браузер не разрешит доступ к ответу.
Ослабление спецификации CORS с помощью подстановочных знаков
Заголовок Access-Control-Allow-Origin поддерживает подстановочные знаки. Например:
Access-Control-Allow-Origin: *Обратите внимание, что подстановочные знаки нельзя использовать внутри любого другого значения. Например, следующий заголовок не валидный:
Access-Control-Allow-Origin: https://*.normal-website.comК счастью, с точки зрения безопасности использование подстановочного знака ограничено в спецификации, поскольку вы не можете комбинировать подстановочный знак с передачей учётных данных между источниками (аутентификация, файлы cookie или сертификаты на стороне клиента). Следовательно, междоменный ответ сервера вида:
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: trueНе разрешён, так как это было бы небезопасно, так как любой аутентифицированный контент на целевом сайте будет доступен всем.
Учитывая эти ограничения, некоторые веб-серверы динамически задают заголовки Access-Control-Allow-Origin на основе указанного клиентом источника. Это обходной путь для ограничений CORS, который не является безопасным.
Предполётные проверки
Предполётная проверка была добавлена в спецификацию CORS для защиты устаревших ресурсов от расширенных параметров запроса, разрешённых CORS. При определённых обстоятельствах, когда междоменный запрос включает нестандартный HTTP-метод или заголовки, междоменному запросу предшествует запрос с использованием метода OPTIONS, а протокол CORS требует первоначальной проверки того, какие методы и заголовки разрешены перед тем, как разрешить запрос из разных источников. Это называется предполётной проверкой. Сервер возвращает список разрешённых методов в дополнение к доверенному источнику, и браузер проверяет, разрешён ли метод запрашивающего браузера.
Например, это предполётный запрос, который пытается использовать метод PUT вместе с настраиваемым заголовком запроса под названием Special-Request-Header:
OPTIONS /data HTTP/1.1
Host: <some website>
...
Origin: https://normal-website.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Special-Request-HeaderСервер может вернуть ответ, подобный следующему:
HTTP/1.1 204 No Content
...
Access-Control-Allow-Origin: https://normal-website.com
Access-Control-Allow-Methods: PUT, POST, OPTIONS
Access-Control-Allow-Headers: Special-Request-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 240В этом ответе устанавливаются разрешённые методы (PUT, POST и OPTIONS) и разрешённые заголовки запроса (Special-Request-Header). В этом конкретном случае междоменный сервер также разрешает отправку учётных данных, а заголовок Access-Control-Max-Age определяет максимальный период времени для кэширования ответа перед отправкой для повторного использования. Если методы запроса и заголовки разрешены (как в этом примере), то браузер обрабатывает запрос из разных источников обычным образом. Предполётные проверки добавляют к междоменному запросу дополнительный HTTP-запрос туда и обратно, поэтому они увеличивают накладные расходы при просмотре.
Защищает ли CORS от CSRF
CORS не обеспечивает защиту от атак с подделкой межсайтовых запросов (CSRF), это распространённое заблуждение.
CORS — это контролируемое ослабление политики единого источника (Same-origin policy), поэтому плохо настроенный CORS может увеличить вероятность атак CSRF или усугубить их воздействие.
Существуют различные способы выполнения CSRF-атак без использования CORS, включая простые HTML формы и междоменные ресурсы.
Дополнительная информация
- Что такое CORS (Cross-origin resource sharing)
- SOP: Что такое Same-origin policy
- CSRF: Как предотвратить уязвимость