我使用rails new demo
创建了一个演示应用程序,然后使用rails generate scaffold User name:string email:string
生成了一个脚手架用户控制器。脚手架代码的ApplicationController
带protect_from_forgery
,UserController
的{{1}}也是ApplicationController
。
我运行webrick,添加用户,很酷。真实性令牌的工作方式与/ on上的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
你能解释一下,当我从未发送过这些请求的任何令牌时,为什么我可以做这些事情?
答案 0 :(得分:10)
非常短版:protect_from_forgery
旨在防止来自伪造HTML FORM元素的XSRF攻击。 PUT和DELETE不容易受到XSRF攻击,因为HTML表单不能使用PUT或DELETE。
XSRF(跨站点请求伪造)攻击是受害者浏览器被欺骗向服务器提交伪造请求而无需用户交互的地方。
更长的版本:您可以这样做的原因是:
这些不是protect_from_forgery
旨在防范的情景。
protect_from_forgery
的目的是防范XSRF攻击 - 跨站点请求伪造。当访问邪恶网站(或添加了恶意的好网站)的用户被欺骗向另一个网站提交请求时,就会发生这种情况。例如,您可以欺骗访问者发出任何GET请求,如下所示:
<img src="http://victim.com/victimPage?action=delete&id=ID12345" />
受害者一旦访问Evil网站,他的浏览器就会自动尝试检索图像。这显然不会检索图像,但同时victim.com将执行删除项目ID12345的请求。 POST可以用类似的方式伪造,只需创建一个表单,然后使用脚本将其提交到外部站点,或者诱骗用户点击它以提交。
这就是protect_from_forgery
的用武之地:服务器将令牌发送到带有表单的隐藏字段中的客户端。如果没有出现有效令牌,则服务器断定所提交的表单不是服务器发送的真实表单的提交,因此请求将被拒绝,因为可能是伪造的。
但你知道的。
重点是HTTP表单只能使用GET和POST方法,而不能使用PUT或DELETE。这有两个影响:
protect_from_forgery
令牌。 PUT或DELETE不是表单提交的结果,因此服务器无法将令牌发送到客户端,因此客户端没有令牌可以发回。这意味着,如果您托管它的域不包含恶意代码本身,则无需保护PUT和DELETE免遭伪造。如果服务器确实包含恶意代码,攻击者可以发出任意XMLHttpRequest请求以获取有效令牌,因此无论如何都可以轻松绕过伪造保护。
有关XSRF的快速说明,请尝试此处: