我们正在Web应用程序上实现自我密码重置,我知道我想怎么做(向用户预先注册的电子邮件地址发送限时密码重置URL)。

我的问题是我找不到使用该技术指向开发人员的参考。谁能指出我对此技术的一些良好参考的方向?

评论

您正在使用哪种编程语言?

另请参见关于SO的类似问题。

请参阅:忘记密码·OWASP备忘单系列

#1 楼

一些建议:

在确认之前不要重设用户密码。不要立即重置用户密码。只有在用户单击发送到其预注册电子邮件地址的确认链接后,才重置它。

需要验证码。当用户要求重设密码时,请强迫他们解决验证码,然后再继续操作。这是为了防止自动化工具试图使许多用户感到悲伤,并迫使用户证明他们是人类(而不是机器人)。

随机性。限时密码重置URL应包含一个随机的,不可猜测的组成部分。确保使用加密质量随机性。 /dev/urandomSystem.Security.Cryptography.RNGCryptoServiceProvider的输出将是一个不错的选择。 rand()random()System.Random的输出不够随机,将是一个不好的选择。 GUID或时间戳不够随机,因此不是一个很好的选择。

包括时间限制。重设确认链接应在一段合理的时间后失效:例如24小时。该链接只能使用一次,并在使用后立即失效。

在电子邮件中包含解释性文字。您可能想在电子邮件中添加一些说明性文字,以说明发送电子邮件的原因,以防有人请求重设非您自己的帐户。您可以输入一些文字,例如“有人要求在username上为您的帐户site重置密码。如果您提出此请求,请单击此处更改密码。如果您没有提出此请求,请单击此处取消请求。 “

重设密码后发送电子邮件。成功重置密码后,请向用户发送电子邮件,以使他们知道密码已更改。请勿在该电子邮件中包含新密码。

监控取消。您可能会考虑添加一些逻辑来监视用户单击取消链接的频率,以表明他们没有请求重设。如果超过某个阈值,则向系统操作员发送警报可能会很有用。另外,如果在访问确认链接后访问了某个请求的取消链接,则表明该用户受到了潜在的攻击-您可能希望在此时采取措施,例如,使用户密码无效并要求他们再次重置他们的密码。 (这是针对以下攻击的一种防御措施:攻击者可以访问用户的邮箱,然后请求重置其在您网站上的密码,然后访问确认链接。如果攻击者没有从用户的收件箱中删除这些电子邮件,那么当真实用户阅读他们的电子邮件时,他们可以单击取消链接,以向您指示可能的故障。)

使用HTTPS。该链接应使用https(而不是http :)来防御各种攻击(例如,对从网吧上网的用户的Firesheep攻击)。
我建议记录所有此类请求。除了记录用户的用户名之外,您可能还希望记录通过电子邮件发送给用户的请求重置链接的客户端的IP地址,以及访问重置链接的客户端的IP地址。

其他阅读。您可能还想阅读Troy Hunt的精彩博客文章,有关构建安全密码重置功能的所有信息。感谢@coryT提供此资源的链接。

最后,考虑非密码身份验证。密码作为身份验证机制存在许多问题,您可能会考虑其他对用户进行身份验证的方法,例如将安全的持久性Cookie存储在其计算机上,并带有不可猜测的机密来对其进行身份验证。这样,虽然您确实需要提供一种方法来授权用户从新计算机或新浏览器授权访问(可能通过电子邮件发送给用户的预注册用户),但无需忘记密码,也不会欺骗用户。注册的电子邮件地址)。这份调查报告对许多后备身份验证方法及其优缺点进行了出色的调查。

评论


+1,还请注意,尽管它很流行(这一SO问题上的大多数错误答案都证明了这一点),但GUID不够随机。另外,我只会添加一个限制机制,即用户无法请求重设密码,例如一小时内3000次。

–AVID♦
2011年1月30日上午8:19

总结我与@avid在他对这个问题的回答时的对话,我想说版本4 GUID实际上基本上是随机的,我想它足够长了。但是使用它可能很愚蠢,并且有点危险,因为它最初并不是为该任务设计的。谁知道下一步将代码移植到哪里?

–nealmcb
2011年1月30日21:31

“不要在该电子邮件中包含新密码。”如果您以明文形式输入用户密码,那么您做错了。

–阿德里亚诺瓦罗利广场
2012年7月19日在21:38

@DavidMurdoch,对于随机部分,64-80位应该足够了。 (实际上,40位就足够了,但是为什么还要冒险?)

– D.W.
2012年7月21日,0:49

