protect_from_forgery не защищает PUT/DELETE запросы
Я сделал демонстрационное приложение с rails new demo
а затем сгенерировал пользовательский контроллер с леса с rails generate scaffold User name:string email:string
, Код лесов имеет ApplicationController
с protect_from_forgery
так же UserController
который вытекает из ApplicationController
,
Я запускаю webrick, добавляю пользователя, круто. Токен подлинности работает, как и было обещано с помощью POST на /users.
Тем не менее, до сих пор с Rails 3.0.5 я могу сделать:
niedakh@twettek-laptop:~$ telnet 10.0.0.4 3000
PUT /users/3 HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 39
user[name]=vvvvv&user[email]=shiaus.pl
И измените пользователя 3 без указания токена:
Started PUT "/users/3" for 10.0.0.4 at 2011-04-02 14:51:24 +0200
Processing by UsersController#update as HTML
Parameters: {"user"=>{"name"=>"vvvvv", "email"=>"shiaus.pl\r"}, "id"=>"3"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 3 LIMIT 1
', "updated_at" = '2011-04-02 12:51:24.437267' WHERE "users"."id" = 3s.pl
Redirected to http://10.0.0.4:3000/users/3
Completed 302 Found in 92ms
Также я могу сделать то же самое с DELETE:
DELETE /users/3 HTTP/1.1
Что дает мне:
Started DELETE "/users/3" for 10.0.0.4 at 2011-04-02 15:43:30 +0200
Processing by UsersController#destroy as HTML
Parameters: {"id"=>"3"}
SQL (0.7ms) SELECT name
FROM sqlite_master
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 3 LIMIT 1
AREL (0.5ms) DELETE FROM "users" WHERE "users"."id" = 3
Redirected to http://10.0.0.4:3000/users
Completed 302 Found in 180ms
Не могли бы вы объяснить мне, почему я могу делать такие вещи, когда я никогда не отправляю токен вместе с этими запросами?
1 ответ
Очень короткая версия: protect_from_forgery
предназначен для защиты от XSRF-атак от поддельных элементов HTML FORM. PUT и DELETE не уязвимы для атак XSRF, потому что формы HTML не могут использовать PUT или DELETE.
Атака XSRF (подделка межсайтовых запросов) - это случай, когда браузер жертвы обманом отправляет поддельный запрос на сервер без взаимодействия с пользователем.
Более длинная версия: причина, по которой вы можете сделать это, вы либо:
- Не требуется безопасность / логин или
- Уже вошли в систему и делаете запросы от скрипта, размещенного в том же домене, или
- Делаете запросы через Fiddler или аналогичные (в обход встроенной защиты браузера).
Это не сценарий protect_from_forgery
предназначен для защиты от.
Цель protect_from_forgery
для защиты от атак XSRF - межсайтовая подделка запросов. Это происходит, когда пользователь, посещающий злой сайт (или хороший сайт с добавленным злом), вынужден отправить запрос на другой сайт. Например, вы можете заставить посетителя сделать любой запрос GET, например так:
<img src="http://victim.com/victimPage?action=delete&id=ID12345" />
Как только жертва заходит на злой сайт, его браузер автоматически попытается получить изображение. Это, очевидно, не будет извлекать изображение, но пока жертва выполнит запрос на удаление элемента ID12345. POST может быть подделан аналогичным образом, просто создайте форму и отправьте ее на иностранный сайт с помощью скрипта, либо обманом заставьте пользователя щелкнуть по нему для отправки.
Вот где protect_from_forgery
приходит: сервер отправляет токен клиенту в скрытом поле с формой. Если действительный токен не появляется, сервер приходит к выводу, что отправленная форма не является отправкой подлинной формы, отправленной сервером, поэтому запрос отклоняется как потенциально подделанный.
Но ты знал это.
Дело в том, что формы HTTP могут использовать только методы GET и POST, а не PUT или DELETE. Это имеет два эффекта:
- Во-первых, если вы получаете PUT или DELETE, некуда поставить
protect_from_forgery
маркер. PUT или DELETE не являются результатом отправки формы, поэтому сервер не может отправить токен клиенту, поэтому у клиента нет токена для отправки обратно. - Во-вторых, поскольку HTML-формы могут использовать только POST и GET, если запрос представляет собой PUT или DELETE, злоумышленник не может использовать HTML-форму, чтобы заставить или заставить пользователя отправить запрос. Они могут использовать XMLHttpRequest, но XMLHttpRequest не разрешает межсайтовые запросы (если это не разрешено настройками безопасности на обоих сайтах).
Это означает, что, если домен, на котором вы его размещаете, не содержит самого вредоносного кода, нет необходимости защищать PUT и DELETE от подделки. Если сервер содержит злой код, злоумышленник может сделать произвольные запросы XMLHttpRequest для получения действительного токена и, следовательно, легко обойти защиту от подделки.
Для быстрого описания XSRF попробуйте здесь: