Что такое CSRF атака и как она работает
Что проверяют
Понимаете ли вы, что атака держится на автоматической отправке кук браузером, и отличаете ли её от XSS. Следом спрашивают, спасает ли SameSite, защищает ли CORS и уязвимо ли SPA, которое шлёт токен в заголовке.
Как отвечать
Механика: пользователь залогинен на bank.example, сессия лежит в куке. Он открывает чужую страницу, где спрятана автоотправляемая форма <form method="POST" action="https://bank.example/transfer">. Браузер прикладывает к запросу куку сессии, и сервер не отличает его от настоящего. Ответ атакующий прочитать не может, но ему это и не нужно: действие уже выполнено.
Защита складывается из слоёв:
SameSiteу сессионной куки:Laxне отправляет куку с межсайтовыми POST и фоновыми запросами,Strictне отправляет ни с какими межсайтовыми. Chrome считает куку без атрибутаLax, Firefox и Safari так не делают, поэтому атрибут задают явно;- CSRF-токен: случайное значение, привязанное к сессии. Сервер кладёт его в страницу или в читаемую куку, фронтенд возвращает в заголовке.
axiosи AngularHttpClientделают это сами: читают кукуXSRF-TOKENи шлют заголовокX-XSRF-TOKEN; - проверка
OriginиSec-Fetch-Site: эти заголовки ставит браузер, со стороннего сайта их не подделать. Так, например, Server Actions в Next.js сверяютOriginс хостом; - безопасные GET: при
Laxкука уходит при обычном переходе по ссылке, поэтому GET не должен ничего менять.
Если SPA держит токен в памяти или localStorage и отправляет его в Authorization, классический CSRF не сработает: браузер не подставляет такой заголовок сам. Зато этот токен уводится любой XSS.
Где спотыкаются
Считают защитой CORS. Он ограничивает чтение ответа, а простой POST из формы с application/x-www-form-urlencoded уходит без preflight и выполняется.
Называют защитой смену идентификатора сессии. Это мера против фиксации сессии, к CSRF она отношения не имеет.
Полагаются на Referer. Его режут прокси и Referrer-Policy: если пустой заголовок пропускать, атакующий его просто подавит, а если отклонять, пострадают честные пользователи. Origin надёжнее.