5.2 账号管理
本节将针对账号(用户)管理实现上需要注意的地方加以说明。在账号管理当中,用户 ID(登录 ID)、密码、邮箱地址等的管理和安全性关联特别紧密。以下功能和这几方面紧密有关,我们将主要对在实现这些功能时需要注意的安全事项进行说明。
- 用户注册
- 修改密码
- 修改邮箱地址
- 密码找回
- 账号冻结
- 账号删除
5.2.1 用户注册
用户注册的时候,一般都会需要提供前面提到过的用户 ID、密码、邮箱地址等信息,需要注意的安全事项如下。
- 邮箱地址确认
- 防止用户 ID 重复
- 应对自动用户注册(即程序自动进行的机器人注册,此项内容为非必须事项)
- 关于密码的注意事项
上面第四点关于密码的相关问题,我们在前面的 5.1 节里面已经详细介绍过了,这里将不再讨论。
另外,除了上面提到的几点之外,用户注册时还容易发生下面两种安全漏洞。
- SQL 注入漏洞(4.4.1 节)
- 邮件头注入漏洞(4.9.2 节)
关于上面两种脆弱性请参考第四章的相关章节。下面我们就开始对用户注册功能的注意事项进行说明。
邮箱地址确认
在需要认证的网站里邮箱地址有着举足轻重的地位,除了能够用它来找回密码,还能在修改密码或者账号被锁定时用来发送系统通知。特别是有密码找回功能的网站,如果密码通知邮件错误的发给了其他人邮箱的话,那就变成安全事故了。
所以在用户注册、修改电子邮箱地址的时候,需要确认用户提供的邮箱是否能收到系统发送的邮件,即进行邮箱的收信确认。具体的话有下面两种方法。
- 将带有令牌的 URL 通过邮件发送到用户邮箱,用户在收到邮件点击 URL 后进行后续操作(方法 A)
- 用户输入邮箱地址后,转向令牌确认页面。令牌则通过邮件发送到用户输入的电子邮箱地址(方法 B)
上面两种方法都会给用户指定的邮箱发送令牌,然后通过确认用户输入的令牌来进行邮箱地址合法性的验证。方法 A 和方法 B 不不同的地方是,方法 A 在邮件正文里提供了一个 URL,用户点击 URL 打开网页即可。方法 B 的话则需要用户手工在页面上输入在邮件里收到的令牌。
方法 A 的处理流程如图 5-16 所示。方法 A 的话在用户在输入邮箱地址后,验证过程会临时停止,等用户收到邮件并点击里面的 URL 后,又会继续后面的验证过程。
图 5-16 邮件收信确认(方法 A)
和方法 A 不同的是,方法 B 只在邮件里发送令牌,而不带任何 URL 信息,且页面切换过程不会中断,用户需要在下一页面输入在邮件里收到的令牌。令牌在用户打开邮件之前属于秘密信息,不能放在 hidden 元素里在页面间传递,所以需要将令牌的值保存在会话中。
图 5-17 邮件收到确认(方法 B)
下表总结了方法 A 和方法 B 各自的优缺点。
表 5-4 用户邮箱地址确认方法的优点、缺点
| 方法 A | 方法 B |
---|---|---|
优点 |
|
|
缺点 |
|
|
实际中可能采用更多的是方法 A,但是在邮件里发送 URL 的话,可能会对预防钓鱼攻击措施带来不利影响,所以本书里反而推荐使用方法 B。
防止用户 ID 重复
用户 ID,即用户登录名,必须保持唯一性。笔者进行网站的安全咨询工作时,就遇到过能使用重复用户 ID 注册的情况,这里介绍一下笔者见过的用户 ID 重复的例子。
- 例子 1:ID 相同密码不同可以注册的网站
有一个会员系统网站的用户 A 忘了自己的密码,作为尝试将用户 ID 作为密码输入后竟然登录成功了,而且看到的个人信息也都是别人的。
调查后发现,即使用户 ID 相同,如果密码不同的话也能在这个网站上注册成功。而 A 用户只是偶然地登录进和用户 ID 相同的其他账号而已。
- 例子 2:用户 ID 没有添加唯一性约束的网站
笔者曾负责检查一个网站的安全漏洞,检查发现该网站在经过特殊的操作之后,可以使用重复的用户 ID 注册多个账号。笔者建议网站的管理员在数据库的表定义上给用户 ID 加上唯一(UNIQUE)约束,但是他们的系统在删除用户的时候做的是逻辑删除(即在数据库里给被删除的记录设置删除标记代表用户已被删除),所以不能在表定义上做唯一约束。
这样的网站在现实中应该为数不少,如果应用程序存在 Bug 的话(比如竞争 / 互斥处理不当等),就可能导致产生重复用户 ID 的问题。
和例子 1 一样,如果相同的用户 ID 能注册不同的用户的话,就存在用户登录到其他用户账号里的风险。最好是在数据库的定义上把表示用户 ID 的那一列加上唯一约束。如果现实不允许设置这种约束的话,那么至少在应用程序里必须要加入防止用户 ID 重复的逻辑,在处理互斥等操作的时候也要格外细心。
应对自动用户注册
如果 Web 站点是能自由注册的话,那么攻击者有时候会通过程序自动注册大量机器人账号。攻击者为了各种目的到处注册大量这种机器人账号,比如在提供邮件服务的网站里注册大量用户,然后用这些用户发送垃圾邮件。
根据网站性质不同,这种大量自动注册用户带来的威胁也不一样,如果已经预估到这种风险或者已经因这种攻击而带来损失的话,可以采用 CAPTCHA(验证码)来做预防。
- 利用 CAPTCHA 防止自动注册
CAPTCHA(验证码)是通过故意在页面显示经过变形处理的文字等,让用户确认后输入,来验证正在操作的是人而不是机器程序在执行而发明的一种方法。18
网上有很多公开的在 PHP 等中使用的 CAPTCHA 库,可以根据自己的需求去选择合适的库使用。图 5-18 就是一个面向 PHP 的叫作 cool-php-captcha19 的画面截图,这个库基于 GPLv3 许可证方式公开。在使用这样的库的时候,除了要看它们的功能和方便程度之外,许可证也是不可忽略的选择条件之一。
图 5-18 cool-php-captcha 提供的例子画面
有时候使用 CAPTCHA 会给用户的使用体验带来负面影响,最近也出现了一些使用声音代替图片的网站。下面的是 Google 用户注册时的 CAPTCHA,点击输入框右边的小喇叭图标的话,就会播放混着杂音的录音,在录音里播放作为验证码的字符。用户可以在收听验证码后输入。
图 5-19 使用了声音的 CAPTCHA
如上文所述,使用 CAPTCHA 可以在一定程度上达到阻止程序进行自动用户注册的恶意行为。
即使在用户注册界面不使用 CAPTCHA 功能,也不能说系统就存在安全上的隐患。但是如果考虑到系统被自动注册大量账号后可能会带来何种损失的话,那么请一定要考虑下使用 CAPTCHA 功能。
18 CAPTCHA 是卡内基梅隆大学的注册商标,但是他们在 2008 年 4 月 21 日放弃了该商标的所有权。请参考 http://tsdr.uspto.gov/#caseNumber=78500434&caseType=SERIAL_NO&searchType=statusSearch
19 https://code.google.com/p/cool-php-captcha/
5.2.2 修改密码
这一节我们介绍密码修改功能在安全上需要注意的事项,具体如下。
- 需要确认当前密码
- 修改密码后向用户发送邮件通知
另外,在修改密码时可能存在的以下安全漏洞。
- SQL 注入漏洞
- CSRF 漏洞
下面分别对这几项进行详细说明。
确认当前密码
当用户想要修改密码的时候,需要向用户确认当前密码(再认证)。这样做的话能防止会话劫持等情况下攻击者直接修改用户密码。而且,通过再认证,还能防止后面将要提到的 CSRF 漏洞。
图 5-20 是典型的修改密码的例子。
图 5-20 修改密码页面的示例
修改密码后向用户发送邮件通知
当发生像修改密码这样比较重要的事件时,最好是将具体信息以邮件的方式通知用户。这样即使是攻击者恶意修改了密码,用户也能尽早发现并且采取措施防止受到进一步的损失。
密码修改功能容易发生的漏洞
密码修改功能中容易发生的漏洞有以下两点。
- SQL 注入漏洞
- CSRF 漏洞
如果修改密码的页面存在 SQL 注入漏洞的话,除了 4.4.1 节里讲的常见的 SQL 注入危害以外,还存在以下危害。
- 绕过再认证而直接就能修改密码
- 修改其他用户的密码
- 一次修改所有用户的密码
此外,如果修改密码页面存在 CSRF 漏洞的话,就会像第 4.5 节里说的那样,存在攻击者在修改掉密码后,使用新密码登录的风险。
但是如果修改密码时使用上面提到的再认证功能的话,就不存在 CSRF 攻击的风险了。
5.2.3 修改邮箱地址
用户修改邮箱地址也会对影响用户安全。如果用户邮箱地址被攻击者恶意修改的话,攻击者就有可能利用密码找回功能得到用户的密码或者设置新的密码。
典型的被利用来恶意修改用户邮箱地址的攻击方式有以下几种,都是在第 4 章里介绍过的内容。
- 会话劫持
- CSRF 攻击
- SQL 注入攻击
修改邮箱地址功能要考虑的安全对策
在实现修改邮箱地址功能时,需要考虑到的安全因素包括下面几项。
- 对新邮箱地址进行收信确认(请参考 5.2.1 节)
- 再认证(请参考上一节)
- 邮件通知(请参考上一节)
修改邮箱地址后的邮件通知,需要给修改前后的两个地址都发送邮件。给旧地址发送邮件的目的是为了在邮箱地址被其他人恶意修改后能够及时通知到真正用户。
修改邮箱地址时需要的对策总结
功能方面的对策
- 邮箱地址确认
- 再认证
- 邮件通知(修改前后的两个邮箱地址)
针对容易发生的漏洞的对策
- SQL 注入漏洞的对策
- CSRF 漏洞的对策(再认证的话可以解决此问题)
5.2.4 密码找回
在用户忘记密码时,我们要通过某些手段告知用户密码或者让用户设置新密码,这个功能称为密码找回或者密码重置。
不管采用什么方法,都需要在确认用户的合法性之后,将密码告知用户或者引导用户设置新密码。把现在的密码告知用户,称为(狭义的)密码找回功能,告诉用户修改后的密码,或者引导用户设置新密码,称为密码重置。在这一节里,我们把这两种方式统称为“密码找回”。
密码找回分为面向管理员(不是供管理员找回自己的密码,而是管理员操作找回普通用户的密码)和面向最终用户两种。每个应用程序都应该提供面向管理员的密码找回功能,而面向最终用户的密码找回功能则会降低系统的安全系数,所以需要根据自己网站的特点来决定是否需要提供这个功能。
面向管理员的密码找回功能
有时候用户可能会忘记自己的密码,这时候他们就会向网站管理员求助。所以网站需要提供供管理员使用的找回密码功能。但是如果在管理员使用的密码找回功能里明文显示密码的话,就有可能存在密码被窃取等安全事故,所以一般都采用密码重置的方式实现。
管理员根据用户请求找回密码按照下面的流程进行处理。
1. 收到用户找回密码请求,对请求者进行身份验证
2. 管理员重置密码,将临时密码告诉用户
3. 用户使用临时密码登录后,立即修改密码
在第一步用户本人操作确认中,最常用的方法是通过电话确认用户注册时填写的个人资料等信息。但是这样很容易产生假冒他人的问题,所以需要根据自己网站的实际情况,选择最合适的确认用户合法性的方法。比如网银一般都会要求用户提供申请书并且加盖注册时使用的印章,然后将重置的密码通过信件邮寄给用户 20 。
20 根据银行不同,也有提供通过电话或者网站重置密码的。
在对用户进行身份合法性进行验证之后,需要将重置后的密码告诉用户,一般来说最好不直接通过电话,而是使用管理程序通过电子邮件通知用户。其原因有以下几条。
- 管理员或者用户都不会看到密码,不会造成密码泄露
- 如果有人冒名打来电话,能减少密码泄漏的风险
不管哪种情况,用户在收到重置的密码后应该立即修改密码。为了实现这个目的,可以使用“临时密码”,临时密码是只能用来修改自己密码的密码。用户只有在修改密码后,才能继续使用全部功能。
这里我们总结一下,供管理员使用的密码重置功能的需求有以下几点。
- 验证用户合法性时显示个人信息(通过电话或者书面确认)
- 生成临时密码并告知用户。临时密码不直接在屏幕上显示而是通过邮件发送
- 临时密码只能在登录后用来修改密码
面向用户的密码找回功能
忘记自己密码的用户可以通过面向用户的密码找回功能 21 找回自己的密码或者重置密码。面向用户的密码找回功能也沿用在确认操作者的合法身份后再向用户发送密码通知的流程。下面我们对此进行详细说明。
21 单说“密码找回”一般多指面向个人用户的“密码找回”功能。
- 对用户进行身份确认
面向个人用户的密码找回功能通常使用下面方法来确认操作者的合法性
- 让用户在注册时设置安全问题和答案,在用户找回密码时进行确认
- 通过向注册的邮箱地址发送邮件确认用户的合法性
但是上面的这两种方法都存在用户被冒充的可能性,第一种方法里如果安全问题是类似“你母亲的姓”之类的话,答案很容易被第三者知道。如果采用第二种方法的话,如果邮件是不加密发送的话,也存在着被监听的风险。
所以要认识到,在实现供用户找回密码功能的时候,存在用户被冒充的风险,只有在能接受这个风险的基础上再去实现这个功能。
- 如何发送密码通知
在确认了用户的合法性身份之后就要通知用户密码信息了,如何实现通知,有下面 4 种方法可以选择。
(A)通过邮件发送现在的密码
(B)发送供用户修改密码的 URL
(C)通过邮件发送临时密码
(D)直接转向修改密码页面
在本书里我们推荐使用(C)或者(D)方法。
方法(A)首先给人一种密码没有被加密的不安全感,其次,现在密码不是临时密码,万一被监听并盗取的话,在用户不知情的情况下可能会被持续盗用。所以不建议使用方法(A)。
(B)的话有一种强迫让用户养成查看邮件里附带的 URL 习惯的感觉,笔者觉得不是很好。
(C)虽然也存在被监听的风险,但是即使临时密码被攻击者得到并修改密码,用户会立刻收到修改密码的邮件通知,因为此时用户本人肯定还没有修改密码,所以立即可以知道之前的临时密码一定是被别人恶意盗用了。使用方法(C)的大致流程如图 5-21 所示。
图 5-21 方法(C)操作流程示例
在这种方法里需要注意的是,在用户输入系统不存在的邮箱地址时,也要显示保密问题确认页面。如果不这么做的话,攻击者一下子就能知道所使用的邮箱地址是否已经注册过了。所以需要在系统里保存一些预置的保密问题,当用户输入的邮箱地址不存在时,选择一个保密问题显示。当然,这时候用户无论怎么回答结果应该都是错误的。另外,对于同一个邮箱地址,每次显示的预置保密问题也应该是同一个。
在上面的操作过程中,确认保密问题是不可省略的一步。如果省略了,则随便谁都可以简单的把其他人的密码置为无效了。即使不能置为无效,也会发送重置密码邮件,给真正的用户带来困扰。
发送给用户的临时密码只能用于修改密码。此外用户在修改密码时,要通过邮件通知用户(请参考 5.2.2 节)。
下面图 5-22 是方法(D)的操作流程示意图。
图 5-22 方法(D)操作流程示例
(D)方法不会向用户发送临时密码,为了确认邮箱使用了令牌机制。另外,由于已经验证过了令牌,所以后面的“保密问题”步骤可以省略。
在用这种方式去实现密码找回通知的时候,需要注意下面几点。
首先,即使用户输入的邮箱地址不存在,也不显示错误信息,而仍然显示令牌确认页面。这么做是为了防止有人能通过观察输入不存在邮箱地址后的页面来判断出该邮件是否已经注册了。
其次,为了防止针对验证码(令牌)的暴力破解,可以考虑在验证码验证错误次数或者密码重置次数超过一定值之后,将账户冻结。但是,用户被冻结这件事在页面上不做任何提示,而是给真正的用户发送邮件,指引其向客服寻求帮助。
5.2.5 账号冻结
针对特定的账号,如果在安全性上出现什么问题的话,有时候我们可能会暂时冻结该账号。具体可能导致账号被冻结的可能原因有如下几点。
- 用户本人要求冻结(比如 PC 被偷了、手机丢了,或者收到了密码被修改的邮件等)
- 账号被非法使用的时候
除了上述行为之外,在用户违反了网站的使用规范等其他情况下也可能导致账号被冻结。
应该给管理员提供账号冻结及解锁的功能,并且像 5.2.4 节所提到那样,如果是用户自己要求冻结账号或者解锁的话,需要先进行用户的身份确认,然后再进行相应的操作。
5.2.6 账号删除
账号删除通常来说是不可恢复的操作,为了确认用户是否真的想删除账号,且为了预防 CSRF 漏洞,最好在操作时进行密码确认(再认证)。
除此之外容易在账号删除功能里出现的漏洞是 SQL 注入漏洞。
5.2.7 账号管理总结
这一节里我们对账户管理方面安全性上的注意事项做出了说明。下面我们总结了在各个功能里都需要注意的事项。
- 用户输入的电子邮箱地址一定要确认收信
- 进行重要操作的时候进行再认证
- 执行重要的处理后发邮件通知
另外,在账号管理里比较容易发生的安全漏洞也有下面几个。
- SQL 注入漏洞
- CSRF 漏洞
- 邮件头注入漏洞(邮箱地址注册、修改时)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论