Php MySQL中比较字符串是否容易受到定时攻击?

Php MySQL中比较字符串是否容易受到定时攻击?,php,mysql,security,hash,login,Php,Mysql,Security,Hash,Login,我正在为用户密码部署一个经典的哈希保护。登录时提交的密码将被加密、散列,然后与数据库中已存储的散列进行比较 但不是使用PHP函数调用来比较现在散列的用户输入和存储的散列,而是在数据库中进行比较——更准确地说,是使用WHERE子句(注意:在开始比较时,由于各种原因,salt已经知道,但密码不知道) 由于用户名是唯一的,下面的查询可以有效地判断用户名+密码对是否匹配: SELECT * FROM `users` WHERE `password`='$password_hash' AND `usern

我正在为用户密码部署一个经典的哈希保护。登录时提交的密码将被加密、散列,然后与数据库中已存储的散列进行比较

但不是使用PHP函数调用来比较现在散列的用户输入和存储的散列,而是在数据库中进行比较——更准确地说,是使用
WHERE
子句(注意:在开始比较时,由于各种原因,salt已经知道,但密码不知道)

由于用户名是唯一的,下面的查询可以有效地判断用户名+密码对是否匹配:

SELECT * FROM `users` WHERE `password`='$password_hash' AND `username`='$username';
这种方法容易受到定时攻击吗?



编辑:SQL注入不是一个问题,它会得到解决。

如果您在
用户
表中的
(用户名、密码)
上放置一个复合索引,并将查询从
选择*
更改为
选择计数(*)作为匹配的用户计数
,在进行匹配的查询和不花费大致相同时间的查询方面,您将有很大的进步。如果你的散列都是相同的长度,这也会有帮助

如果所有这些查询都需要相同的时间,那么计时攻击就会变得更加困难。显然,通过在每个查询上睡眠伪随机的时间量,您可以做更多的工作来击败定时攻击。试试这个:

SELECT COUNT(*) AS matching_user_count, SLEEP(RAND()*0.20) AS junk
  FROM `users` 
 WHERE `password`='$password_hash'
   AND `username`='$username'

它将为每个查询添加0到0.2秒之间的随机时间。这种随机性将支配执行索引的
WHERE
子句的几乎恒定的时间。

是的,字符串比较(和/或索引查找)原则上可能会泄漏数据库中存储的密码哈希和根据输入的密码共享计算的密码哈希的相同前导字节数

原则上,攻击者可以使用此方法逐字节迭代学习密码哈希的前缀:首先,他们找到与数据库中的哈希共享其第一个字节的哈希,然后找到共享其前两个字节的哈希,依此类推

不,这几乎肯定无关紧要

为什么??嗯,有很多原因:

  • 定时攻击可使攻击者了解用户密码散列的一部分。然而,设计良好的密码散列方案(使用salt和)应该保持安全(当然,假设密码本身不容易猜测),即使攻击者知道整个密码散列。因此,即使定时攻击成功,密码本身也是安全的。

  • 要实施攻击,攻击者必须提交他们知道其哈希值的密码。散列值取决于盐。因此,除非攻击者不知何故已经知道了盐,否则此攻击是不可能的。

    (的确,在大多数密码散列方案的安全分析中,salt被假定为公共信息。然而,这只是因为此类分析假设了上述最坏情况,即攻击者已经获得了整个用户数据库、salt和散列等的副本。如果攻击者还不知道他说,“没有理由认为他们会知道盐的。”

  • 即使攻击者知道salt,为了执行上述迭代攻击,他们也需要生成密码,将其散列为具有所需前缀的值。对于任何安全散列函数,唯一可行的方法是尝试一个错误,这意味着执行此操作所需的时间随长度呈指数级增长前缀的名称

    这在实践中意味着,为了提取足够多的散列位,以便能够对其进行离线暴力攻击(不需要全部攻击;只需超过密码中的有效熵),攻击者需要执行破解密码本身所需的计算量。对于设计良好的密码哈希方案和安全选择的密码,这是不可行的

  • 原则上,迭代攻击可以让攻击者在本地完成大部分蛮力计算,同时只向您的系统提交相当少的密码。但是,即使如此,只有当他们从提交的每个密码中收到详细可靠的时间信息时,这一点才有效。在实践中,实时攻击效率极低,,需要许多(通常是数千或数百万)查询才能产生任何有用的信息。这很可能会抵消定时攻击可能为攻击者提供的任何潜在性能优势

    如果您使用适当的密钥拉伸密码散列方案,这一点会被放大,因为此类方案被故意设计为缓慢。因此,与最初对密码进行散列相比,数据库中的字符串比较可能需要的时间可以忽略不计,由此引起的任何时间变化都将在n中丢失瓦兹


  • 取决于攻击者,但不太可能。您更容易受到攻击。您应该使用参数化查询。当然,当前正在开发的查询比这更复杂;我只是给出了一个简短的示例来说明这个问题。截至2014年11月20日,两个提交的答案都是高质量的,并提供了描述良好的解决方案s、 我之所以选择这篇文章作为公认的文章,是因为在我看来,它提供了更多的细节供将来参考,并强调了定时攻击可能带来的一些额外危险——尽管另一篇文章更直接地回答了这个问题。这实际上不是一种处理定时攻击的安全方法。它使执行定时攻击更加不方便rm是一种定时攻击,但实际上并不能解决问题。