在很多Web网站中,有一项功能是忘记密码,不同网站对忘记密码的策略有自己的一套方案。但是目前却缺少一个工业标准实现一个忘记密码功能,导致的问题就是有可能在某些流程中出现漏洞,被hacker盗取账号。
OWASP作为Web安全公认的组织,在这里提出了自己的标准。下面是它的几个步骤。最后会用支付宝作为例子分析一遍。
博客园的排版不是很好,同样的文章在我的github上查看,排版比较好:
https://zebinlin.github.io/blogs/forgot-password-cheat-sheet
如果写得不错,别忘了关注我哦
Step 1) Gather Identity Data or Security Questions
第一步:收集用户身份数据或者安全问题
第1步一般让用户填写以前自己填写过的数据(一般是在用户注册的时候填写的),也就是查询数据库中是不是有这个账号的信息,
这一步收集的信息里,至少要包含可以用来发送重置密码消息的第三方信息,这些信息可以是邮箱地址或者手机号等等,第3步时要用到。
Step 2) Verify Security Questions
第二步:校验安全问题
第1步的信息提交后,应用校验每一个数据,如果有错误,或者用户名(username, 应该是用户的某个标识)没有被识别,第二页可以展示错误的信息。如果是正确的,第二页应该展示至少两个用户之前提交的两个安全问题,让用户在输入框中输入,输入框应当是一个HTML表单的一部分。
注意,不能够提供下拉列表让用户选择自己想回答的问题,这里我不是很懂,可能想表达的意思是:如果有多个问题,不能让用户只选择一个回答,这样防御能力会变弱,影响安全性。
当表单提交的时候,应避免发送用户名作为参数(不管是不是hidden域),用户名应该储存在服务端的session中,在获取的时候应该从session中获取,而不是提交表单的形式获取。(如果不做到这样,hacker可以建立另一个账号,通过输入自己的标识和自己的问题和答案绕过这一步)
因为用户填写的那些安全问题一般比细心选择的密码更加的不安全(如典型的问题有 你最喜欢什么运动,你出生在哪个城市等等),因此,应该限制猜测的次数,这个阈值可以控制在3到5次之间,当还是错误时,要锁定用户的账户一定的时间(比如5分钟),以避免hacker猜测问题,重置了用户的密码,
然后通过质疑令牌(challenge token)质疑用户身份,进入下一步的多因素认证流程
因为有可能认为用户的个人信息已经泄露,因此发送的令牌token不能包含一些个人信息如手机号码或者email等
Step 3) Send a Token Over a Side-Channel
第三步:发送质疑令牌到第三方渠道
第2步之后,应当立即锁定用户的账户,然后采用8位或以上的随机数作为token发送到第1步填写的个人信息中(比如邮箱或手机上);
在这里引入了另一个外部渠道,增加了防御的深度,令黑客更加难通过验证。这样如果有黑客成功通过了第一二步,他也可能会在这一步被拦住。
同时,这个随机数应当只有一定的生命周期,也就是一定的存活时间,如不超过20分钟左右。如果用户没有及时的查看邮箱,那么这个邮箱将不能再被使用。如果没被用户用来重置密码,token也不能再被使用(如收到验证码后不理它);当然,在成功重置完密码后token不能再使用,应当销毁。
Step 4) Allow user to change password in the existing session
第四步:要求(require)在现有会话(即第二步填写的安全问题时所在会话)中输入第三步发送的token,如果不及时输入,将不能成功;
可以通过展现一个HTML表单,里面包含3个输入域,一个token输入框,一个新密码输入框和一个确认密码输入框;
校验时,应确保令牌是正确的,而密码是足够复杂的。同样的,应当避免用户名作为表单参数被提交。
最后,检查用户是不是绕过了前面的步骤进入这一步的,也就是验证是否是从合法的页面来的,否则有可能引入强制浏览攻击(forced browsing attack)
实例
支付宝的忘记密码功能是很规范的,可以参考它的忘记密码流程
第1步:标识凭据
使用手机号或用户名作为标识 里面需要添加了验证码,是为了有人防止恶意尝试电子邮箱或手机号,进入第2步。
第2步:填写安全问题
可以看到有 验证短信+验证身份证件 和 验证短息+回答安全保护问题,当然通过人工服务就没什么说了,只要是自己账号,基本上人工是可以解决的,现在看看第二种方式,即验证短信+回答安全保护问题
可以看到需要先发送验证吗,验证身份信息,其实都是为了防止,这里就是第三步的内容 短信中提示30分钟内输入,而安全保护问题也是问我的出生地,可能是我之前填写的,我自己也忘了,然后修改了原来的问题,修改成3个问题,用来验证它是不是随机选择问题,后来发现居然你问多少个问题就要回答多少个问题,挺安全的 TAT。
其中的验证码是第3步的质疑令牌
题外话:从重置密码中可以看到可以使用身份证重置,我点进去看了一下,就我而言,不是很认同这种重置方式,虽然有通过收手机验证码方式,但是身份证号泄露还是不难的,也就是只有手机这个方面能够有效防御,换句话说,就是给入侵者减少了一道防御,不过就方便而言确实方便很多,当然,安全和方便总是矛盾的。
第3步:发送质疑令牌
因为第1步填了手机号,所以第3步支付宝将验证码发到了手机上
手机信息如下: 【支付宝】您正在修改登录密码,校验码257***,请于30分钟内输入,工作人员不会向您索取,请勿泄露。
验证码长度为6位,有效期为30分钟,这个是网站自己定义的。
第4步:修改密码
需要在当前会话中完成,因为有事中途走开了,然后我刷新步骤3的页面,发现这样子了
接着我重复前面的步骤,回到了填写安全保护问题的步骤,填写了正确的安全保护问题后,进入了重置密码阶段
输入新的密码确定就可以了,当然修改密码后token肯定就销毁了
题外话:当我输入的密码和之前的相同时,提示我”新登录密码必须和当前登录密码不同”,在一次保证了安全,有意思,大家可以试一下
小结
结合OWASP推出的忘记密码方案和支付宝的实例,我们可以发现其实很多网站对忘记密码的处理都不是很恰当。也警示我们写程序应该遵循一定的步骤走,不应该擅自的修改步骤,否则很可能会出现问题
有什么问题欢迎指出