在Rails中使用find params[:id]安全吗?

7
以下表达式在Rails中很常见:
@project = Project.find params[:id] # example 1

@project = current_user.projects.find params[:project_id] # example 2

然而,我意识到find也接受数组!这意味着使用假设@project是单个项目而不是数组的代码将产生意外和潜在的危险行为。

现在的问题是:

  • 每次在find中使用时,我是否应该对params[:id].to_s进行强制类型转换?
  • 我是否应该使用强参数来避免数组? find params.permit(:id)[:id])?(如果您不想将nil转换为"",则比to_s更好)
  • 是否有其他替代方法或常规做法?

上述漏洞似乎只存在于路由没有定义该名称的参数的情况下。

例如:

# SAFE routes.rb
resources :projects

# projects_controller.rb
Project.find params[:id]

查询/projects/3?id[]=4&id[]=5只会产生一个参数{id: 3}。这使得使用Project.find params[:id]是安全的,但我找不到有关此行为的任何文档,并且我不知道是否可以依赖它:也许这只是偶然发生的。 此外,以下内容根本不等效,并将在控制器中创建漏洞:
# Likely UNSAFE routes.rb
# E.g.: 
# /projects?id=3 => params = {id: 3}
# /projects?id[]=3&id[]=4 => params = {id: [3, 4]}
put '/projects' => 'projects#update'

2
就我个人而言,我更常使用find_by(id: params[:id])。如果find不能找到给定值,它会导致代码错误,并返回ActiveRecord::RecordNotFound错误。而find_by如果找不到任何内容,将返回nil,在某种意义上我认为这更安全。 - lusketeer
2
你所描述的漏洞性质似乎是“攻击者可以生成一个500服务器错误”。你是否担心某种特定的升级问题? - Jim Van Fleet
1
@JimVanFleet 例如,Token.find(params[:token]) 允许攻击者只需一次调用即可尝试数千个令牌。 - collimarco
1
@lusketeer 在Rails中,使用find并让异常生成404错误是惯用的做法。 - user229044
1个回答

0
这要看情况。你的参数是怎么传进来的?你的 `params[:id]` 和 `params[:project_id]` 是作为路由参数传递过来的吗?如果是的话,那就没问题。
否则,你应该使用 strong params - 这样应该能保护你。
最后,你可能想使用 #2,因为你不希望用户访问他们不属于的项目。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接