Я всегда думал, что защита CSRF в Ruby on Rails должна защищать от веб-запросов от других атакующих сайтов.Но сегодня я решил провести эксперимент и был удивлен.Английский - это мой второй язык, поэтому мне лучше показать пример на примере:
Предположим, что браузер жертв на fishing-website.com выполняет следующий код:
var req = new XMLHttpRequest();
req.open('GET', 'http://attacked-website.com/fakes', false);
req.withCredentials = true;
req.send(null);
if(req.status == 200) {
var token = req.responseText.match(/<meta name="csrf-token" content="(.*)" \/>/)[1];
}
console.log(token);
Коданализирует запрос и получает метатег csrf-token, расположенный в голове.Кроме того, он хранит cookie-файлы сеанса, с которыми Ruby on Rails будет сравнивать csrf-токен:
HMTrRjbvbeFLTlkv8rpGLZhPWOHk1PCgSKCzbuhPMOjvrNlR0uQo7LqD47qG = 0 * * 0 * * * *и защищенные файлы cookie только для http:
req.open('POST', 'http://attacked-website.com/fakes', false);
req.setRequestHeader('X-CSRF-Token', token)
req.withCredentials = true;
req.send(null);
И ... защита xsrf проходит!
Хорошо, я обманул.На самом деле это не так.Это проходит, только если я выполнил этот код, например, из консоли с того же сайта.И если код выполняется на другом веб-сайте, я получаю:
HTTP Origin header (http://fishing-website.com) didn't match request.base_url (http://attacked-website.com)
Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms | Allocations: 485)
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
actionpack (6.0.0) lib/action_controller/metal/request_forgery_protection.rb:217:in `handle_unverified_request'
...
Но подождите, разве защита CORS не предназначена для этого?Нужен ли нам (I) механизм Ruby on Rails protect_from_forgery
, когда браузеры имеют защиту CORS?И если да, то в каких ситуациях это полезно?