比较MySQL中的字符串容易受到时间攻击吗?

时间:2014-11-19 22:29:23

标签: php mysql security hash login

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

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

由于用户名是唯一的,因此以下查询有效地告知用户名+密码对是否匹配:

SELECT * FROM `users` WHERE `password`='$password_hash' AND `username`='$username';

这种方法是否容易受到时间攻击?


编辑:SQL注入不是问题,需要注意。

2 个答案:

答案 0 :(得分:5)

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

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

不,这几乎肯定无关紧要。

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

  1. 定时攻击可能允许攻击者学习用户密码哈希的一部分。然而,一个精心设计的密码散列方案(使用salt和key stretching)应保持安全(当然,假设密码本身不易猜测),即使攻击者知道整个< / em>密码哈希。因此,即使定时攻击成功,密码本身也是安全的。

  2. 要执行攻击,攻击者必须提交他们知道的哈希值的密码。哈希值取决于salt。因此,除非攻击者以某种方式已经知道盐,否则这种攻击是不可能的。

    (确实,在大多数密码散列方案的安全性分析中,盐被假定为公共信息。但是,这只是因为这种分析假设上面提到的最坏情况,攻击者已经获得整个用户数据库,盐和哈希等的副本。如果攻击者还不知道哈希,那么就没有理由认为他们会知道盐。)

  3. 即使攻击者知道了盐,为了执行上述的迭代攻击,他们也需要生成散列到具有所需前缀的值的密码。对于任何安全散列函数,唯一可行的方法是通过试验错误,这意味着这样做所需的时间与前缀的长度成指数级地缩放。

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

  4. 原则上,迭代攻击可以给攻击者提供的是能够在本地进行大部分暴力计算的能力,同时只提交相当少量的密码到你的系统。但是,即使这样,只有当他们从提交的每个密码中收到详细可靠的时间信息时才会成立。在实践中,实时定时攻击非常低效,并且需要许多(通常数千或数百万)个查询才能产生任何有用的信息。这很可能会抵消时间攻击可能为攻击者提供的任何潜在性能优势。

    这一点被放大了你使用适当的密钥拉伸密码哈希方案,因为这样的方案是故意设计的慢。因此,与首先对密码进行散列相比,数据库中的字符串比较可能花费的时间可以忽略不计,因此由此引起的任何时序变化都会在噪声中丢失。

答案 1 :(得分:1)

如果您在(username, password)表格中的users上添加了复合索引,并将查询从SELECT *更改为SELECT COUNT(*) AS matching_user_count,那么您将在很长的路要走匹配和查询不会花费大致相同的时间。如果你的哈希长度都相同,也会有所帮助。

如果所有这些查询花费的时间相同,那么定时攻击会更加困难。显然,你可以通过在每个查询上休眠一段伪随机时间来做更多的事情来打败定时攻击。试试这个:

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子句。