2013-12-10 2 views
154

Я пытаюсь понять всю проблему с CSRF и соответствующие способы ее предотвращения. (Ресурсы, которые я прочитал, понимаю и согласен с:. OWASP CSRF Prevention CHeat Sheet, Questions about CSRF)Почему распространено помещать токены CSRF в файлы cookie?

Как я понимаю, уязвимость вокруг CSRF вводится в предположении, что (с точки Вебсервер зрения) действительный куки сессии в входящий HTTP-запрос отражает пожелания аутентифицированного пользователя. Но все файлы cookie для домена происхождения магически привязаны к запросу браузера, поэтому на самом деле весь сервер может вывести из присутствия допустимого сеансового файла cookie в запросе, что запрос поступает из браузера, который имеет аутентифицированный сеанс; он не может больше предположить что-либо о код, работающий в этом браузере, или он действительно отражает пожелания пользователей. Способ предотвращения этого состоит в том, чтобы включить в запрос дополнительную аутентификационную информацию («токен CSRF»), переносимую некоторыми средствами, отличными от автоматической обработки файлов cookie браузера. В то же время cookie сеанса аутентифицирует пользователя/браузер, а токен CSRF аутентифицирует код, запущенный в браузере.

Итак, если вы используете cookie сеанса для аутентификации пользователей вашего веб-приложения, вы также должны добавить маркер CSRF для каждого ответа и потребовать соответствующий токен CSRF в каждом (мутирующем) запросе. Затем токен CSRF выполняет обратную пересылку с сервера на браузер обратно на сервер, доказывая серверу, что страница, на которой выполняется запрос, сгенерирована (сгенерирована, даже) на этом сервере.

На мой вопрос, касающийся конкретного метода транспорта, используемого для этого токена CSRF в этом обратном направлении.

кажется распространенным (например, в AngularJS, Django, Rails) послать маркер CSRF от сервера к клиенту, как куки (т.е. в заголовке Set-Cookie), а затем Javascript в клиенте царапать его из cookie и прикрепить его как отдельный заголовок XSRF-TOKEN для отправки на сервер.

(Альтернативный метод является тем, который рекомендуется, например, Express, где токен CSRF, сгенерированный сервером, включен в тело ответа через расширение шаблона на стороне сервера, прикрепленное непосредственно к коду/разметке, которое будет возвращать его обратно сервер, например, как скрытый ввод формы. Этот пример представляет собой более простой способ работы с текстом, но будет обобщать его на более высокий JS-клиент.)

Почему так часто используется Set- Печенье как транспортный поток для токена CSRF/почему это хорошая идея? Я полагаю, авторы всех этих концепций тщательно изучили свои варианты и не ошибались. Но на первый взгляд использование файлов cookie для работы над тем, что по существу является ограничением дизайна для файлов cookie, кажется глупым. Фактически, если вы использовали куки-файлы в качестве транспорта в оба конца (Set-Cookie: заголовок вниз по течению для сервера, чтобы сообщить браузеру токен CSRF, а Cookie: заголовок вверх по течению для браузера, чтобы вернуть его на сервер), вы повторно введете уязвимость, которую вы пытаются исправить.

Я понимаю, что фреймворки выше не используют файлы cookie для всего обратного перехода для токена CSRF; они используют Set-Cookie downstream, затем что-то еще (например, заголовок X-CSRF-Token) вверх по течению, и это закрывает уязвимость. Но даже использование Set-Cookie в качестве нисходящего транспорта потенциально обманчиво и опасно; браузер теперь присоединяет токен CSRF к каждому запросу, включая настоящие вредоносные запросы XSRF; в лучшем случае это делает запрос больше, чем он должен быть, и в худшем случае какой-то здравомыслящий, но ошибочный фрагмент кода сервера действительно может попытаться его использовать, что было бы очень плохо. Кроме того, поскольку фактический предполагаемый получатель токена CSRF является клиентским Javascript, это означает, что этот файл cookie не может быть защищен только с помощью http-only. Поэтому отправка токена CSRF ниже по течению в заголовке Set-Cookie кажется мне довольно субоптимальным.

