Как передать токен CSRF между приложениями rails - PullRequest
12 голосов
/ 04 февраля 2012

Наше приложение rails3 взаимодействует с другим приложением rails, представленным как функции REST. Мы получаем следующее предупреждение после миграции на rails3 при всех вызовах POST, выполняемых службам REST.

WARNING: Can't verify CSRF token authenticity

Как мы должны передавать токен csrf по проводам, когда мы выполняем вызов POST для служб REST, ApplicationController имеет метод protect_from_forgery, и этот вызов также попадает в вызов handle_unverified_request. Мы используем базовую аутентификацию HTTP для аутентификации, и она работает нормально. Что мы должны сделать, чтобы решить эту проблему.

1 Ответ

11 голосов
/ 04 февраля 2012

Хорошо, теперь я попробую ответить на ваш вопрос.

Маркеры CSRF являются «зависимыми от сеанса», это означает, что пользователь должен совместно использовать сеанс с приложением, с которым он связывается. Это означает, что запрос должен быть сделан до того, как он отправит действительную форму, как в случае стандартных HTML-форм, где форма отображается перед отправкой, поэтому есть место для создания токена CSRF для этого пользователя.

Давайте назовем Приложение, которое обслуживает приложение UI Button App1, и приложение, на котором размещено Приложение REST Service 2.

Пользователь разделяет сеанс с App1 и получает кнопку интерфейса пользователя, обслуживаемую App1. Как только пользователь нажимает кнопку, выполняется запрос к App1, а App1 отправляет запрос в REST Service of App2.

Вывод: пользователь не делит сеанс с App2, но ваше приложение 1 имеет сеанс с App2. Это заканчивается двумя вещами:

  1. Пользователь не уязвим для межсайтовой фальсификации в App2, поскольку у него нет сеанса на этом сервере. Поэтому, если я опубликую что-то вроде <img src="http://app2.com/rest-service/destroy>, App2 не узнает меня, потому что я не делюсь сессией с App2 и ничего не происходит.

  2. Вы можете реализовать свои собственные меры безопасности в службе REST, чтобы защитить ее от общественности:

    • Аутентификация с помощью HTTP Basic Auth
    • Аутентификация по ключу API
    • ....

Это означает, что вы можете сбросить защиту CSRF в службе REST и оставаться в безопасности, пока пользователь не может совершать прямые вызовы через AJAX и т. Д.

Добавление

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

Большой сценарий таков: я злоумышленник, и я хотел бы изменить имя учетной записи вашего пользователя на «Mr. Potatoe». Для этого я должен разместить на своем веб-сайте скрытую форму, которая будет размещена на Yourdomain.com/account со скрытым полем типа account[name]="Mr. Potatoe". Теперь, что происходит без защиты CSRF? Мой браузер отправляет форму и отправляет файл аутентификации вместе с ней, и теперь меня зовут "Мистер Картошка". Что происходит с защитой CSRF? Мои браузеры отправляют форму и отправляют cookie, но форма не имеет токена CSRF, поэтому запрос отклоняется. Есть ли у злоумышленника способ получить токен CSRF при таких обстоятельствах? Ответ - нет. Может быть, вы спросите себя ...

  • Что если я разместу на своем сайте скрытый iframe, который указывает на Yourdomain.com/account/edit, и просто скопирую скрытое поле, содержащее токен? - Ответ: он не будет работать из-за той же политики происхождения, вы не можете прочитать, что внутри iframe, если его содержимое не исходит от вашего домена.

  • Что если я сделаю AJAX-вызов в фоновом режиме, чтобы получить токен? Ответ: Это не сработает, потому что, используя чистый AJAX, вы также обязаны соблюдать ту же политику происхождения.

Теперь давайте перейдем к делу: я не могу отправить скрытый вызов AJAX со своей страницы на вашу, чтобы нанести вред вашему пользователю, который находится на моем сайте.

Что это значит? Вы можете реализовать фильтр before, который проверяет, является ли request.xhr? истинным или пользовательский агент похож на «Мой клиент REST XY», потому что это не может быть подделано межсайтовым запросом в >> browser <<. Так что, если это так, вы можете игнорировать / отключить защиту CSRF. </p>

Кстати, если вы хотите сделать запрос AJAX на своем сайте, вы можете получить токен CSRF следующим образом:

var token = $('meta[name="csrf-token"]').attr('content');

См. Скрипт Rails UJS: https://github.com/rails/jquery-ujs/blob/master/src/rails.js#L81

ПРИМЕЧАНИЕ: это защищает вас только от подделки сайтов и ничего больше ...

...