Password reset by email without a database table
通过邮件重置用户密码的正常流程是:
生成随机字符串并将其存储在数据库表中
向用户发送电子邮件字符串
用户单击包含字符串的链接
根据数据库验证字符串;如果匹配,则重置用户的pw
然而,维护一个表和过期的旧字符串等似乎有点不必要的麻烦。这种替代方法有什么明显的缺陷吗?
生成用户现有密码的MD5哈希
向用户发送哈希字符串
用户单击包含字符串的链接
通过再次散列现有的pw来验证字符串;如果匹配,则重置用户的pw。
请注意,用户的密码已经以哈希和盐格式存储,我只是再次对其进行哈希处理,以获得唯一但可重复的字符串。
是的,有一个明显的"缺陷":这样生成的重置链接在用户更改密码(点击链接)之前不会过期。我真的不明白为什么这会是一个问题——如果邮箱被破坏了,那么用户就完蛋了。而且没有重用的风险,因为一旦用户的密码被更改,重置链接将不再匹配。
要修复obvious flaw,请将当前日期(如果一天太长,则添加更多表示当前一天分数的时间相关信息)添加到要散列的内容中,以生成神秘字符串并检查它——这会使字符串"过期"(如果需要更长的"到期时间",则可以检查前一个日期以及当前日期或分数)。所以在我看来你的计划是可行的。
- 啊,你打败了我。只需确保使用数据取决于用户时区:)
- 如何从用户提交的散列中派生到期日期,以检查当前日期是否已过期?它必须加密和附加。否则:a)您只需对其进行编码,用户会中断编码,甚至会破坏时间检查的目的。b)你把它留作纯文本,同样的事情。然后,如果您有一些避免空间浪费的全局秘密,您可以发送用户HASH(S || time || userpass),time;用户发送回hash,time,这将允许服务器针对用户发送回的哈希测试HASH(S || time_user_sent_back || userpass)。
- @longpoke,如果(例如)字符串在2010/05/06和2010/05/07上是有效的,那么您将2010/05/06附加到要散列的字符串上——就是这样。通过检查,你可以通过附加今天和昨天的ISO格式来检查散列值——就是这样,几乎不需要火箭科学。如果为了特殊的字符串过期目的,您希望比一天有更好的粒度,那么您也可以使用一天中的适当部分——例如,如果您希望字符串持续大约1.5天,那么在您要散列的内容中使用"半天"(例如AM或PM)(并检查3种可能性)——也不难!
- 哈哈,我都没想到,不过我的方法是广义的!:)
- 非常聪明!谢谢。
如果有人使用密码散列访问您的数据库,他们将不知道实际的密码。如果您实现了这个系统,那么他们就可以生成重置链接并自己重置密码。有了随机字符串和妥协的知识,您就可以使所有的随机字符串失效,并且即使不知道访问权限,只有在重置密码过程中的用户才会受到损害。不太可能,但考虑到随机字符串的名义开销,这可能是值得考虑的。
- 一旦您的站点受到攻击,您也希望重置所有密码,因为攻击者可能在将密码提交到服务器时以明文形式将其记录下来(这是不可避免的情况;只有SSL客户端证书才能阻止)。更不用说,攻击者可能在几个小时内破解了90%的哈希密码。另外,如果您使用Alex Martelli的建议,您可以根据妥协时间对重置请求添加额外检查,这实际上与您刚才建议的相同:)
- 除了不是每个用户都会有一个随机字符串,但是每个用户实际上都有一个生成的字符串,所以如果您没有立即意识到这一危害,那么只有少数用户会受到影响。当然,除了90%的人密码很弱。
- 啊!这绝对是一个真正的漏洞,尽管正如Longpoke所说,一旦攻击者进入数据库,所有的赌注都取消了:他们不需要使用重置链接继续前进,只需直接在用户表中更改密码。+但是我发现了!
- 我想象的是数据库的只读快照,而不是完全写访问。
实际上,在再次考虑这个问题之后,您的方法可能比"正常流"的安全性要低。
如果您只发送回HASH(HASH(user's original password)),我可以看到这样的场景,攻击者可以利用:
情景1:
Jim在您的站点注册为[email protected]。
Jim请求密码重置,但不使用。重置的电子邮件永远放在他的收件箱里。
Jim更改了他在你网站上的电子邮件地址。
[email protected]受到Bob的影响。
Bob现在通过他的分布式GPGPU服务器场进行一次野蛮攻击,并恢复Jim的密码。
情景2:
Jim使用密码jimjonesupinthisma!作为他的银行账户。
Jim在您的站点注册为[email protected]。[email protected]与Jim的银行账户没有任何关联。
[email protected]受到Bob的影响。
Bob现在请求复位,他现在有HASH(HASH(jim's password))了。
Bob现在通过他的分布式GPGPU服务器场进行了一次野蛮攻击,并恢复了Jim的密码,然后他使用该密码访问Jim的银行帐户。
情景3:
(您的站点使用TLS,用户通过TLS注册。)
Jim在您的站点注册为[email protected]。
Bob请求在Jim的帐户上重置密码。
Bob在641a房间为NSA工作。
Bob使用他的全球互联网嗅探器,并获得HASH(HASH(jim's password)),因为它以明文形式发送给[email protected]。
Bob现在通过他的分布式GPGPU服务器场进行一次野蛮攻击,并恢复Jim的密码。
场景1和场景2的变体一直在发生(取决于哈希和密码的强度),我不太确定3。关键是,您的方法会窃取不必要的信息,这确实可以利用攻击者攻击您的用户。
我建议您使用随机生成的令牌,这些令牌与用户的密码无关。
- 不好意思,我不同意这一点:您所有的场景似乎都假定二次加盐和散列的字符串在恢复原始字符串中有任何作用,但事实似乎并非如此。MD5已知易受碰撞攻击,但您假设的黑客需要成功的预映像攻击才能从哈希中取回密码。迄今为止已知的针对一轮未加保险的MD5的最好的此类攻击的复杂性为2^123,甚至在科幻小说领域中都是如此。
- 您不需要(通常也不需要)冲突,只需要一个密码(通过字典,然后通过1-n位返回到字符集的野蛮变形)。大多数用户的密码都很弱,没有哈希可以真正保存密码。这些攻击都是真实的,虽然不像你听说的典型剧本《儿童攻击》那样常见。实际上,更多的是要有决心,在正确的时间在正确的地点。
- 这些攻击是针对未加安全保护的MD5的,在MD5中,您可以使用彩虹表来逆转散列,但是这里的密码是加了盐的,并且是双重散列的。
- 什么?更强的散列只会减慢速度。preimage可能会被salt打败,是的,但是如果不牺牲服务器的性能,就不能真正减少那么多的野蛮时间。如果你如此确信你的散列值神奇地强大,为什么不发布一个用户列表和他们相应的散列值呢?
刚刚通过这个问题,有一个想法:
1)发布一个包含用户帐户信息的JWT(JSON Web令牌)。令牌已过期,例如1小时。
2)通过电子邮件/链接将令牌发送给用户
3)用户点击链接,令牌被发送到服务器端点,令牌被验证。如果有效,则解包令牌并更新用户帐户
这种方法有缺陷吗?不接触数据库(必要时,新用户密码除外)
- 是的,你可以多次使用这个令牌,但我同意。这是件好事。我将令牌到期时间设置为1小时,因此不太可能被滥用。我错过了什么?它很简单,而且工作得很漂亮,我一定错过了什么。
- 另外,我会将请求的IP地址放入令牌中。然后,在验证时,匹配调用方的IP。令牌只能从启动请求的同一设备使用。这只是额外的措施。IP欺骗者仍然需要令牌,并且在1小时内。
假设在一个非常罕见的情况下,您的两个用户拥有相同的哈希密码,即使在将随机salt连接到它之后,仍然存在问题,对吗?我想,如果你在重置密码链接中添加用户ID的email或hashid,不会有什么影响。