当我继续建立越来越多的网站和网络应用程序时,我经常被要求存储用户的密码,如果/当用户有问题时,它们可以被检索(要么通过电子邮件发送一个忘记密码的链接,通过电话等),当我可以与这种做法作斗争时,我做了大量的“额外”编程,使密码重置和管理协助成为可能,而不存储他们的实际密码。

当我无法对抗它(或无法获胜)时,我总是以某种方式对密码进行编码,这样至少它不会以明文形式存储在数据库中——尽管我知道如果我的数据库被黑客攻击,罪犯不需要花费太多时间就能破解密码,所以这让我感到不舒服。

在一个完美的世界里,人们会经常更新密码,而不会在许多不同的网站上重复密码——不幸的是,我知道很多人都有相同的工作/家庭/电子邮件/银行密码,甚至在他们需要帮助的时候免费给我。如果我的数据库安全程序因为某种原因失败了,我不想成为他们财务崩溃的罪魁祸首。

从道德和伦理上讲,我觉得我有责任保护一些用户的生活,即使他们对他们的生活不那么尊重。 我确信有许多方法和论点可以用于盐散列和不同的编码选项,但当您必须存储它们时,是否存在单一的“最佳实践”?在几乎所有的情况下,我使用PHP和MySQL,如果这使任何不同的方式,我应该处理的细节。

Bounty的其他信息

我想澄清的是,我知道这不是你想要做的事情,在大多数情况下,拒绝这样做是最好的。然而,我并不是在寻求关于采用这种方法的优点的说教,我是在寻找如果你确实采用这种方法,应该采取的最佳步骤。

在下面的注释中,我指出了主要面向老年人、智障人士或非常年轻的人的网站,当他们被要求执行安全密码恢复程序时,他们会感到困惑。尽管在这些情况下,我们可能会发现这很简单,但有些用户需要额外的帮助,要么让服务技术人员帮助他们进入系统,要么通过电子邮件/直接显示给他们。

在这样的系统中,如果用户没有得到这种级别的访问帮助,来自这些人口统计数据的流失率可能会阻碍应用程序,所以请在回答时考虑到这样的设置。

谢谢大家

这是一个有趣的问题,有很多争论,我很喜欢。最后,我选择了一个答案,它既保留了密码安全性(我不必保留纯文本或可恢复的密码),又使我指定的用户群能够登录到一个系统,而不存在我在正常密码恢复中发现的主要缺陷。

像往常一样,由于不同的原因,大约有5个答案我想标记为正确,但我必须选择最好的一个——其余的都是+1。谢谢大家!

同时,感谢Stack社区中为这个问题投票和/或将其标记为最喜欢的人。我把获得100票作为一种赞美,希望这个讨论能帮助到和我有同样担忧的人。


当前回答

密码遗失/忘记处理:

没有人能够恢复密码。

如果用户忘记了密码,他们至少必须知道自己的用户名或电子邮件地址。 根据请求,在Users表中生成GUID,并向用户的电子邮件地址发送包含GUID作为参数的链接的电子邮件。

链接后面的页面验证参数guid是否真的存在(可能带有一些超时逻辑),并要求用户输入新密码。

如果您需要热线帮助用户,请向授予模型中添加一些角色,并允许热线角色临时以已识别的用户登录。记录所有此类热线登录。例如,Bugzilla为管理员提供了这样的模拟功能。

其他回答

中途教习所怎么样?

使用强加密存储密码,不要启用重置。

与其重置密码,不如允许发送一次性密码(必须在第一次登录时立即更改)。然后让用户更改为他们想要的任何密码(如果他们选择,是之前的密码)。

你可以把它作为一种重置密码的安全机制来“推销”。

Michael Brooks一直对cwe257直言不讳——事实上,无论您使用什么方法,您(管理员)仍然可以恢复密码。那么下面这些选项怎么样:

使用其他人的公钥(一些外部授权机构)加密密码。这样,您就不能亲自重建密码,用户必须去外部权威机构要求恢复他们的密码。 使用从第二个口令短语生成的密钥加密密码。在客户端进行加密,绝不将其明文传输到服务器。然后,为了恢复,通过从他们的输入重新生成密钥,再次在客户端解密。不可否认,这种方法基本上是使用第二个密码,但您总是可以告诉他们把它写下来,或者使用旧的安全问题方法。

我认为1。是更好的选择,因为它允许您在客户的公司内指定某人持有私钥。确保他们自己生成密钥,并将其与指示一起存储在保险箱等。您甚至可以通过选择只加密密码并向内部第三方提供密码中的某些字符来增加安全性,这样他们就必须破解密码才能猜测它。将这些字符提供给用户,他们可能会记住它是什么!

