На странице авторизованного пользователя внешняя ссылка может незаметно отправить запрос, изменяющий его настройки. Какую защиту должен проверить тестировщик?
Тестировщик должен проверить защиту от CSRF — подделки межсайтовых запросов. Для изменяющих состояние операций сервер обычно должен требовать непредсказуемый CSRF-токен, связанный с пользовательской сессией, и отклонять запросы без корректного токена.
Одной проверки наличия cookie недостаточно: браузер может автоматически приложить cookie авторизации к запросу, инициированному с другого сайта.
Подход появился из-за модели браузера, в которой cookie сессии автоматически отправляются на соответствующий домен. Сайт-атакующий не обязан знать значение cookie: ему достаточно заставить браузер жертвы отправить запрос к доверенному приложению.
CSRF-защита решает исходную проблему доверия к запросу. Сервер должен отличать запрос, сформированный самим приложением, от запроса, случайно инициированного сторонним сайтом.
Если операция изменения настроек принимает только cookie авторизации, внешняя страница может инициировать такую операцию от имени уже вошедшего пользователя. В результате злоумышленник способен изменить адрес доставки, контактные данные, настройки уведомлений или другие параметры, доступные этой сессии.
Особенно опасна мутация состояния через GET: ссылки, изображения и автоматические переходы могут отправлять такие запросы без явного действия пользователя. Использование метода POST само по себе проблему не устраняет, поскольку форму POST также можно разместить на стороннем сайте.
Основной вариант — синхронный CSRF-токен: сервер генерирует непредсказуемое значение, связывает его с сессией и ожидает этот токен в каждом изменяющем состояние запросе. Атакующий сайт обычно может вызвать запрос, но не может прочитать содержимое доверенной страницы и получить оттуда токен из-за политики браузера об одинаковом источнике.
При тестировании нужно отправить изменяющий запрос без токена, с пустым токеном, с токеном другой сессии и с изменённым токеном. Во всех случаях сервер должен отклонять запрос и не менять состояние. Также проверяют, что токен не принимается из неподходящего места без предусмотренной сервером проверки и не становится доступным через URL, логи или открытые страницы.
Дополнительной защитой служит атрибут SameSite для cookie. Он ограничивает отправку cookie в межсайтовых сценариях, но не должен быть единственной универсальной защитой: поведение зависит от выбранного режима, типа перехода и поддерживаемых браузеров. Проверки заголовков Origin или Referer также полезны как дополнительный барьер, но требуют корректной обработки случаев отсутствия или ограничения раскрытия этих заголовков.
Если приложение использует только явно передаваемый токен авторизации в заголовке, а браузер не прикладывает его автоматически как cookie, классический CSRF-риск обычно существенно ниже. Однако это не отменяет проверки других уязвимостей, включая XSS, через которую злоумышленник может действовать в контексте доверенного источника.
Защита должна применяться ко всем операциям, меняющим состояние, включая изменение профиля, создание или удаление объектов, смену реквизитов и выполнение административных действий. Для безопасных операций чтения CSRF-токен обычно не требуется, но изменение данных через GET следует устранить.
В приложении смена адреса доставки выполнялась POST-запросом, но сервер проверял только cookie сессии. Рассматривались три варианта: полагаться на POST, установить SameSite для cookie или добавить CSRF-токен.
Переход на POST не решил бы проблему, поскольку внешний сайт всё ещё мог отправить форму. Один только SameSite уменьшил бы риск в современных браузерах, но оставил бы зависимость от режима cookie и особенностей клиентов.
Выбранным решением стал обязательный токен, связанный с сессией, дополненный настройкой SameSite и проверкой Origin там, где заголовок доступен. Тесты подтвердили, что запрос без токена отклоняется, запрос с токеном другой сессии не принимается, а легитимная операция из приложения продолжает работать.
1. Достаточно ли заменить GET на POST, чтобы устранить CSRF?
Нет. POST снижает риск случайных изменений через обычные ссылки и ресурсы, но внешняя страница может создать и автоматически отправить HTML-форму методом POST. Поэтому для операций, меняющих состояние, нужен отдельный механизм проверки происхождения запроса, обычно CSRF-токен.
2. Защищает ли CORS от CSRF?
Не обязательно. CORS в первую очередь управляет тем, может ли скрипт прочитать ответ другого источника; он не запрещает все виды отправки межсайтовых запросов. Простая форма или другой разрешённый браузером механизм может отправить запрос, поэтому CORS не заменяет CSRF-защиту.
3. Почему токен должен быть связан с сессией, если он просто непредсказуем?
Непредсказуемость мешает атакующему угадать значение, но сама по себе не гарантирует, что сервер проверяет принадлежность токена конкретному пользователю. Если сервер принимает один и тот же или чужой действительный токен, защита может быть обойдена. Связь токена с сессией, сроком действия или конкретной формой позволяет убедиться, что токен выдан именно для текущего контекста запроса.