作者:新思科技软件质量与安全部门管理顾问Olli Jarva
互联网时代,用户在使用各种网络服务或软件时,都需要进行注册并设置密码,密码安全也随之成为用户普遍关心的问题。那么,从公司角度来看,制定密码管理策略并保障用户的信息安全就显得尤为重要。
虽然现在身份验证技术已经更加成熟,但是密码仍然是保护我们最敏感信息的主要途径。密码是防御潜在入侵者试图模仿另一个用户的第一道防线,但这样的防护往往比较弱。用户通常想创建易于记忆的密码,使用出生日期或纪念日,甚至写下来。开发人员则想尽可能少地投入密码管理策略中。毕竟,研发新功能比密码管理和存储更令人兴奋、更有趣。
许多密码本身安全性非常弱,很容易猜得到,攻击者就会有机可乘。最糟糕的是,我们信任的密码存储系统和其它关键信息的系统也面临着许多安全挑战。黑客会反复尝试密码数据库进行盗窃,攻击者同伙经常会破坏那些保护数据的模式。
我们探讨一下公司在密码管理策略方面做出的一些常见错误。让在下面的讨论中,我们将提到“在线攻击”和“离线攻击”。在线攻击是对应用程序登录页面的攻击,攻击者试图猜测用户的密码;离线攻击是攻击者获取密码数据库副本,并尝试计算存储在其中的用户密码的攻击。
您已限制用户可以使用的字符数量或种类
推理:
安全人员反复告诉开发人员验证所有输入以防止各种攻击(例如,注入攻击)。因此,根据某些规则来制定验证密码的规则必然是一个好主意,对吧?
攻击:
限制密码中字符数量或种类的问题是减少了可能的密码总数。这使得在线和离线攻击更容易。如果我知道只允许在密码中使用特殊字符!和@,那也就是我知道用户密码都没有包含#,$,%,<和>等字符。此外,如果我知道只允许长度为8到12个字符的密码,我也就知道所有用户都没有使用13个字符或更长的密码。如果我想猜测用户的密码,这些规则可以让我的工作变得更轻松。
但是SQL注入、跨站点脚本,命令注入和其它形式的注入攻击呢?如果遵循密码存储最佳做法,您将在收到密码后立即计算密码的哈希值。然后,您将只处理哈希密码,不必担心注入攻击。
防御:
允许用户选择包含任意字符的密码。指定最小密码长度为8个字符,但在可行的情况下允许任意长度的密码(例如,将它们限制为256个字符)。
您在使用密码组合规则
推理:
大多数用户选择容易猜到的密码。我们可以通过让用户选择包含几种不同类型字符的密码,以强制用户选择难以猜测的密码。
攻击:
安全专业人员曾经认为,让用户选择包含各种字符类型的密码会增强密码的安全性。不幸的是,研究表明这通常没有帮助。 “Password1!”和“P @ ssw0rd”可能遵循了许多密码组合规则,但这些密码并不比“password”更强。密码组合规则只会让用户难以记住密码;它们不会让攻击者的工作变得更加困难。
防御:
摆脱密码组成规则。在应用程序中添加密码复杂性检查功能,告诉用户他们的密码选择是否明显强度偏弱。但是,不要强制用户在其密码中添加数字、特殊字符等。稍后,我们将讨论如何使应用程序更安全,以防止安全性弱的用户密码。
您没有安全地存储密码
推理:
加密哈希函数是单向函数。因此,存储哈希密码应该可以防止攻击者计算出它们。
攻击:
与前面讨论过的两个问题不同,这个问题通常只与离线攻击有关。许多企业和组织的密码数据库都被盗了。当掌握了被盗密码库和强大的计算能力,攻击者通常可以计算出许多用户的密码。
存储密码的常用方法是使用加密哈希函数,对密码进行哈希处理。如果最终用户选择完全随机的20+字符密码,这种方法将是完美的。例如密码设成:/K`x}x4%(_.C5S^7gMw)。不幸的是,人们很难记住这些密码。如果简单地对密码进行哈希处理,则使用彩虹表攻击就很容易猜到用户选择的典型密码。
阻止彩虹表攻击通常需要在对每个密码进行散列之前添加随机“盐”。“盐”可以与密码一起存储在清除中。不幸的是,加盐的哈希并没有多大帮助。 GPU非常擅长快速计算加盐哈希值。能够访问大量加盐哈希和GPU的攻击者将能够使用暴力破解和字典攻击等攻击合理且快速地猜测到密码。
有太多不安全的密码存储机制,值得专门写篇文章去探讨。不过,我们先来看看您应该如何存储密码。
防御:
有两种主要机制可以防止攻击者:一种是使哈希计算更加昂贵,另一种是向哈希添加一些不可估测的东西。
为了使哈希计算更加昂贵,请使用自适应哈希函数或单向密钥派生函数,而不是密码哈希函数来进行密码存储。加密哈希函数的一个特性是它们可以被计算出来;这个属性导致它们不适合用于密码存储。攻击者可以简单地猜测密码并快速散列以查看生成的哈希值是否与密码数据库中的任何内容匹配。
另一方面,自适应哈希函数和单向密钥导出函数具有可配置的参数,这些参数可用于使哈希计算更加资源密集。如果使用得当,它们可以有助于充分减缓离线攻击,以确保您有时间对正在受到攻击的密码数据库做出反应。
这种方法的问题在于,每次要对用户进行身份验证时,都必须自己计算这些哈希值。这会给服务器带来额外负担,并可能使应用程序更容易受到DoS(拒绝服务)攻击。
或者,您可以添加一些不可猜测的密码哈希值。例如,如果要生成一个长随机密钥,将其添加到密码哈希值以及唯一的随机盐,并且稳妥地保护密钥,那么被盗密码数据库对攻击者来说将毫无用处。攻击者需要窃取密码数据库以及能够使用离线攻击计算出用户密码的密钥。当然,这也产生了一个需要解决的非常重要的密钥管理问题。
您完全依赖密码
推理:
密码必须是验证用户身份的好方法。其他人都在使用它们!
攻击:
即使用户执行上述所有操作,以使在线和离线攻击更加困难,也无法阻止其它应用程序/网站执行不恰当的操作。用户经常在许多站点上重复使用相同的密码。攻击者经常会在某平台尝试从其它平台盗取密码。
此外,用户成为网络钓鱼攻击的受害者,因为一些用户无论密码要求如何都会选择安全性弱的密码,等等。
防御:
要求用户使用多因素身份验证登录。请记住多因素身份验证的含义:使用至少两种不同因素进行身份验证(典型因素是您知道的事情、拥有的物品、以及生物识别等等)。使用两种不同的密码(例如,密码+安全问题的答案)不是多因素身份验证。同时使用密码和动态口令属于多因素验证的一种。此外,请记住,某些多因素身份验证机制比其它多因素身份验证机制更安全(例如,加密设备比基于SMS的一次性密码更安全)。无论如何,使用某种形式的多因素身份验证总是比仅依靠密码更安全。
如果必须仅使用密码进行身份验证,用户则还必须采取某种类型的设备身份验证。这可能涉及设备/浏览器指纹识别,检测用户是否从不寻常的IP地址登录,或类似的方式。
结论
如您所见,处理用户密码时需要考虑很多事项。我们还没有谈到密码轮换策略、帐户锁定、帐户恢复、速率限制,防止反向暴力攻击等等。
有一个很重要的问题需要考虑:您是否可以将用户身份验证转给其他人?如果你是一家金融机构,答案可能是否定的;如果您要把最新的猫咪宠物视频给别人看,在此之前需要验证,那这种情况下答案应该是可以的;如果您正在开发面向企业员工内部使用的应用程序,请考虑基于SAML的身份验证或LDAP集成;如果您正在开发面向公众的应用程序,请考虑使用社交登录(即使用Google,Facebook等登录)。许多社交网站已经投入大量精力来保护其身份验证机制,并为用户提供各种身份验证选项。您不需要全盘重来。
在不必要的情况下实施用户身份验证会给企业和用户都带来麻烦,甚至有潜在危险。创建安全的用户验证机制困难且耗时。可您是真的想要处理被盗用的密码数据库,还是攻击者在身份验证机制中发现漏洞?而且用户有更重要的事情要做,而不是记住另一个密码!