针对哈希令牌SQL选择的定时攻击对策

针对哈希令牌SQL选择的定时攻击对策,sql,api,hash,timing,Sql,Api,Hash,Timing,我们希望创建一个web API,用户通过电子邮件接收哈希令牌(196位),作为购买软件许可证的一部分,然后可以使用此令牌将其试用软件版本激活为“完整”软件。web API负责接收哈希令牌,并确认或拒绝用户升级到完整 撇开大量细节不谈,似乎以这种方式接收哈希令牌,然后仅使用SQL SELECT检查该令牌是否在数据库中就暴露了定时攻击。攻击者可以通过测量响应时间,尝试从数据库中的令牌猜测单个字节 如何防范??一般来说,特别是在RubyonRails中 迄今为止的想法: 实现恒定的查找时间(如何?)

我们希望创建一个web API,用户通过电子邮件接收哈希令牌(196位),作为购买软件许可证的一部分,然后可以使用此令牌将其试用软件版本激活为“完整”软件。web API负责接收哈希令牌,并确认或拒绝用户升级到完整

撇开大量细节不谈,似乎以这种方式接收哈希令牌,然后仅使用SQL SELECT检查该令牌是否在数据库中就暴露了定时攻击。攻击者可以通过测量响应时间,尝试从数据库中的令牌猜测单个字节

如何防范??一般来说,特别是在RubyonRails中

迄今为止的想法:

  • 实现恒定的查找时间(如何?)
  • 添加随机噪声(多少?)
  • 在关键部分(32位)和剩余部分拆分令牌。仅对密钥执行查找,对其余密钥执行安全比较

基于此原因设计删除令牌\u身份验证时提出的一个解决方案是基于公共条件(如电子邮件)执行查找,然后对查询找到的哈希令牌和在参数中发送的哈希令牌进行恒定时间比较。检查“安全”版本的要点


我相信从统计学的角度来看,添加随机噪声是徒劳的,有了足够的数据,随机性应该会趋于平缓。我很想听到更多关于SQL comprisons内部比较机制的详细信息。

我的工作解决方案使用了第二个索引令牌\u键字段,它是令牌\u散列的前导8字节:

def valid_token(given_token_hash)

  # don't look for hash, because of SQL timing attacks
  token_key = given_token_hash[0,8]
  token = ActivationToken.find_by_token_key(token_key)

  # Even if not found in database, we should pretend to take some time
  token_hash = token.nil? ? "123e4567-e89b-12d3-a456-426655440000" : token.token_hash

  if (!secure_compare(token_hash, given_token_hash))
    return nil
  end

  return token
end

您可以在将数据返回到客户端之前添加随机等待,从而混淆查询时间。通过这种方式,请求时间不仅取决于数据库查找。什么是合适的补偿时间?我猜它必须取决于平均查询执行时间(但我不擅长统计)。如果您知道最长执行时间,您还可以始终以一定的余量最大化响应时间(例如,响应此类查询总是需要10秒)。当然,在重载情况下仍然存在一些问题,但在我看来,重载会增加单个查询执行时间的不可预测性。与DOS防御机制相结合,这使得此类攻击变得不可行。添加随机定时噪声可能无法提高所述的安全性。这就是我最终所做的:我将令牌的前32位视为公共(整数ID),这将导致在数据库中查找(定时攻击将对此起作用)。下一步,比较剩余部分。@ChristopherRoezbek是否使用自动递增id生成前32位?如果它是随机的,那么使用生日问题,您将有50%的概率在只有77000个令牌的情况下发生前32位的冲突,这似乎也是一个问题low@danny:我使用random,但随后检查现有ID。