ответ

153

Положительная причина, по которой вы имеете отношение, заключается в том, что после получения cookie CSRF она будет доступна для использования во всем приложении в клиентском скрипте для использования как в обычных формах, так и в AJAX POST. Это будет иметь смысл в тяжелом приложении JavaScript, например, в приложении AngularJS (использование AngularJS не требует, чтобы приложение было одностраничным приложением, поэтому было бы полезно, когда состояние должно протекать между различными запросами страницы, где значение CSRF обычно не сохраняется в браузере).

Рассмотрите следующие сценарии и процессы в типичном приложении для некоторых плюсов и минусов каждого описанного вами подхода. Они основаны на Synchronizer Token Pattern.

Запрос подход тела

  1. Пользователь успешно входит в систему.
  2. вопросы сервера аутентификации печенья.
  3. Пользователь нажимает, чтобы перейти к форме.
  4. Если этот сеанс еще не сгенерирован, сервер генерирует токен CSRF, сохраняет его против пользовательского сеанса и выводит его в скрытое поле.
  5. Пользователь отправляет форму.
  6. Сервер проверяет скрытое поле соответствует сохраненному токену сеанса.

Преимущества:

  • Простой в реализации.
  • Работы с AJAX.
  • Работы с формами.
  • Cookie может быть действительно HTTP Only.

Недостатки:

  • Все формы должны выводить скрытое поле в HTML.
  • Любые AJAX POST должны также включать значение.
  • Страница должна заранее знать, что для нее требуется токен CSRF, поэтому он может включать его в содержимое страницы, поэтому все страницы должны содержать значение токена где-то, что может потребовать много времени для реализации для большого сайта.

Пользовательский заголовок HTTP (вниз по течению)

  1. Пользователь успешно входит в систему.
  2. вопросы сервера аутентификации печенья.
  3. Пользователь нажимает, чтобы перейти к форме.
  4. Загрузка страницы в браузере, затем выполняется запрос AJAX для извлечения токена CSRF.
  5. Сервер генерирует токен CSRF (если он еще не сгенерирован для сеанса), сохраняет его в сеансе пользователя и выводит его на заголовок .
  6. Пользователь отправляет форму (токен отправляется через скрытое поле).
  7. Сервер проверяет скрытое поле соответствует сохраненному токену сеанса.

Преимущества:

  • работы с AJAX.
  • Cookie может быть HTTP Only.

Недостатки:

  • не работает без запроса AJAX, чтобы получить значение заголовка.
  • Все формы должны иметь добавленную стоимость в свой HTML динамически.
  • Любые AJAX POST должны также включать значение.
  • Страница должна сначала выполнить запрос AJAX, чтобы получить токен CSRF, поэтому каждый раз это будет означать дополнительную поездку в оба конца.
  • Возможно, просто вывести токен на страницу, которая сохранит дополнительный запрос.

Пользовательский заголовок HTTP (вверх по течению)

  1. Пользователь успешно входит в систему.
  2. вопросы сервера аутентификации печенья.
  3. Пользователь нажимает, чтобы перейти к форме.
  4. Если еще не сгенерирован для этой сессии, сервер генерирует токен CSRF, сохраняет его против пользовательского сеанса и выводит его в содержимое страницы где-то.
  5. Пользователь отправляет форму через AJAX (токен отправляется через заголовок).
  6. Сервер проверяет собственный заголовок, который соответствует сохраненному токену сеанса.

Преимущества:

  • работы с AJAX.
  • Cookie может быть HTTP Only.

Недостатки:

  • не работает с формами.
  • Все AJAX POST должны включать заголовок.

