Protect_from_forgery 不保护 PUT/DELETE 请求
我使用rails new demo制作了一个演示应用程序,然后使用rails生成脚手架用户名:字符串电子邮件:字符串生成了一个脚手架用户控制器。脚手架代码有一个带有 protect_from_forgery
的 ApplicationController
,派生自 ApplicationController
的 UserController
也是如此。
我运行 webrick,添加一个用户,很酷。真实性令牌按照 /users 上 POST 的承诺工作。
然而,仍然使用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
你能向我解释一下为什么我可以在以下情况下执行这些操作吗?我从来没有在这些请求旁边发送任何令牌?
I made a demo application with rails new demo
and then generated a scaffolded user controller with rails generate scaffold User name:string email:string
. The scaffolded code has an ApplicationController
with protect_from_forgery
, so does UserController
which derives from ApplicationController
.
I run webrick, add a user, cool. Authenticity token works as promised with the POST on /users.
Yet still with Rails 3.0.5 I am able to do a:
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
And have the user 3 modified without giving a token:
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
Also I can do the same with DELETE:
DELETE /users/3 HTTP/1.1
Which gives me:
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
Could you explain to me why can I do those things when I never send any token alongside those requests?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
非常简短的版本:
protect_from_forgery
旨在防止来自伪造的 HTML FORM 元素的 XSRF 攻击。 PUT 和 DELETE 不易受到 XSRF 攻击,因为 HTML 表单无法使用 PUT 或 DELETE。XSRF(跨站点请求伪造)攻击是指受害浏览器被欺骗,在没有用户交互的情况下向服务器提交伪造的请求。
较长版本:您能够执行此操作的原因是:
这些并不是
protect_from_forgery
旨在防范的场景。protect_from_forgery
的目的是防止 XSRF 攻击 - 跨站点请求伪造。当访问邪恶网站(或添加邪恶的好网站)的用户被诱骗向另一个网站提交请求时,就会发生这种情况。例如,您可以欺骗访问者发出任何 GET 请求,如下所示:一旦受害者访问邪恶站点,他的浏览器就会自动尝试检索图像。这显然不会检索到图像,但同时victim.com将执行删除项目ID12345的请求。 POST可以用类似的方式伪造,只需创建一个表单,然后使用脚本将其提交到国外站点,或者欺骗用户点击它来提交。
这就是
protect_from_forgery
的作用:服务器将令牌通过表单的隐藏字段发送到客户端。如果没有出现有效的令牌,服务器就会断定所提交的表单不是服务器发送的真实表单的提交,因此该请求因可能伪造而被拒绝。但你知道这一点。
重点是 HTTP 表单只能使用 GET 和 POST 方法,而不能使用 PUT 或 DELETE 方法。这有两个影响:
protect_from_forgery
令牌。 PUT 或 DELETE 不是表单提交的结果,因此服务器无法将令牌发送给客户端,因此客户端没有令牌可发回。这意味着,只要您托管的域本身不包含恶意代码,就没有必要保护 PUT 和 DELETE 免遭伪造。如果服务器确实包含恶意代码,攻击者可以发出任意 XMLHttpRequest 请求来获取有效令牌,从而轻松绕过伪造保护。
有关 XSRF 的快速描述,请尝试此处:
Very Short Version:
protect_from_forgery
is designed to protect against XSRF attacks from forged HTML FORM elements. PUT and DELETE are not vulnerable to XSRF attacks because HTML forms cannot use PUT or DELETE.An XSRF (cross site request forgery) attack is where the victim browser is tricked into submitting a forged request to the server without interaction from the user.
Longer version: The reason you are able to do this is you either:
These are not the scenario
protect_from_forgery
is designed to protect against.The purpose of the
protect_from_forgery
is to protect against XSRF attacks - Cross Site Request Forgery. This occurs when a user visiting an evil website (or a good website with added evil) is tricked into submitting a request to another website. For example you can trick a visitor into making any GET request, like this:As soon as the victim visits the Evil site, his browser will automatically attempt to retrieve the image. This will obviously not retrieve an image, but meanwhile victim.com will execute the request deleting item ID12345. POST can be forged in a similar way, just create a form, and submit it to the foreign site using script, or else trick the user into clicking on it to submit.
That is where
protect_from_forgery
comes in: The server sends the token to the client in a hidden field with the form. If no valid token appears, the server concludes that the form which was submitted isn't a submission of a genuine form sent by the server, so the request is rejected as potentially forged.But you knew that.
The point is that HTTP forms can only use methods GET and POST, not PUT or DELETE. This has two effects:
protect_from_forgery
token. PUT or DELETE are not the result of a form submitting, so there is no way for the server to send the token to the client, therefore the client has no token to send back.This means that, provided the domain you host it on does not contain evil code itself, it is not necessary to protect PUT and DELETE from forgery. If the server does contain evil code, the attacker can make arbitrary XMLHttpRequest requests to get a valid token, and therefore easily circumvent the forgery protection anyway.
For a quick description of XSRF try here: