Michael Tetelev Asked:2020-10-06 13:37:49 +0800 CST2020-10-06 13:37:49 +0800 CST 2020-10-06 13:37:49 +0800 CST 盐的安全储存 772 哪个更安全,比: 将所有用户密码的一种普通盐存储在环境变量中 或者将每个用户的盐存储在与哈希相同的表中? безопасность 2 个回答 Voted Best Answer AivanF. 2020-10-06T14:13:32+08:002020-10-06T14:13:32+08:00 更详细地考虑选项 选项 1. 为数据库外的所有用户密码存储一种盐 hash(secret + password) 从表面上看,它看起来更安全,因为如果有人可以访问数据库,那么他将没有盐,并且可能无法恢复密码?.. 但是如果攻击者从环境变量中获得了对数据库和盐的访问权限,那么仍然需要构建彩虹表来提取密码。如果您为所有用户提供一种盐,那么这更容易做到。另一个安全问题:如果攻击者(或他的同谋/受害者)以用户身份访问系统,那么他已经知道 1 个密码及其哈希值,他可能能够更改密码并观察哈希值的变化,找到其他用户在数据库中使用相同的密码... 此选项类似于Security through obscurity 原则(security through obscurity / obfuscation),建议避免使用此原则并依赖于更强的加密方法。 选项 2. 将每个用户自己的 salt 存储在带有密码哈希的数据库中 hash(salt + password) 在这种情况下,如果攻击者获得了对数据库的访问权限,那么连同密码哈希一起,他还将收到给他们的盐。但是现在,要提取密码,需要为每个用户生成一个彩虹表,而不是为每个用户生成他自己的彩虹表!同时,正确实现与用户合作的系统很重要:更改密码时,您必须同时更改盐,这样即使使用旧版本的数据库,攻击者也将无法再受益从中。 在 Django 中使用了相同的方法,在 enSO 上的类似问题中也建议并证明了这一点- 我建议您阅读,那里讨论了不同的选项及其理由。 正如评论中提到的,这个问题实际上是没有实际意义的,取决于您的系统实施。如果您只有 1 台或多台服务器之间具有完全或弱保护的访问权限,那么有权访问数据库的攻击者很可能很容易通过环境变量获得对操作系统的访问权限,反之亦然,这就消除了第一个选项。如果您有一个经过深思熟虑的大型基础设施,使用代码对数据库和服务器的访问进行了分隔,配置了严格的安全组,在数据库和操作系统中随处使用有限制的用户,那么您可以受益从第一种方法。因此,有以下选项。 选项 3. 混合两个选项 您可以结合两全其美,如下所示: hash(hash(salt + secret) + password) 尽管还有其他选项,但可以在同一个问题中找到详细信息。但是话又说回来,这并不比第二个选项有用得多,尤其是在您的服务器基础设施保护不力的情况下。 Barmaley 2020-10-06T14:21:39+08:002020-10-06T14:21:39+08:00 既不是一个也不是另一个。 每个用户都有自己的salt——这个证据甚至不需要证明,如果有1个salt,那么为这个salt为所有用户生成1个彩虹表,大大简化了攻击者的任务 盐必须与哈希分开存储。即使在不同的数据库中,或者至少在不同的表中,它也是可取的。 由于盐本质上是开放的,因此建议注意胡椒(胡椒),它与盐不同,必须保密:key = hash(password+pepper+salt)
更详细地考虑选项
选项 1. 为数据库外的所有用户密码存储一种盐
从表面上看,它看起来更安全,因为如果有人可以访问数据库,那么他将没有盐,并且可能无法恢复密码?..
但是如果攻击者从环境变量中获得了对数据库和盐的访问权限,那么仍然需要构建彩虹表来提取密码。如果您为所有用户提供一种盐,那么这更容易做到。另一个安全问题:如果攻击者(或他的同谋/受害者)以用户身份访问系统,那么他已经知道 1 个密码及其哈希值,他可能能够更改密码并观察哈希值的变化,找到其他用户在数据库中使用相同的密码...
此选项类似于Security through obscurity 原则(security through obscurity / obfuscation),建议避免使用此原则并依赖于更强的加密方法。
选项 2. 将每个用户自己的 salt 存储在带有密码哈希的数据库中
在这种情况下,如果攻击者获得了对数据库的访问权限,那么连同密码哈希一起,他还将收到给他们的盐。但是现在,要提取密码,需要为每个用户生成一个彩虹表,而不是为每个用户生成他自己的彩虹表!同时,正确实现与用户合作的系统很重要:更改密码时,您必须同时更改盐,这样即使使用旧版本的数据库,攻击者也将无法再受益从中。
在 Django 中使用了相同的方法,在 enSO 上的类似问题中也建议并证明了这一点- 我建议您阅读,那里讨论了不同的选项及其理由。
正如评论中提到的,这个问题实际上是没有实际意义的,取决于您的系统实施。如果您只有 1 台或多台服务器之间具有完全或弱保护的访问权限,那么有权访问数据库的攻击者很可能很容易通过环境变量获得对操作系统的访问权限,反之亦然,这就消除了第一个选项。如果您有一个经过深思熟虑的大型基础设施,使用代码对数据库和服务器的访问进行了分隔,配置了严格的安全组,在数据库和操作系统中随处使用有限制的用户,那么您可以受益从第一种方法。因此,有以下选项。
选项 3. 混合两个选项
您可以结合两全其美,如下所示:
尽管还有其他选项,但可以在同一个问题中找到详细信息。但是话又说回来,这并不比第二个选项有用得多,尤其是在您的服务器基础设施保护不力的情况下。
既不是一个也不是另一个。
key = hash(password+pepper+salt)