@DavidMurdoch有关D.W.答案的更多信息,请参见我在上面发布的链接(例如,为此目的64位随机数可能是合适的):随机随机数应持续多长时间? -IT安全

–nealmcb
2012年7月26日在16:13



#2 楼

特洛伊·亨特(Troy Hunt)在这个确切的问题上写得很好。
关于构建安全密码重置功能的所有信息,您都想知道。

评论


troy的博客是有关Web安全的所有内容的绝佳资源

–拉什·弗里斯比(Rush Frisby)
2012年7月19日在23:01

#3 楼

好的,所以您的问题是,应该如何组织密码/帐户恢复过程?这将取决于您要优化的内容:无忧的用户体验或良好的安全性。

如果想要良好的安全性:


在注册期间,用户必须输入电子邮件地址。
在注册期间,用户必须输入辅助身份验证渠道-手机号码或质询问题和答案(即“母亲的娘家姓什么”或更好)。
在恢复过程中,您的系统首先会通过上述辅助渠道(质询问题)或通过SMS将代码发送到手机或类似方式来粗略地验证身份。
当上面的第一次身份检查时清除后,系统仅将密码重置电子邮件发送到先前输入的电子邮件地址。这是防止f.x的另一项重要措施。莎拉·佩林(Sarah Palin)类型的漏洞利用程序。
电子邮件中不得包含新密码或类似密码。它应具有指向您网站上HTTPS加密网页的可点击链接,该链接的a)通过URL中提供的不可猜测的秘密值链接到帐户,b)是有时间限制的,因此帐户恢复仅适用于在请求之后的x个小时内,c)为最终用户提供了一种创建新密码的方法。
对所有帐户重置交易都有良好的登录记录,并让人员实际监控这些交易,并在出现可疑行为时采取行动(查看服务器日志中的IP地址fx,是否有许多请求来自同一IP地址,是否存在实例,例如,用户试图从不同于注册帐户所有者所在国家的国家/地区重置密码)。

您也可以完全避开这种复杂性:尚在初期,但是OAuth / OpenID /通过Facebook,Google等进行登录完全从您的系统中消除了这种复杂性,但可用性可能不那么成熟。

评论


挑战性问题与安全性相反。

–大卫·默多克(David Murdoch)
2012年7月19日在21:27

@DavidMurdoch:您能否提供讨论此内容的参考?我想了解更多。

– Marjan Venema
2012年7月20日在10:46

@David Murdoch:挑战问题等同于密码-但是关键问题是密码。在我的方案中,他们解锁了一个密码重置机制,该机制(大概)不受攻击者控制;原始电子邮件地址。但是,确实,密码重置机制通常会以降低安全性为代价来提高可用性,也许我应该更清楚地说明这一点。

– Jesper M
2012年7月20日上午10:58

请注意,在令人眼花future乱的2015年未来世界中,将电话号码用作MFA计划的一部分已经分崩离析,因为相同的小型可丢失设备充当电子邮件和SMS的网关。

–尖尖的
2015年4月3日17:01

#4 楼

任何可以向您发送密码的地方都意味着他们不会对密码进行哈希处理,而是将其存储在可以以某种方式解密为“纯文本”的位置。

可能不是“最”安全​​,但更安全的是:

在提出密码请求后,将密码重置链接发送给具有嵌入式GUID的用户。 GUID中的会话将在hmm,hour左右到期。

评论


是的,它没有问题,因为我的会话受到了SQL注入的保护,所以我发送带有随机密码重置会话代码的邮件,并允许一个小时的时间来更改它,这没关系。

–安德鲁·史密斯(Andrew Smith)
2012年7月23日在17:40



@AndrewSmith-如已经说明的那样,应该允许用户选择不将新密码发送给他们,如果您能够将密码发送给用户,则说明您的安全模型有问题。

–猎犬
2012年7月23日在18:47

该网站当前生成一个新密码,通过电子邮件发送,对其进行哈希处理并存储在db中,我认为这不好。

–安德鲁·史密斯(Andrew Smith)
2012年7月23日在18:52



生成密码并且在下次连接时不终止密码确实是一个坏主意。

–卢卡斯·考夫曼(Lucas Kauffman)
2012年7月23日19:01

如果此GUID是纯文本格式,则可以通过sql注入获得它,然后您就无法实现密码哈希的全部目的。这个帖子含糊不清是一个危险的建议。

–rook
2012年7月23日在19:38

#5 楼

另一个可能适用于您的应用程序或可能不适合您的应用程序,但用于在线银行应用程序和类似类型的事物的方法是,通过SMS消息发送一半的重置代码到注册的手机。从攻击者的角度来看,这是一个完整的PITA,因为它需要折衷一些渠道才能破解。