Пользовательский заголовок HTTP (вверх & вниз по течению)

  1. Пользователь успешно входит в систему.
  2. вопросы сервера аутентификации печенья.
  3. Пользователь нажимает, чтобы перейти к форме.
  4. Загрузка страницы в браузере, затем выполняется запрос AJAX для извлечения токена CSRF.
  5. Сервер генерирует токен CSRF (если он еще не сгенерирован для сеанса), сохраняет его в сеансе пользователя и выводит его на заголовок .
  6. Пользователь отправляет форму через AJAX (токен отправляется через заголовок).
  7. Сервер проверяет собственный заголовок, который соответствует сохраненному токену сеанса.

Преимущества:

  • работы с AJAX.
  • Cookie может быть HTTP Only.

Недостатки:

  • не работает с формами.
  • Все POST-адреса AJAX также должны включать значение.
  • Страница должна сначала выполнить запрос AJAX, чтобы получить токен CRSF, так что это будет означать дополнительную поездку в оба конца каждый раз.

Set-Cookie

  1. Пользователь успешно входит в систему.
  2. вопросы сервера аутентификации печенья.
  3. Пользователь нажимает, чтобы перейти к форме.
  4. Сервер генерирует токен CSRF, сохраняет его против сеанса пользователя и выводит его в файл cookie.
  5. Пользователь отправляет форму через AJAX или через HTML-форму.
  6. Сервер проверяет пользовательский заголовок (или поле скрытой формы) соответствует сохраненному токену сеанса.
  7. Cookie доступен в браузере для использования в дополнительных AJAX и запросах формы без дополнительных запросов на сервер для получения токена CSRF.

Преимущества:

  • Простой в реализации.
  • Работы с AJAX.
  • Работы с формами.
  • Необязательно требуется запрос AJAX для получения значения cookie. Любой HTTP-запрос может получить его, и он может быть добавлен ко всем формам/запросам AJAX через JavaScript.
  • После того, как маркер CSRF был извлечен, поскольку он хранится в файле cookie, значение может быть повторно использовано без дополнительных запросов.

Недостатки:

  • Все формы должны иметь добавленную стоимость к его HTML динамически.
  • Любые AJAX POST должны также включать значение.
  • Файл cookie будет отправлен за каждый запрос (т. Е. Все GET для изображений, CSS, JS и т. Д., Которые не участвуют в процессе CSRF), увеличивая размер запроса.
  • Cookie не может быть HTTP Only.

Так печенья подход является довольно динамичным предлагает простой способ получить значение куки (любой запрос HTTP) и использовать его (JS может добавить значение в любой форме автоматически и может быть использовано в AJAX запросов либо как заголовок или как значение формы). После того, как токен CSRF был получен для сеанса, нет необходимости его регенерировать, поскольку злоумышленник, использующий эксплойт CSRF, не имеет метода получения этого токена. Если злоумышленник пытается прочитать токен CSRF пользователя в любом из вышеперечисленных методов, это будет предотвращено Same Origin Policy. Если злоумышленник пытается получить сторону сервера токенов CSRF (например, через curl), то этот токен не будет связан с той же учетной записью пользователя, что и файл cookie для проверки подлинности жертвы будет отсутствовать в запросе (это будет атакующее - поэтому оно не будет связана с сервером с сеансом жертвы).

Существует также метод предотвращения CSRF Double Submit Cookie, который, конечно же, использует файлы cookie для хранения типа токена CSRF. Это проще реализовать, так как для маркера CSRF не требуется никакого состояния на стороне сервера. Токен CSRF на самом деле может быть стандартным cookie-аутентификатором при использовании этого метода, и это значение представляется с помощью файлов cookie, как обычно, с запросом, но значение также повторяется либо в скрытом поле, либо в заголовке, из которого злоумышленник не может реплицироваться как они не могут прочитать значение в первую очередь. Однако было бы желательно выбрать другой файл cookie, кроме файла cookie аутентификации, чтобы файл cookie аутентификации можно было защитить, будучи помеченным HttpOnly. Таким образом, это еще одна распространенная причина, по которой вы можете найти CSRF-предупреждение, используя метод на основе файлов cookie.

