Я пытаюсь понять всю проблему с CSRF и соответствующие способы ее предотвращения. (Ресурсы, которые я читал, понимал и соглашался с: OWASP CSRF Предупреждение CHeat Sheet, Вопросы о CSRF.)
Как я понимаю, уязвимость вокруг CSRF вводится по предположению, что (с точки зрения веб-сервера) допустимый куки файл сеанса в входящем HTTP-запросе отражает пожелания аутентифицированного пользователя. Но все файлы cookie для домена происхождения магически привязаны к запросу браузера, поэтому на самом деле весь сервер может вывести из присутствия допустимого сеансового файла cookie в запросе, что запрос поступает из браузера, который имеет аутентифицированный сеанс; он не может больше предположить что-либо о коде, запущенном в этом браузере, или он действительно отражает пожелания пользователя. Способ предотвращения этого заключается в том, чтобы включить в запрос дополнительную аутентификационную информацию ( "токен CSRF" ), переносимый некоторыми средствами, отличными от обработки автоматического cookie браузера. В то же время, cookie сеанса аутентифицирует пользователя/браузер, а токен CSRF аутентифицирует код, запущенный в браузере.
Итак, если вы используете cookie сеанса для аутентификации пользователей вашего веб-приложения, вы также должны добавить токен CSRF для каждого ответа и потребовать соответствующий токен CSRF в каждом (мутирующем) запросе. Затем токен CSRF выполняет обратную пересылку с сервера на браузер обратно на сервер, доказывая серверу, что страница, на которой выполняется запрос, сгенерирована (сгенерирована, даже) на этом сервере.
На мой вопрос, который касается конкретного метода транспорта, используемого для этого токена CSRF в этом обратном просмотре.
Это кажется общим (например, в AngularJS, Django, Rails), чтобы отправить токен CSRF с сервера на клиент в качестве файла cookie (то есть в заголовке Set-Cookie) а затем Javascript в клиенте очистите его из файла cookie и присоедините его как отдельный заголовок XSRF-TOKEN для отправки обратно на сервер.
(Альтернативный метод - тот, который рекомендуется, например, Express, где токен CSRF, сгенерированный сервером, включен в тело ответа через расширение шаблона на стороне сервера, прикрепленное непосредственно к коду/разметке, которое будет поставлять его обратно на сервер, например, в виде скрытого ввода формы. Этот пример представляет собой более простой способ делать что-то в Интернете, но обобщил бы его на больше JS-тяжелого клиента.)
Почему так часто используется Set-Cookie как транспортный поток для токена CSRF/почему это хорошая идея? Я полагаю, авторы всех этих концепций тщательно изучили свои варианты и не ошибались. Но на первый взгляд, использование файлов cookie для работы над тем, что по существу ограничивает дизайн файлов cookie, кажется глупым. Фактически, если вы использовали куки файлы в качестве транспорта в оба конца (Set-Cookie: заголовок вниз по течению для сервера, чтобы сообщить браузеру токен CSRF, а Cookie: заголовок вверх по течению для браузера, чтобы вернуть его на сервер), вы повторно введете уязвимость, которую вы пытаются исправить.
Я понимаю, что фреймворки выше не используют куки для всего обратного перехода для токена CSRF; они используют Set-Cookie downstream, затем что-то еще (например, заголовок X-CSRF-Token) вверх по течению, и это закрывает уязвимость. Но даже использование Set-Cookie в качестве нисходящего транспорта потенциально обманчиво и опасно; браузер теперь присоединяет токен CSRF к каждому запросу, включая настоящие вредоносные запросы XSRF; в лучшем случае это делает запрос больше, чем он должен быть, и в худшем случае какой-то здравомыслящий, но ошибочный фрагмент кода сервера действительно может попытаться его использовать, что было бы очень плохо. Кроме того, поскольку фактический предполагаемый получатель токена CSRF является клиентским Javascript, это означает, что этот файл cookie не может быть защищен только с помощью http-only. Поэтому отправка токена CSRF ниже по течению в заголовке Set-Cookie кажется мне довольно субоптимальным.