#6 楼

进行密码重置的最安全方法是生成一个大的随机唯一的一次性重置令牌,该令牌具有与用户ID关联的到期日期。令牌应该在数据库中散列,因为具有SQL访问权限的攻击者可以使用该令牌来重置任意用户密码。

重置链接应该发送到包含重置令牌的电子邮件地址。当用户单击链接时,应该在数据库中找到令牌的哈希,并验证到期日期为将来。如果满足这些条件,则应该向用户显示允许他们输入新密码的屏幕。

整个过程必须通过SSL进行,否则攻击者可能会嗅探URL并重置

其他一些提示:


机密的问题是对攻击者的轻微困扰和对用户的重大困扰。完全避免使用它们。
在发送密码重设之前,请用户进行人工验证(例如,验证码)。这样可以防止自动重置请求。
检查执行重置的IP地址是否是先前已成功登录该帐户的IP地址。如果不是,请询问有关帐户/用户的更多详细信息,例如帐户创建年份,出生日期,第一行地址。
添加“我没有要求此电子邮件”链接,以便用户可以报告错误的密码重置请求。


评论


即使它是通过SSL生成的:您也无法保证电子邮件本身是通过SSL传输的,因此此方法在传输过程中存在巨大缺陷-电子邮件中继和检索的基本缺陷。

–埃文·卡洛尔(Evan Carroll)
2012年7月23日在22:19

@EvanCarroll“电子邮件中继和检索的基本缺陷”。关于电子邮件检索:用户有责任使用来自具有POPS,IMAPS或HTTPS网络邮件支持的电子邮件提供商的电子邮件恢复地址(当今大多数电子邮件提供商都提供这三种服务)。

–好奇
2012年7月24日13:06

@EvanCarroll虽然这不是理想的情况,但是安全性始终是可用性的第二要务。如果您实现了世界上最安全的浏览器登录,但需要JavaScript,Flash,Java,ActiveX,Silverlight和计算机科学学位才能使用,则您的用户将关闭。电子邮件是这种功能的事实上的标准,主要是因为每个人都可以使用它。用户的电子邮件系统和个人网络的安全负担不是我的责任,也不是我的责任。

–多项式
2012年7月24日13:38



@EvanCarroll现状的论据是没有可接受的替代方法。

–好奇
2012年7月24日19:20在

我同意您的回答,但是为什么要将用户ID包含在链接中?例如,如果此用户ID是8个字符的数字,那么这8个字符也很容易猜到,因为令牌中还有8个其他随机字符。对于随机字符,您不会公开用户ID。

–martinstoeckli
2012年7月24日20:25



#7 楼

通过短信进行2要素认证! 1.您知道客户及其手机号码,然后向他们发送一个唯一的代码,以将其添加到网站上以验证是否是他们:)

评论


这不一定是两因素解决方案,但它是带外的。

–AVID♦
2011年4月20日23:40

直到有人偷了他们的电话。

–轨道轻赛
2014年2月3日,13:10

#8 楼

使其成为几步过程。例如这样的事情:


用户忘记了密码。他单击“我忘记了密码,给我发送电子邮件,下一步该怎么做”按钮(按钮标签可能有所不同;))
您的服务器向他发送了一个链接www.yourdomain.com/lostpassword?param_1=x;param_2=y

,他单击了该链接,并且能够为其创建新密码
,他单击提交。一切都完成了。每个人都很高兴

第三点是唯一的收获。 X和Y值应该是随机的,不可预测的,并且应与此特定帐户关联。它们也应该只使用一次,并且应该在短时间(24小时?)后变得陈旧。将这两个值存储在带有相应列的专用表中:

| some_id | user_id | X | Y | expire_time


如果用户尝试使用正确的链接,请检查是否不满足到期时间,如果不满足,请允许他更改密码。

评论


这与其他答案有何不同?同时使用X和Y没有任何好处,只使用一个随机值即可。

–多项式
2012年7月24日15:09

不错,但是如何防止SQL注入安全?是因为专用桌子吗?

–安德鲁·史密斯(Andrew Smith)
2012年7月24日18:35

@多项式一个值很容易通过蛮力攻击而被破坏。

– Andrzej Bobak
2012年7月24日在18:47

@AndrewSmith可以以完全不同的方式防止自己进行sql注入。这是过滤用户输入以及将其传递给查询的方式。

– Andrzej Bobak
2012年7月24日在18:48

@AndrzejBobak:两个值一样容易突破蛮力,因为一个值是两个值的长度的两倍。

–轨道轻赛
2014年2月3日,13:11