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: Как предотвратить уязвимость