Я пытаюсь понять всю проблему с CSRF и соответствующие способы предотвратить это. (Ресурсы, которые я прочитал, понимаю и с которыми согласен: Шпаргалка по профилактике OWASP CSRF , Вопросы о CSRF .)
Насколько я понимаю, уязвимость вокруг CSRF вводится в предположении, что (с точки зрения веб-сервера) действительный файл cookie сеанса во входящем 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-файлов, кажется глупым. Фактически, если вы использовали файлы cookie в качестве транспорта туда и обратно (заголовок Set-Cookie: вниз по течению, чтобы сервер сообщал браузеру токен CSRF, и заголовок Cookie: вверх по течению, чтобы браузер возвратил его на сервер), вы бы снова представили уязвимость, которую вы пытаемся исправить.
Я понимаю, что вышеупомянутые фреймворки не используют куки-файлы для полного обхода токена CSRF; они используют Set-Cookie в нисходящем направлении, а затем что-то еще (например, заголовок X-CSRF-Token) в восходящем направлении, и это закрывает уязвимость. Но даже использование Set-Cookie в качестве нижестоящего транспорта потенциально вводит в заблуждение и опасно; теперь браузер будет прикреплять токен CSRF к каждому запросу, включая подлинные вредоносные запросы XSRF; в лучшем случае это делает запрос больше, чем нужно, а в худшем случае какой-то благонамеренный, но ошибочный кусок серверного кода может попытаться его использовать, что было бы очень плохо. И далее, поскольку фактическим предполагаемым получателем токена CSRF является клиентский Javascript, это означает, что этот файл cookie не может быть защищен только с помощью http.