Безопасно ли отключать токены csrf для вызовов json rails?

У меня есть существующий бэкэнд-сайт rails, который делает json-вызовы на сервер. Теперь я разрабатываю мобильное приложение для iOS, чтобы использовать тот же бэкэнд и отправлять звонки в json. Однако мобильные запросы не выполняются:

WARNING: Can't verify CSRF token authenticity

При поиске в stackoverflow многие предлагали отключить проверку csrf для вызовов json, используя что-то вроде этого:

# Or this in your application_controller.rb
def verified_request?
  if request.content_type == "application/json"
    true
  else
    super()
  end
end

Но мой вопрос: я не понимаю, как это предотвращает атаки csrf в формате json? Злоумышленник всегда может отправить json-запрос на нашу конечную точку со своего сайта. У кого-нибудь есть понимание этого? Я не мог найти четкого ответа на это.


person Anish    schedule 20.05.2012    source источник


Ответы (3)


То, что вы описываете, очень легко использовать с помощью Flash:

        var request:URLRequest = new URLRequest("http://stackoverflow.com"); 
        request.requestHeaders.push(new URLRequestHeader('Content-Type', 'application/json'));      
        request.data = unescape('{"a":1,"b":{"c":3}}');
        request.method = URLRequestMethod.POST;
        navigateToURL(request, '_blank');   

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

person rook    schedule 20.05.2012
comment
Спасибо Рук. Да, можно взломать json-вызовы в csrf. Просмотр этой страницы дает мне больше информации о том, кто может решить эту проблему. Но знаете ли вы, как я могу использовать токены CSRF, сгенерированные Rails, чтобы мобильное приложение могло использовать их и отправлять запрос? - person Anish; 21.05.2012
comment
@Anish Вы можете загрузить его, может быть, использовать статический вызов get, который всегда возвращает токен. - person rook; 21.05.2012
comment
вы можете проверить реферера, чтобы убедиться, что он из домена, которому вы доверяете. Конечно, их легко подделать - person SooDesuNe; 06.09.2012
comment
@SooDesuNe Хотя подделать ВАШ СОБСТВЕННЫЙ реферер тривиально, это невозможно сделать при атаке CSRF. Пожалуйста, прочтите памятку по предотвращению CSRF, ссылка на которую приведена выше. - person rook; 06.09.2012
comment
Если у вас есть API, который возвращает токен, что мешает злоумышленнику вызвать этот API, чтобы получить токен, а затем передать его другому API? - person Trejkaz; 20.01.2015
comment
@Trejkaz та же политика происхождения - person rook; 20.01.2015
comment
@Rook Итак ... не помешает ли это им также отправить JSON? Я не понимаю, как один запрос является особенным. - person Trejkaz; 21.01.2015
comment
@Trejkaz Политика того же источника не позволяет злоумышленнику читать любой HTTP-ответ из другого домена, что защищает токен синхронизации CSRF. Если вы хотите узнать больше о CSRF, пожалуйста, прочитайте страницу OWASP об атаке, кроме того, шпаргалка OWASP — предотвращение CSRF содержит больше методов использования той же политики происхождения для предотвращения CSRF. Если вы не понимаете SoP, прочитайте «Руководство по безопасности браузера», распространяемое Google. - person rook; 21.01.2015

Это исправление для ajax

Получите csrf_token с рельсов или, если используете что-то еще, из мета

// js file
var csrf_token = $('meta[name=csrf-token]').attr('content');

or

//js.erb file
var csrf_token = "<%= request.session["<%= _csrf_token %>"] %>";

затем добавьте это в js

$("body").bind("ajaxSend", function(elm, xhr, s){
   if (s.type == "POST") {
    // place lines mentioned above here
    // line goes here...
    xhr.setRequestHeader('X-CSRF-Token', csrf_token);
   }
});
person Abdo    schedule 06.06.2012
comment
Пример JS может быть плохим, потому что вы собираетесь предварительно скомпилировать свои активы, и они не будут динамически регенерироваться. Просто совет. Это может быть действительно страшно, потому что это будет работать в разработке, но не в производстве. - person StingeyB; 31.03.2014
comment
@StingeyB спасибо за ваш комментарий :-) Я добавил комментарий к последнему блоку кода, указывающий пользователю, где разместить строки, упомянутые выше. Это должно выдержать предварительную компиляцию ассета, согласны? - person Abdo; 31.03.2014

Один из подходов, который вы можете использовать, — оставить проверки CSRF, но отключить их на основе наличия заголовка http. Если ваши запросы json имеют токен JWT, вы можете сделать что-то подобное в соответствующих контроллерах.

protect_from_forgery with: :exception, unless: -> { some_auth_token.valid? }

Отправки форм не смогут установить заголовок http, и поэтому csrf защитит от него.

Ваши запросы json должны иметь заголовок Authorization для обеспечения безопасности.

person Derek    schedule 02.03.2019