Информационная безопасность

CSRF, SSRF, CORS

2019 год. Capital One. Один из крупнейших банков США. Атакующий находит в облачном приложении функцию загрузки URL и передаёт адрес AWS metadata-сервиса: http://169.254.169.254/latest/meta-data/iam/security-credentials/. Сервер послушно делает запрос, получает IAM-ключи, возвращает результат. Утекает 106 миллионов записей клиентов. Штраф: 80 млн долларов. Инструмент атаки - SSRF, три буквы, о которых не знал ни один из разработчиков системы.

  • **Capital One 2019:** SSRF через WAF дал IAM credentials и утечку 106 млн записей - первый крупный SSRF на облачную инфраструктуру
  • **Linksys CSRF 2008:** вредоносные сайты меняли DNS-настройки 200 000 маршрутизаторов через CSRF без единого клика пользователя
  • **Facebook SSRF 2016:** bug bounty 31 500 долларов за SSRF, позволявший читать внутренние сервисы - награда выплачена за этичный репорт

CSRF: когда браузер становится оружием

2008 год. Маршрутизаторы Linksys по всему миру меняют DNS-серверы без ведома владельцев. Вектор атаки: пользователь открывает вредоносный сайт, браузер автоматически отправляет POST-запрос на `http://192.168.1.1/admin/dns` с куками от предыдущей сессии. Маршрутизатор верит куке. Это **Cross-Site Request Forgery**.

**CSRF** эксплуатирует то, что браузер автоматически добавляет cookies к каждому запросу. Если пользователь залогинен в bank.com, а на evil.com есть форма, POST-запрос на bank.com придёт с валидным session cookie. Сервер не может отличить легитимный запрос от поддельного.

Метод защитыПринципНадёжность
CSRF-токенСекрет, известный только серверу и легитимной страницеВысокая - стандарт
SameSite=StrictБраузер блокирует cookie при cross-site запросахВысокая для современных браузеров
SameSite=LaxБлокирует POST, разрешает GET-навигациюДостаточно для большинства случаев
Double Submit CookieСравнение cookie и параметра запросаСредняя - обходится при subdomain takeover
Origin/Referer checkПроверка заголовка источника запросаСлабая - заголовки можно отсутствовать

**SameSite=Lax** теперь стандарт по умолчанию в Chrome/Firefox/Safari. Это значительно снизило prevalence CSRF. Но legacy-системы, custom auth-протоколы и mobile WebView - всё ещё уязвимы. CSRF-токены остаются необходимыми для state-changing действий.

Сайт использует JWT в localStorage (не в cookie) для авторизации. Уязвим ли он к CSRF?

Same-Origin Policy: изоляция браузера

**Same-Origin Policy (SOP)** - фундаментальный механизм безопасности браузера. JavaScript на `evil.com` не может читать ответы с `bank.com`. Без SOP любой сайт мог бы читать почту Gmail, переводить деньги, красть куки. SOP определяет "origin" как комбинацию: протокол + домен + порт.

**SOP блокирует чтение, не отправку.** CSRF возможен именно потому, что SOP не запрещает браузеру отправлять cross-origin POST-запросы. Запрещено только читать ответ. Для state-changing операций этого достаточно - ответ не нужен, достаточно что сервер выполнил действие.

JavaScript на `https://app.example.com` делает fetch к `https://api.example.com/data`. SOP блокирует этот запрос?

SSRF: сервер как прокси для атакующего

2019 год. Capital One. Облачный WAF принимает URL от пользователя и делает запрос к нему. Атакующий передаёт `http://169.254.169.254/latest/meta-data/` - адрес metadata-сервиса AWS EC2. Сервер возвращает IAM-credentials. Утекло 106 миллионов записей клиентов. Это **Server-Side Request Forgery (SSRF)**.

**SSRF** - атака, при которой сервер делает HTTP-запрос к произвольному адресу, указанному пользователем. Сервер работает изнутри сети, имеет доступ к внутренним сервисам, облачным metadata API, localhost. SSRF в OWASP Top 10 2021 - новая позиция, отдельная от других инъекций.

