Урок по треку Безопасность приложений 7 мин

CSRF, SameSite и CORS

Как браузер отправляет куки, CSRF-токены, SameSite, проверка Origin и чем CORS не защищает от CSRF.

CSRF (cross-site request forgery) заставляет браузер жертвы отправить запрос на ваш сайт от её имени. Атакующий не видит ответа, но запрос выполнится с cookie жертвы: перевод денег, смена email, удаление данных.

Как это работает

Жертва залогинена на bank.ru, cookie сессии в браузере. Она открывает страницу атакующего, на которой:

<form action="https://bank.ru/transfer" method="POST">
  <input name="to" value="attacker"><input name="amount" value="10000">
</form>
<script>document.forms[0].submit()</script>

Браузер исторически прикладывал cookie bank.ru к любому запросу на bank.ru, откуда бы он ни шёл. Сервер видит валидную сессию и выполняет перевод.

Условия CSRF: аутентификация через то, что браузер прикладывает автоматически (cookie, HTTP Basic, клиентские сертификаты), и действие, которое можно вызвать предсказуемым запросом.

Защита

1. SameSite у cookie. Атрибут говорит браузеру, когда прикладывать cookie к межсайтовым запросам:

  • Strict: никогда. Надёжно, но пользователь, пришедший по ссылке из почты, окажется не залогинен.
  • Lax: только при навигации верхнего уровня безопасными методами (переход по ссылке GET). POST-форма с чужого сайта cookie не получит. Chrome и другие Chromium-браузеры используют Lax по умолчанию для cookie без атрибута.
  • None: всегда, только вместе с Secure. Нужен для встраиваемых виджетов и межсайтовых сценариев.

SameSite работает на уровне сайта (регистрируемый домен), а не origin: evil.example.com и app.example.com один сайт. Поддомен под контролем атакующего обходит SameSite.

2. CSRF-токен. Случайное значение, привязанное к сессии, кладётся в форму или заголовок и проверяется сервером. Сайт атакующего его не знает. Варианты: synchronizer token (хранится в сессии) и подписанный double submit cookie (токен в cookie и в заголовке, подпись привязывает к сессии). Сравнивать токены нужно за постоянное время.

3. Проверка Origin и Fetch Metadata. Браузер добавляет заголовок Origin к POST-запросам и Sec-Fetch-Site (same-origin, same-site, cross-site, none) к запросам в современных браузерах. Сервер может отклонять изменяющие запросы с чужим источником. Это хорошая дополнительная мера и основная для API.

4. Не менять состояние в GET. GET, HEAD, OPTIONS должны быть безопасными. Иначе <img src="/delete?id=1"> удалит данные, и SameSite Lax не поможет.

5. Повторное подтверждение для критичных действий: пароль, код из MFA.

Фреймворки (Django, Rails, Laravel, Spring Security) включают CSRF-защиту по умолчанию. Уязвимость часто появляется, когда её отключают («мешала тестам») или делают @csrf_exempt на эндпоинте.

Токены в заголовке

Если API аутентифицируется токеном в заголовке Authorization, который выставляет JavaScript, классический CSRF невозможен: браузер не добавит заголовок сам. Зато токен в localStorage доступен любому XSS. Выбор хранения это компромисс: cookie с HttpOnly и SameSite плюс защита от CSRF, или заголовок и строгая защита от XSS.

CORS не защищает от CSRF

CORS ослабляет политику одного источника (same-origin policy): разрешает чужим сайтам читать ответы. Он не мешает отправить запрос. Простые запросы (форма POST с application/x-www-form-urlencoded) уходят без preflight, и сервер их выполнит при любых настройках CORS.

Опасные ошибки CORS:

  • Отражать любой Origin в Access-Control-Allow-Origin вместе с Access-Control-Allow-Credentials: true: любой сайт читает данные пользователя.
  • Разрешать null origin (его отправляют песочницы и локальные файлы).
  • Проверять origin через endsWith("example.com"): пройдёт evilexample.com.

Звёздочку * браузер не разрешает вместе с credentials.

Частые ошибки

  • «У нас SPA и JSON, CSRF не страшен», а сервер принимает и формы.
  • Отключённая CSRF-защита фреймворка.
  • Изменяющие действия через GET.
  • CORS со всеми origin и credentials.

Что спросят на собесе

  • Как работает CSRF и какие условия нужны атакующему.
  • Чем Strict отличается от Lax.
  • Защищает ли CORS от CSRF.
  • Нужна ли защита от CSRF, если токен в заголовке Authorization.
  • Как правильно проверять Origin.

Закрепите за 5 минут

После урока в тренажёре 3-5 проверочных вопросов, дальше модуль уходит в повторения.