Рассматриваем лучшие практики и меры безопасности, которые нужно соблюдать, чтобы обезопасить веб-приложения от уязвимостей при использовании механизма межсайтовых запросов (CORS)
В современных веб-приложениях часто используется JavaScript, благодаря чему они становятся динамическими и обеспечивают более удобное взаимодействие с пользователем. Зачастую, чтобы предоставить пользователям контент и данные, веб-приложению требуется взаимодействие с другими веб-приложениями, что подразумевает межсайтовые запросы и настройку правил совместного использования ресурсов разными источниками (Cross-Origin Resource Sharing, CORS) со стороны этого приложения.
В этой статье будет рассмотрено, как неправильная настройка CORS-правил может сделать веб-приложение уязвимым, и как Tenable.io Web Application Scanner (WAS) помогает выявлять такие уязвимости.
История CORS
Модель безопасности веб-приложений, реализованная браузерами, основана на нескольких концепциях. Одна из наиболее важных — правило единого источника (Same-Origin Policy, SOP). SOP ограничивает взаимодействие между скриптами, загруженными с исходного источника, и ресурсами, размещенным на других источниках. Исходный источник определяется тремя элементами: протокол, имя хоста и порт.
Исходный источник = протокол + имя хоста + порт
CORS — это стандарт, определенный Консорциумом Всемирной паутины (W3C), который является дополнением к SOP. Он позволяет серверу определять, какие внешние приложения могут загружать с него ресурсы, и добавлять их в разрешенный список.
CORS реализуется с помощью HTTP-заголовков, которыми обмениваются клиент и приложение. Простой пример реализации CORS: браузер загружает веб-страницу, которая запрашивает внешние ресурсы с другого домена, затем браузер отправляет этим внешним ресурсам запрос с HTTP-заголовком Origin. Ответ целевого приложения на сервере будет содержать заголовок Access-Control-Allow-Origin, который определяет, каким источникам разрешено загружать этот ресурс. В некоторых случаях в ответе может быть еще заголовок Access-Control-Allow-Credentials, он указывает, разрешено ли вызывающему скрипту попросить браузер добавить учетные данные (например, куки, заголовки авторизации или TLS-сертификаты клиента) в кросс-доменный запрос. При получении ответа от внешнего ресурса клиентский браузер разрешает исходной странице читать ответ внешнего ресурса или блокирует его в соответствии с настройками политики CORS.
Сложные запросы с определенными HTTP-методами, такими как PUT и DELETE, или с пользовательскими HTTP-заголовками, требуют отправки предварительного запроса (preflight request). Этот запрос использует метод OPTIONS и проверяет, настроена ли политика CORS в целевом приложении сервера, и поддерживаются ли опции, упомянутые в запросе.
В такой ситуации ответ целевого приложения содержит дополнительные заголовки, например, Access-Control-Allow-Methods, который определяет разрешенные HTTP-методы при кросс-доменных запросах.
Основной запрос будет отправлен целевому приложению на сервере после получения ответа на предварительный.
Распространенные уязвимости
Из-за неправильной настройки механизма CORS злоумышленник может обойти его и использовать клиентский браузер как прокси между вредоносным сайтом и атакуемым веб-приложением. Чаще всего подобные риски недооцениваются, и они сильно возрастают, когда веб-приложение разрешает отправлять аутентифицированные запросы.
Одной из наиболее распространенных ошибок является значение в заголовке Access-Control-Allow-Origin, которое уязвимое приложение отправляет браузеру. В приведенном ниже списке описаны наиболее распространенные ошибки при настройке CORS-правил:
- При использовании в заголовке Access-Control-Allow-Origin подстановочного символа wildcard (*) любому источнику разрешается читать ответы на кросс-доменные запросы. В спецификации CORS предусмотрена дополнительная защита на этот случай: она запрещает устанавливать значение “true” для заголовка Access-Control-Allow-Credentials.
- Использование значения “null” в надежде, что такое значение не дает возможности отправить кросс-доменный запрос. Наоборот, такая конфигурация приводит к таким же результатам, что и использование wildcard. При некоторых обстоятельствах веб-браузеры автоматически присваивают источнику значение “null” , например, после перенаправления CORS-запроса уязвимым ресурсом, или когда этот запрос был отправлен с ресурса определенного типа (например, из iframe или локального файла).
- Построение динамического заголовка Access-Control-Allow-Origin с неправильной проверкой на стороне сервера. Спецификация определяет только один источник в заголовке ответа Access-Control-Allow-Origin. При необходимости предоставлять доступ нескольким источникам разработчики должны решать проблему динамической проверки источника с помощью регулярных выражений на основе домена целевого веб-приложения.
В случае неправильной конфигурации регулярное выражение может, например, неявно разрешить имя хоста, производное от имени целевого приложения. В других ситуациях заголовок Origin, отправленный браузером, просто копируется внешним приложением, что приводит к тем же последствиям, что и использование wildcard-значения. Это распространенный трюк для обхода проверки CORS, которая мешает использованию wildcard-списка и учетных данных.
- Слепое доверие сторонним публичным сервисам. В политике CORS иногда разрешается доступ к публичным хостинговым инфраструктурам, таким как облака (бакеты хранения), сети доставки контента (CDN) или сервисы для хостинга кода. Эти публичные сервисы доступны и для потенциального злоумышленника, который может использовать их для размещения вредоносного JavaScript-кода и выполнения кросс-доменных запросов к уязвимому приложению.
Эксплуатация CORS-уязвимостей
Далее приводятся риски и негативные последствия, связанные с неправильной конфигурацией CORS.
Распространенные сценарии эксплуатации уязвимостей CORS состоят из следующих этапов:
- Злоумышленник создает вредоносный сайт с JavaScript-кодом, который должен извлечь данных из целевого (уязвимого) веб-приложения.
- Злоумышленник заманивает жертву на этот сайт с помощью фишинга или непроверенного перенаправления в уязвимом приложении.
- Затем JavaScript загружается в браузер жертвы и выполняет незаметные кросс-доменные аутентифицированные запросы к уязвимому приложению, чтобы украсть и сохранить данные.
Риск возрастает, когда правила CORS разрешают использовать запросы с учетными данными, однако могут быть ситуации, когда даже один непроверенный источник может привести к серьезным последствиям. Например, уровень защиты веб-приложений во внутренней сети компании иногда не соответствует стандартам ИБ. Они могут предоставлять доступ к внутреннему содержимому корпоративной сети любому ее пользователю без аутентификации. Таким образом, если у приложения неправильно настроен механизм CORS, то посещение вредоносного внешнего сайта, который отправляет CORS-запрос на внутренний сайт, может привести к утечке информации.
Утечка информации — это самый простой способ эксплуатации уязвимостей CORS. Также злоумышленники часто используют подобные уязвимости для продвинутых атак, которые могут привести к краже учетных записей пользователей или выполнения несанкционированных изменений в целевом приложении от имени взломанного пользователя. В этом году Крис Лайн, старший инженер-исследователь команды Tenable Zero Day Research Team, выявил уязвимость в Plex Media Server, связанную с политикой CORS, и рассказал о возможных рисках для пользователей этого приложения.
Использование Tenable.io WAS для обнаружения CORS-уязвимостей
Tenable.io WAS помогает выявить CORS-уязвимости с помощью множества плагинов (проверок). Две главные задачи таких проверок заключаются в следующем:
- В соответствии с лучшими практиками проверить, что значения заголовка Access-Control-Allow-Origin разрешают не слишком широкий доступ для других ресурсов.
- Удостовериться в правильности проверки источника, используя наиболее распространенные способы обхода политики, известные команде Tenable Research.
После обнаружения уязвимости CORS платформа Tenable.io WAS предоставляет информацию, которая поможет определить конфигурацию, подлежащую исправлению, и руководство по устранению уязвимости.
В целом, уязвимости CORS – это ошибки конфигурации, которые можно легко устранить, если следовать следующим принципам:
- Если приложение не требует обмена данными между разными источниками запросов, то нужно лишь убедиться, что политика не установлена.
- Заголовок Access-Control-Allow-Origin должен разрешать только конкретные источники и не открывать слишком большой доступ. Значение wildcard должно подставляться только тогда, когда весь контент приложения является общедоступным.
- Значения заголовка Access-Control-Allow-Methods должны быть ограничены в соответствии с требованиями приложения.
- Лучше использовать только проверенные источники. По умолчанию публичные облачные провайдеры или сервисы вроде GitHub Pages не должны находиться в «зоне доверия» при настройке CORS.
- Устанавливайте значение “true” для заголовка Access-Control-Allow-Credentials только при необходимости и после проверки значений в Access-Control-Allow-Origin.
Наконец, важно отметить, что CORS сам по себе не является защитным механизмом и для его правильной работы по-прежнему нужно придерживаться лучших практик по защите веб-приложений.
Хотите узнать больше о веб-сканере Tenable.io?
Закажите расчет, демо или тестирование Tenable.io по этой ссылке.