**DNS Rebinding** обходит IP-фильтрацию SSRF: на первый DNS-запрос домен attacker.com отдаёт публичный IP (проходит whitelist), на второй - 169.254.169.254. Браузер/сервер кешируют первый ответ, но при истечении TTL получают внутренний IP. Mitigation: DNS pinning + двойная проверка IP после резолва.

Приложение на AWS принимает URL для загрузки изображения. Разработчик добавил проверку: URL должен начинаться с https://. Достаточна ли эта защита от SSRF?

CORS: настройка исключений из SOP

SOP запрещает cross-origin запросы по умолчанию. Но реальная архитектура требует: фронтенд на `app.example.com` обращается к API на `api.example.com`. Решение - **CORS (Cross-Origin Resource Sharing)**: сервер явно разрешает определённые origins через HTTP-заголовки. Браузер проверяет эти заголовки и снимает ограничение SOP.

**Portswigger исследование 2018:** 40% публичных API имеют misconfigured CORS, позволяющий произвольным origins читать ответ. Самый частый паттерн: `if (req.headers.origin) { res.set('ACAO', req.headers.origin); }` - полное зеркало без проверки. Это даёт любому сайту доступ к API с credentials пользователя.

**CORS не защищает сервер** - это защита браузера для пользователя. Curl, Postman, Burp Suite игнорируют CORS-заголовки. CORS говорит браузеру, можно ли JavaScript-коду на одном сайте читать ответ с другого. Server-side защита от несанкционированного доступа - всё равно AuthN/AuthZ.

CORS - это защита от CSRF, и правильная настройка CORS предотвращает cross-site атаки

CORS и CSRF - разные механизмы с разными целями. CORS управляет чтением cross-origin ответов браузером. CSRF атакует через отправку запросов с cookies. Misconfigured CORS может усилить CSRF, но правильный CORS не защищает от него.

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

Разработчик настроил CORS: `Access-Control-Allow-Origin: *`. В чём проблема?

Ключевые идеи

  • **CSRF** использует автоматические cookies браузера: вредоносный сайт делает запрос от имени пользователя. Защита: CSRF-токены + SameSite=Lax/Strict cookie
  • **Same-Origin Policy** блокирует чтение cross-origin ответов, но не отправку. Origin = протокол + домен + порт. Поддомены - разные origins
  • **SSRF** заставляет сервер делать запросы к внутренним сервисам и metadata API. Capital One потерял 106 млн записей через http://169.254.169.254/. Защита: whitelist + IP-проверка + egress firewall
  • **CORS** - механизм исключений из SOP. Misconfigured CORS (зеркало Origin) даёт любому сайту доступ к API с credentials. CORS не защищает от CSRF

Связанные темы

CSRF, SSRF и CORS - механизмы доверия в веб-архитектуре:

  • SQL Injection — Предыдущий класс атак - инъекции в запросы к БД
  • XSS — XSS часто используется для обхода SameSite и усиления CSRF
  • Безопасность API — CORS-политика и защита от CSRF - критичны для REST/GraphQL API

Вопросы для размышления

  • Текущее приложение принимает URL от пользователя (аватар, превью, webhook)? Как валидируется что IP не принадлежит внутренней сети?
  • Какая CORS-конфигурация используется? Есть ли в коде `res.setHeader('ACAO', req.headers.origin)` без проверки?
  • SameSite=Lax установлен для session-cookie? Если нет - каков план миграции без поломки функциональности?

Связанные уроки

  • sec-07 — SQLi - предыдущий класс веб-атак, паттерн инъекции
  • sec-09 — XSS часто используется вместе с CSRF для полноценной атаки
  • sec-03 — CSRF обходит AuthZ - пользователь авторизован, но не знает о запросе
  • sec-17 — Безопасность API: CORS и CSRF критичны для REST/GraphQL
  • net-22-http-headers
CSRF, SSRF, CORS

0

1

Войти