Почему в cookies часто помещают токены предотвращения CSRF?
Я пытаюсь понять всю проблему с CSRF и соответствующие способы ее предотвращения. (Ресурсы, которые я прочитал, понял и согласен с: OWASP CSRF профилактика шпаргалка, вопросы о CSRF.)
Как я понимаю, уязвимость вокруг CSRF вводится предположением, что (с точки зрения веб-сервера) допустимый файл cookie сеанса во входящем HTTP-запросе отражает пожелания аутентифицированного пользователя. Но всех cookies исходный домен волшебным образом присоединен к запросу браузером, поэтому на самом деле все, что сервер может сделать из наличия действительного файла cookie сеанса в запросе, - это то, что запрос исходит из браузера, который имеет аутентифицированный сеанс; он не может далее ничего предположить о код работает в этом браузере, или действительно ли он отражает пожелания пользователя. Способ предотвратить это-включить дополнительную информацию аутентификации ("токен CSRF") в запрос, выполняемый некоторые средства, отличные от автоматической обработки файлов cookie браузера. Грубо говоря, cookie сеанса аутентифицирует пользователя / браузер, а токен CSRF аутентифицирует код, запущенный в браузере.
Итак, в двух словах, если вы используете cookie сеанса для аутентификации пользователей вашего веб-приложения, вы также должны добавить токен CSRF к каждому ответу и потребовать соответствующий токен CSRF в каждом (мутирующем) запросе. Затем токен CSRF совершает обратный путь от сервера к браузеру на сервер, доказывая серверу, что страница, делающая запрос, одобрена (сгенерирована, даже) этим сервером.
на мой вопрос, который касается конкретного транспортного метода, используемого для этого токена CSRF на этом круговом пути.
похоже, здравый (например,AngularJS, Джанго, рейлинги) для отправки токена CSRF с сервера клиенту в виде файла cookie( т. е. в заголовке Set-Cookie), а затем Javascript в клиенте очищает его из файла cookie и прикрепите его как отдельный заголовок XSRF-TOKEN для отправки обратно на сервер.
(альтернативный метод рекомендуется, например,Экспресс, где токен CSRF, сгенерированный сервером, включен в тело ответа через расширение шаблона на стороне сервера, прикрепленный непосредственно к коду/разметке, который будет поставлять его обратно на сервер, например, в качестве скрытого ввода формы. Этот пример-более Веб-1.0-ish способ делать вещи, но обобщил бы штраф на более ИС-тяжелый клиент.)
Почему так часто используется Set-Cookie в качестве нисходящего транспорта для токена CSRF / почему это хорошая идея? Я предполагаю, что авторы всех этих фреймворков тщательно рассмотрели свои варианты и не ошиблись. Но на первый взгляд, использование cookies для работы вокруг того, что по сути является ограничением дизайна cookies, кажется глупым. Фактически, если вы использовали cookies в качестве транспорта туда и обратно (Set-Cookie: заголовок вниз по течению для сервера, чтобы сообщить браузеру CSRF маркер и Cookie: заголовок вверх по течению для браузера, чтобы вернуть его на сервер) вы бы повторно ввести уязвимость, которую вы пытаетесь исправить.
Я понимаю, что вышеприведенные фреймворки не используют cookies для всего раунда для токена CSRF; они используют Set-Cookie вниз по течению, а затем что-то еще (например, заголовок X-CSRF-Token) вверх по течению, и это закрывает уязвимость. Но даже использование Set-Cookie в качестве нисходящего транспорта потенциально вводит в заблуждение и опасно; браузер теперь будет прикреплять токен CSRF к каждому запросу, включая подлинные вредоносные запросы XSRF; в лучшем случае это делает запрос больше, чем он должен быть, и в худшем случае какой-то благонамеренный, но ошибочный кусок кода сервера может фактически попытаться использовать его, что было бы очень плохо. Кроме того, поскольку фактическим получателем токена CSRF является клиентский Javascript, это означает, что этот файл cookie не может быть защищен только http. Поэтому отправка токена CSRF вниз по течению в заголовке Set-Cookie кажется довольно неоптимально для меня.
3 ответов
хорошая причина, которую вы вроде как коснулись, заключается в том, что после получения файла cookie CSRF он доступен для использования во всем приложении в клиентском скрипте для использования как в обычных формах, так и в сообщениях AJAX. Это будет иметь смысл в тяжелом приложении JavaScript, таком как один, используемый AngularJS (использование AngularJS не требует, чтобы приложение было одностраничным приложением, поэтому было бы полезно, когда состояние должно протекать между различными запросами страницы, где значение CSRF не может нормально сохраняться в браузере).
рассмотрим следующие сценарии и процессы в типичном приложении для некоторых плюсов и минусов каждого подхода, который вы описываете. Они основаны на Шаблон Токена Синхронизатора.
Запрос Тела Подход
- пользователь успешно входит в систему.
- сервер выдает файл cookie auth.
- пользователь щелкает для перехода к форме.
- если еще не создан для этого сеанса, сервер генерирует токен CSRF, сохраняет его в сеансе пользователя и выводит его в скрытое поле.
- пользователь отправляет форму.
- сервер проверяет скрытые поля, совпадающие с сохраненным токеном сеанса.
плюсы:
- прост в реализации.
- работает с AJAX.
- работает с формами.
- Cookie на самом деле может быть протоколу HTTP Только.
недостатки:
- все формы должны выводить скрытое поле в HTML.
- любые сообщения AJAX также должны включать значение.
- страница должна заранее знать, что ей требуется токен CSRF, чтобы она могла включить его в содержимое страницы, поэтому все страницы должны содержать значение токена где-то, что может занять много времени для реализации для большого сайта.
пользовательский заголовок HTTP (вниз по течению)
- пользователь успешно входит в систему.
- сервер выдает файл cookie auth.
- пользователь щелкает для перехода к форме.
- страница загружается в браузере, затем выполняется запрос AJAX для получения токена CSRF.
- сервер генерирует токен CSRF (если он еще не сгенерирован для сеанса), сохраняет его против сеанса пользователя и выводит его на заголовок.
- пользователь отправляет форму (токен отправляется через скрытое поле).
- сервер проверяет скрытые поля, совпадающие с сохраненным токеном сеанса.
плюсы:
- работает с AJAX.
- "cookie" может быть только HTTP.
недостатки:
- не работает без запроса AJAX для получения значения заголовка.
- все формы должны иметь значение, добавленное к его HTML динамически.
- любой AJAX Должности должны также включать значение.
- страница должна сначала сделать запрос AJAX, чтобы получить токен CSRF, поэтому это будет означать дополнительную поездку туда и обратно каждый раз.
- можно было бы просто вывести токен на страницу, которая сохранит дополнительный запрос.
пользовательский HTTP-заголовок (вверх по течению)
- пользователь успешно входит в систему.
- сервер выдает файл cookie auth.
- пользователь щелкает для перехода к форме.
- если еще не сгенерирован для этого сеанса, сервер генерирует токен CSRF, сохраняет его против сеанса пользователя и выводит его в содержимое страницы где-то.
- пользователь отправляет форму через AJAX (токен отправляется через заголовок).
- сервер проверяет, соответствует ли пользовательский заголовок сохраненному токену сеанса.
плюсы:
- работает с AJAX.
- "cookie" может быть протоколу HTTP Только.
недостатки:
- не работает с формами.
- все сообщения AJAX должны включать заголовок.
пользовательский HTTP-заголовок (вверх и вниз по течению)
- пользователь успешно входит в систему.
- сервер выдает файл cookie auth.
- пользователь щелкает для перехода к форме.
- страница загружается в браузере, затем выполняется запрос AJAX для получения CSRF знак.
- сервер генерирует токен CSRF (если он еще не сгенерирован для сеанса), сохраняет его против сеанса пользователя и выводит его на заголовок.
- пользователь отправляет форму через AJAX (токен отправляется через заголовок).
- сервер проверяет, соответствует ли пользовательский заголовок сохраненному токену сеанса.
плюсы:
- работает с AJAX.
- "cookie" может быть протоколу HTTP Только.
недостатки:
- не работает с формами.
- все сообщения AJAX также должны включать значение.
- страница должна сначала сделать запрос AJAX, чтобы получить токен CRSF, поэтому это будет означать дополнительную поездку туда и обратно каждый раз.
Set-Cookie
- пользователь успешно входит в систему.
- сервер выдает файл cookie auth.
- пользователь нажимает кнопку, чтобы перейти к форме.
- сервер генерирует токен CSRF, сохраняет его в сеансе пользователя и выводит его в файл cookie.
- пользователь отправляет форму через AJAX или через HTML-форму.
- сервер проверяет пользовательский заголовок (или скрытое поле формы) соответствует сохраненному токену сеанса.
- Cookie доступен в браузере для использования в дополнительных запросах AJAX и form без дополнительных запросов к серверу для получения CSRF знак.
плюсы:
- прост в реализации.
- работает с AJAX.
- работает с формами.
- не обязательно требует запроса AJAX для получения значения cookie. Любой HTTP-запрос может получить его, и он может быть добавлен ко всем формам / AJAX-запросам через JavaScript.
- после извлечения маркера CSRF, так как он хранится в файле cookie, значение можно использовать повторно без дополнительных запросы.
недостатки:
- все формы должны иметь значение, добавленное к его HTML динамически.
- любые сообщения AJAX также должны включать значение.
- файл cookie будет отправлен для запрос (т. е. все получает для изображений, CSS, JS и т. д., которые не участвуют в процессе CSRF) увеличение размера запроса.
- Cookie не может быть протоколу HTTP Только.
таким образом, подход cookie довольно динамичен, предлагая простой способ получить значение cookie (любой HTTP-запрос) и использовать его (JS может автоматически добавлять значение в любую форму, и его можно использовать в AJAX-запросах либо как заголовок, либо как значение формы). После получения маркера CSRF для сеанса нет необходимости его регенерировать, поскольку злоумышленник, использующий эксплойт CSRF, не имеет метода извлечения этого маркера. Если злоумышленник пытается прочитать токен CSRF пользователя в любом из вышеуказанных методов, то это будет предотвращено Та Же Политика Происхождения. Если вредоносный пользователь пытается получить серверную сторону токена CSRF (например, через curl
) тогда этот токен не будет связан с той же учетной записью пользователя, что и файл cookie сеанса аутентификации жертвы, который будет отсутствовать в запросе (это будет файл злоумышленника, поэтому он не будет связан с сервером с сеансом жертвы).
а также синхронизатор Шаблон Токена есть еще Дважды Отправить Cookie метод предотвращения CSRF, который, конечно, использует куки для хранения типа токена CSRF. Это проще реализовать, поскольку для маркера CSRF не требуется состояние на стороне сервера. Токен CSRF фактически может быть стандартным cookie аутентификации при использовании этого метода, и это значение передается через cookie, как обычно с запросом, но значение также повторяется в скрытом поле или заголовке, из которых злоумышленник не может реплицироваться, поскольку они не могут прочитать значение в первую очередь. Однако рекомендуется выбрать другой файл cookie, отличный от файла cookie проверки подлинности, чтобы файл cookie проверки подлинности можно было защитить, пометив HttpOnly. Таким образом, это еще одна распространенная причина, по которой вы найдете CSRF-предотвращение с помощью метода на основе файлов cookie.
использование файла cookie для предоставления клиенту маркера CSRF не позволяет успешно атаковать, поскольку злоумышленник не может прочитать значение файла cookie и, следовательно, не может поместить его в место, требуемое для проверки CSRF на стороне сервера.
злоумышленник сможет вызвать запрос на сервер как с файлом cookie маркера аутентификации, так и с файлом CSRF в заголовках запроса. Но сервер не ищет токен CSRF в качестве файла cookie в заголовках запросов, он ищет в код запроса. И даже если злоумышленник знает, куда поместить токен CSRF в полезную нагрузку, им придется прочитать его значение, чтобы поместить его туда. Но политика кросс-происхождения браузера предотвращает чтение любого значения cookie с целевого веб-сайта.
та же логика не применяется к cookie токена auth, потому что сервер ожидает его в заголовках запросов, и злоумышленнику не нужно делать ничего особенного, чтобы поместить его туда.
мое лучшее предположение относительно ответа: рассмотрите эти 3 варианта того, как получить токен CSRF с сервера в браузер.
- в теле запроса (не HTTP-заголовок).
- в пользовательском заголовке HTTP, а не Set-Cookie.
- как cookie, в заголовке Set-Cookie.
Я думаю, что 1-й, тело запроса (в то время как продемонстрировано Экспресс-учебник, который я связал в вопросе), не как портативно к большому разнообразию не все генерируют каждый HTTP-ответ динамически; где вам в конечном итоге нужно поместить токен в сгенерированный ответ, может сильно отличаться (в скрытой форме ввода; во фрагменте кода JS или переменной, доступной другим кодом JS; возможно, даже в URL-адресе, хотя это, как правило, плохое место для размещения токенов CSRF). Таким образом, в то время как работоспособный с некоторой настройкой, #1-это трудное место для использования единого подхода.
второй, пользовательский заголовок, привлекателен, но не работает, потому что хотя JS может получить заголовки для XHR, который он вызвал, он не может получить заголовки для страницы, которую он загрузил из.
Это оставляет третий, cookie, переносимый заголовком Set-Cookie, как подход, который прост в использовании во всех ситуациях (любой сервер сможет установить заголовки cookie для каждого запроса, и не имеет значения, какие данные находятся в теле запроса). Поэтому, несмотря на свои недостатки, это был самый простой способ для фреймворков широко внедрять.