+0

Спасибо за подробный ответ. Хороший вариант для файлов cookie, оставшихся действительными за всю жизнь начальной загрузки страницы, для приложений, которые не являются одностраничными. – metamatt

+4

Я не уверен, что я понимаю, как «запрос AJAX сделан для получения токена CSRF» (шаг 4 в разделах «пользовательский заголовок: нисходящий поток») можно сделать безопасно; поскольку это отдельный запрос, сервер не знает, от кого он происходит; как он знает, что можно разглашать токен CSRF? Мне кажется, что если вы не можете получить токен из начальной загрузки страницы, вы потеряете (что, к сожалению, делает пользовательский ответный ответный заголовок нестартером). – metamatt

+1

Это было бы сделано так, чтобы одна и та же политика происхождения защищала ответ от чтения другим доменом (например, AJAX POST). – SilverlightFox

4

Мое лучшее предположение относительно ответа: рассмотрите эти 3 варианта, как получить токен CSRF с сервера в браузер.

  1. В теле запроса (а не HTTP-заголовке).
  2. В пользовательском заголовке HTTP, а не Set-Cookie.
  3. Как печенье, в заголовке Set-Cookie.

Я думаю, что 1-й, тело запроса (пока оно показано the Express tutorial I linked in the question), не так переносимо для самых разных ситуаций; не каждый генерирует каждый HTTP-ответ динамически; где вам нужно положить токен в сгенерированный ответ, может сильно различаться (в виде скрытой формы, в фрагменте кода JS или переменной, доступной другим JS-кодом, возможно даже в URL-адресе, хотя это, как правило, плохое место для ввода токенов CSRF). Таким образом, при работе с некоторыми настройками # 1 - это трудное место, чтобы сделать подход одного размера для всех.

Второй, пользовательский заголовок, привлекателен, но на самом деле не работает, потому что while JS can get the headers for an XHR it invoked, it can't get the headers for the page it loaded from.

Это оставляет третий, куки, который несет заголовок Set-Cookie, в качестве подхода, который прост в использовании во всех ситуациях (каждый сервер сможет устанавливать заголовки файлов cookie для каждого запроса, и это не независимо от того, какие данные находятся в теле запроса). Поэтому, несмотря на свои недостатки, это был самый простой способ для каркасов для широкого внедрения.

+4

Я мог бы заявить очевидное, это означает, что cookie не может быть корректным? – Photon

20

Использование куки-файла для хранения токена CSRF не позволяет успешной атаки, так как злоумышленник не может прочитать значение cookie и, следовательно, не может помещать на место, на котором это требует проверка на стороне сервера CSRF.

Злоумышленник сможет вызвать запрос на сервер как с файлом cookie-файла, так и с файлом cookie CSRF в заголовках запросов. Но сервер не ищет токен CSRF в качестве файла cookie в заголовках запроса, он ищет полезную нагрузку запроса. И даже если злоумышленник знает, куда положить токен CSRF в полезную нагрузку, им нужно будет прочитать его значение, чтобы поместить его туда. Но политика перекрестного происхождения браузера предотвращает чтение любого значения cookie с целевого веб-сайта.

Такая же логика не применяется к файловому файлу-маркеру auth, поскольку сервер ожидает его в заголовках запроса, и злоумышленнику не нужно делать что-либо особенное, чтобы поместить его туда.

+0

Наверняка, хотя злоумышленнику не нужно читать cookie в первую очередь. Они могут просто вставить изображение на взломанный сайт с помощью 'src = 'bank.com/transfer? To = hacker & amount = 1000', который будет запрашиваться браузером, в комплекте с соответствующими файлами cookie для этого сайта (' bank.com')? – developius

+1

CSRF предназначен для проверки пользователя на стороне клиента, а не для защиты сайта, как правило, от компрометации на стороне сервера, как вы предлагаете. – Tongfa

Смежные вопросы