目录
保障验证机制的安全
简介:
1、执行安全的验证解决方案需要同时满足几个关键安全目标, 许多时候也需要牺牲其他目标,如功能、易用性和总成本。有些时候。"更加"安全实际上可能适得其反。
强迫用户设置超长密码并频繁修改密码往往促使他们将密码记录下来(因而导致密码泄露)
2、鉴于验证漏洞的多样性, 以及应用程序需要采取非常复杂的防范措施以减轻所有这些漏洞的危害, 许多应用程序设计者与开发者选择接受某些威胁,以集中精力阻止最严项的攻击。在实现
这种防御平衡的过程中,需要考虑更多因数3、应用程序所提供功能的安全程度
用户对不同类密的验证控制的容忍和接受程度
支持一个不够友好的用户界面系统所需的成本
竞争性解决方案相对于应用程序可能产生的收人方面的金融成本或它所保护资产的价值
1.1、使用可靠的证书
简述:
1、应强制执行适当的最小密码强度要求。这些要求包括:最小密码长度,使用字母、数字和排版字符, 同时使用大、小写字符, 避免使用字典中的单词、名称和其他常见密码,避免以用户名为密码, 避免使用和以前的密码相似或完全相同的密码。和大多数安全措施一样, 不同的密码强度要求适用于不同类型的用户
2、应使用唯一的用户名
3、系统生成的任何用户名和密码应具有足够的随机性,其中不包含任何顺序,即使攻击者访问大量连续生成的实例也无法对其进行预测
4、允许用户设置足够强大的密码, 应允许其设置长密码, 允许在密码中使用各种类型的字符
1.2、安全处理证书
简述:
1、应以不会造成非授权泄露的方式创建、保存和传送所有证书
2、应使用公认的加密技术(如SSL)保护客户端与服务器间的所有通信。既无必要也不需要使用定制解决方案保护传输中的数据
3、如果认为最好在应用程序的不需验证的区域使用HTTP,必须保证使用HITPS加载登录表单, 而不是在提交登录信息时才转换到HTTPS
4、只能使用POST请求向服务器传输证书。绝不能将证书放在URL参数或cookie中(即使临时放置也不行)。绝不能将证书返还给客户端,即使是通过重定向参数传送也不行。
5、所有服务器-客户端应用程序组件应这样保存证书,即使攻击者能够访问应用程序数据库中存储的所有相关数据, 他们也无法轻易恢复证书的原始值。达到这种目的最常用的方法是使用强大的散列函数, 并对其进行"加salt处理",以降低预先计算的离线攻击的危害。该salt应特定于拥有密
码的账户, 以防止攻击者重播或替换散列值6、客户端 "记住密码" 功能应仅记忆如用户名之类的非保密数据。在安全要求较低的应用程序中, 可适当允许用户选择一种工具来记住密码。在这种情况下,客户端不应保存明文证书(应使用密钥以可逆加密的形式保存密码, 且只有服务器知道这个密钥),并向用户警告直接访问他们的计算机或远程攻破他们计算机的攻击者可能造成的风险。应特别注意消除应用程序中存在的可用于盗窃其中保存的证书的跨站脚本漏洞
7、应使用一种密码修改工具, 要求用户定期修改其密码
8、如果以非正常交互的形式向新建账户分配证书, 应以尽可能安全的形式传送证书, 并设置时间限制, 要求用户在第一次登录时更改证书, 并告诉用户在初次使用后销毁通信渠道
9、应考虑在适当的地方使用下拉菜单而非文本字段截取用户的一些登录信息。这样做可防止安装在用户计算机上的键盘记录器截获他们提交的所有数据。(简单的键盘记录器只是攻击者用于截获用户输人的一种手段。如果攻击者巳经攻破用户的计算机,从理沦上讲, 他就能够记录计算机上发生的各种类型的事件, 包括鼠标活动、通过HTTPS提交的表单以及截屏。)
1.3、正确确认证书
简述:
1、应确认完整的密码。区分大小写, 不过滤或修改任何字符, 也不截短密码。
2、应用程序应在登录处理过程中主动防御无法预料的事件。
例如, 根据所使用的开发语言,应用程序应对所有API调用使用“全捕获“ 型异常处理程序,这些程序应明确删除用于控制登录状态的所有会话和方法内部数据,并使当前会话完全失效。因此, 即使攻击者以某种方式避开验证, 也会被服务器强制退出
3、应对验证逻辑的伪代码和实际的应用程序源代码进行仔细的代码审查, 以确定故障开放条件之类的逻辑错误
4、如果应用程序执行支持用户伪装功能, 应严格控制这种功能, 以防止攻击者滥用它获得未授权访问。鉴于这种功能的危险程度, 通常有必要从面向公众的应用程序中彻底删除该功能, 只对内部管理用户开放该功能, 而且他们使用伪装也应接受严格控制与审核
5、应对多阶段登录进行严格控制, 以防止攻击者破坏登录阶段之间的转换与关系
有关登录阶段进展和前面验证任务结果的所有数据应保存在服务器端会话对象中绝不可传送给客户端或由其读取
禁止用户多次提交一项登录信息;禁止用户修改已经被收集或确认的数据。如果需要在几个阶段使用同一个数据(如用户名),应在第一次收集时将该数据保存在会话变量中, 随后从此处引用该数据
在每一个登录阶段, 应首先核实前面的阶段均已顺利完成。如果发现前面的阶段没有完成, 应立即将验证尝试标记为恶意尝试
为防止泄漏的是哪个登录阶段失败(攻击者可利用它轮流针对每个阶段发动攻击)的信息, 即使用户无法正确完成前面的阶段、即使最初的用户名无效, 应用程序也应总是处理完所有的登录阶段。在处理完所有的登录阶段后, 应用程序应在最后阶段结束时呈现一条常规 "登录失败" 消息, 并且不提供失败位置的任何信息。
6、如果在登录过程中需要回答一个随机变化的问题,确保攻击者无法选择回答问题
总是采用一个多阶段登录过程, 在第一阶段确认用户身份, 并在后面的阶段向用户提出随机变化的问题
如果已向某一用户提出一个特定的问题, 将该问题保存在永久性用户资料中, 确保每次该用户尝试登录时向其提出相同的问题, 直到该用户正确回答这个问题。
如果向某个用户提出一个随机变化的质询, 将提出的问题保存在服务器端会话变量而非HTML表单的隐藏字段中, 并根据保存的问题核实用户随后提供的答案
提出一个随机变化的问题时精不过慎就可能给攻击者提供用户名枚恭的机会。
为防止攻击者选择回答他知道答案的问题, 应用程序可住会将该用户提出的最后一个问题保存在用户资料中, 并不断提出该问题直到得到正确答案。使用相同用户名多次登录的攻击者就会遇到相同的问题。如果攻击者使用一个无效的用户名进行相同的操作, 应用程序处过的方法可往会有所不同,由于没有与无效用户名有关的用户资料, 也没有问题被保存起来,所以应用程序将找出一个不同的问题(或没有问题)。攻击者可以利用这种在多次登录尝试中表现出来的行为差异, 推断某个特殊用户名的有效性。在一次自定义攻击中, 攻击者能够迅速获得大量用户名
预防措施:如果收到使用无效用户名发起的登录尝试, 应用程序必须在某个位置记录向这个无效用户名提出的随机问题, 并确保随后使用这个用户名登录都会遇到相同的问题。更进一步, 应用程序可定期更换到一个不同的问题, 模拟不存在的用户已作为正常用户登录, 导致提出的下一个问题出现变化
1.4、防止信息泄露
简述:
1、应用程序使用的各种验证机制不应通过公开的消息, 或者通过从应用程序的其他行为进行推断, 来揭示关于验证参数的任何信息。攻击者应无法判定是提交的哪个数据造成了问题
2、应由单独一个代码组件使用一条常规消息负责响应所有失败的登录尝试。这样做可避免由不同代码路径返回的本应不包含大量信息的消息, 因为消息排版方面的差异、不同的HTTP状态码、其他隐藏在HTML中的信息等内容而让攻击查看出差别, 从而产生一个细微的漏洞
3、如果应用程序实行某种账户锁定以防止蛮力攻击, 应小心处理以防造成信息泄露。
例如, 如果应用程序透露、由于N次失败登录, 已将某个特殊的账户冻结x分钟,这种行为就可被用于枚举有效的用户名。另外, 明确公开账户锁定策略标准也使攻击者能够调整任何登录尝试, 不顾锁定政策继续猜测密码。为避免用户名枚举, 如果从相同浏览器发出一系列失败的登录尝试, 应用程序应通过一条常规消息提出警告·如果出现多次登录失败, 账户将被冻结, 并建议用户稍后再试。可通过使用一个cookie或隐藏字段追踪来自相同浏览器的重复登录失败, 从而达到上述目的。
4、如果应用程序支持自我注册, 那么它能够以两种方式防止这种功能被用于枚举现有用户名
不允许自我选择用户名, 应用程序可为每个新用户建立一个唯一(和无法预测)的用户名, 防止应用程序披露表明一个选定的用户名已经存在的信息
应用程序可以使用电子邮件地址作为用户名。如果是这样, 应用程序会在登录过程的第一个阶段要求用户输人他们的电子邮件地址, 然后告诉他们等待接收一封电子邮件,按照其中的指示操作。如果电子邮件地址已经被注册, 应用程序会在电子邮件中通知用户。如果该地址没有被注册, 应用程序会要求用户访问一个唯一的、无法猜测的URL继续注册过程。这样可防止攻击者枚举有效的用户名