Ruby on Rails安全漏洞,通过id进行用户枚举

时间:2012-06-21 04:15:04

标签: ruby-on-rails security

使用Ruby on Rails,我的模型正在创建,增加了独特的ID。例如,第一个用户的用户ID为1,第二个用户ID为3,

从安全角度来看,这并不好,因为如果有人可以窥探最后创建的用户的用户ID(可能是通过创建新用户),他们可以推断出您的增长率。他们也可以轻松猜出用户ID。

是否有一种使用随机ID的好方法?

人们对此做了什么?谷歌搜索没有透露任何内容。

4 个答案:

答案 0 :(得分:1)

我不认为将用户ID公开为公开作为安全漏洞,应该有其他安全机制。当访问者发现你没有他们承诺的那百万用户时,也许这是一个“营销安全漏洞”; - )

反正:

要完全避免网址中的ID,您可以在所有位置使用用户的登录信息。确保登录不包含某些特殊字符(./\#?等),这会导致路由出现问题(使用白名单正则表达式)。此外,以后可能不会更改登录名,如果您的网页上有硬链接/搜索引擎条目,则可能会造成麻烦。

示例调用是/users/Jeff/users/Jeff/edit,而不是/users/522047/users/522047/edit

在您的用户类中,您需要覆盖to_param以使用路由登录而不是用户的ID。这样就不需要替换路由文件中的任何内容,也不需要替换link_to @user等帮助程序。

class User < ActiveRecord::Base
  def to_param
    self.login
  end
end

然后在每个控制器中将User.find替换为User.find_by_login

class UsersController < ApplicationController

  def show 
     @user = User.find_by_login(params[:id])
  end

end

或者之前使用before_filter替换参数。对于具有嵌套资源的其他控制器,请使用params[:user_id]

class UsersController < ApplicationController

  before_filter :get_id_from_login

  def show 
     @user = User.find(params[:id])
  end

  private 
  # As users are not called by +id+ but by +login+ here is a function
  # that converts a params[:id] containing an alphanumeric login to a 
  # params[:id] with a numeric id
  def get_id_from_login
    user = User.find_by_login(params[:id])
    params[:id] = user.id unless user.nil?
  end

end

答案 1 :(得分:0)

即使你会生成随机的INTEGER id,它也可以很容易地被攻陷。您应该为每个用户生成一个随机令牌,如MD5或SHA1(&#34; asd342gdfg4534dfgdf&#34;),然后它会对您有所帮助。您应该使用此随机哈希链接到用户个人资料。

注意,这实际上不是哈希概念,它只是一个随机字符串。

另一种方法是用他们的昵称链接到用户,例如。

但是,我的猜测是知道用户ID或用户数量或用户增长率本身不是漏洞!

答案 2 :(得分:0)

向用户模型添加名为random_id的字段或任何您想要的字段。然后在创建用户时,将此代码放在UsersController中:

def create
  ...
  user.random_id = User.generate_random_id
  user.save
end

并将此代码放在User类中:

# random_id will contain capital letters and numbers only
def self.generate_random_id(size = 8)
  alphanumerics = ('0'..'9').to_a + ('A'..'Z').to_a
  key = (0..size).map {alphanumerics[Kernel.rand(36)]}.join

  # if random_id exists in database, regenerate key
  key = generate_random_id(size) if User.find_by_random_id(key)

  # output the key
  return key
end

如果您也需要小写字母,请将它们添加到字母数字中,并确保从内核中获取正确的随机数,即Kernel.rand(62)

另外,请务必修改您的路线和其他控制器,以使用random_id代替默认id

答案 3 :(得分:0)

您需要添加适当的授权层以防止未经授权的访问。

我们假设您在show控制器的Users操作中显示用户信息,代码如下所示:

class UsersController < ActionController::Base

  before_filter :require_user

  def show
    @user = User.find(params[:id])
  end

end  

此实现容易受到id猜测。您可以通过确保show action始终显示登录用户的信息来轻松修复它:

def show
  @user = current_user
end

现在,无论URL中给出了什么ID,您都会显示当前的用户个人资料。

我们假设我们希望允许帐户管理员和帐户所有者访问show操作:

def show
  @user = current_user.has_role?(:admin) ? User.find(params[:id]) : current_user
end

使用像CanCan这样的宝石可以更好地实现OTH授权逻辑。