刚刚看到这个有趣而热烈的讨论。 最让我惊讶的是,很少有人关注以下基本问题:

Q1。用户坚持访问纯文本存储的密码的实际原因是什么?为什么它这么有价值?

用户年龄大或小的信息并不能真正回答这个问题。但是,如果没有正确理解客户的关注点,如何做出业务决策呢?

为什么这很重要呢? 因为如果客户要求的真正原因是系统难以使用,那么解决具体原因可能会解决实际问题?

由于我没有这些信息,也无法与这些客户交谈,我只能猜测:这是关于可用性的,见上文。

我看到的另一个问题是:

Q2。如果用户一开始就不记得密码,为什么旧密码很重要?

这是可能的答案。 如果你有一只叫“miaumiau”的猫,用她的名字作为密码,但忘记了,你是更愿意被提醒它是什么,还是更愿意被发送像“#zy*RW(ew)”这样的信息?

另一个可能的原因是,用户认为想出一个新密码是一项艰巨的工作!所以,把旧密码发送回去给她一种错觉,让她不用再去做那件痛苦的工作了。

我只是想知道原因。但无论原因是什么,必须解决的是原因而不是原因。

作为用户,我希望事情简单!我不想努力工作!

如果我登录一个新闻网站看报纸,我想输入1111作为密码,然后就可以通过了!!

我知道这是不安全的,但我在乎别人访问我的“帐户”吗?是的,他也会看新闻!

网站是否存储我的“私人”信息? 我今天读的新闻? 那就是网站的问题,不是我的! 站点是否向已验证的用户显示私人信息? 那就先别表现出来!

这只是为了说明用户对问题的态度。

总之,我不认为这是一个如何“安全地”存储纯文本密码的问题(我们知道这是不可能的),而是如何解决客户实际关心的问题。

保护凭证不是一个二进制操作:安全/不安全。安全是关于风险评估的,是在连续统上衡量的。安全狂热分子讨厌这样想,但丑陋的事实是,没有什么是完全安全的。具有严格的密码要求、DNA样本和视网膜扫描的散列密码更安全,但以开发和用户体验为代价。明文密码的安全性要低得多,但实现起来成本更低(但应该避免使用)。在一天结束的时候,它归结为一个漏洞的成本/收益分析。您可以根据所保护的数据的值及其时间值来实现安全性。

一个人的密码泄露到野外的代价是什么?给定系统中模拟的成本是多少?对于联邦调查局的电脑来说,代价可能是巨大的。对于Bob的一次性5页网站来说,成本可以忽略不计。专业人员为客户提供选项,并在涉及到安全性时列出任何实现的优势和风险。如果客户要求的某些东西可能会使他们处于风险之中,因为他们未能遵守行业标准,那么情况就会加倍。如果客户明确要求双向加密,我将确保您记录您的反对意见,但这不应该阻止您以您所知道的最佳方式实现。说到底,这是客户的钱。是的,你应该推动使用单向哈希,但说这绝对是唯一的选择,其他任何东西都是不道德的,这完全是无稽之谈。

如果您使用双向加密存储密码,安全性就归结于密钥管理。Windows提供了一些机制来限制对管理帐户和密码的证书、私钥的访问。如果你在其他平台上托管,你需要看看你在那些平台上有什么可用的选项。正如其他人建议的那样,您可以使用非对称加密。

据我所知,没有法律(包括英国的数据保护法案)明确规定密码必须使用单向哈希存储。这些法律中唯一的要求就是采取合理的措施保证安全。如果对数据库的访问受到限制,那么在这种限制下,即使是明文密码也可以合法地使用。

然而,这确实揭示了另一个方面:法律优先权。如果法律优先级建议您必须根据构建系统的行业使用单向散列,那么情况就完全不同了。这是你用来说服你的客户的弹药。除此之外,最好的建议是提供合理的风险评估,记录您的反对意见,并以您可以满足客户要求的最安全的方式实施系统。

允许用户检索其原始密码的唯一方法是使用用户自己的公钥对其加密。只有该用户才能解密他们的密码。

步骤如下:

用户在您的站点上注册(当然是通过SSL)而无需设置密码。自动登录或提供临时密码。 您提供存储他们的公共PGP密钥,以便将来检索密码。 他们上传他们的公共PGP密钥。 你让他们设置一个新密码。 他们提交密码。 您使用可用的最佳密码哈希算法(例如bcrypt)哈希密码。在验证下一次登录时使用此选项。 使用公钥加密密码,并单独存储。

如果用户随后询问他们的密码,您将使用加密的(而不是散列的)密码进行响应。如果用户不希望将来能够检索他们的密码(他们只能将其重置为服务生成的密码),可以跳过步骤3和7。