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