The definitive guide to form-based website authentication基于表单的网站身份验证
我们认为,堆栈溢出不仅应该是非常具体的技术问题的资源,而且应该是关于如何解决常见问题变化的一般指南。"基于表单的网站认证"应该是此类实验的一个很好的主题。 它应该包括以下主题:
不应包括以下内容:
请通过以下方式帮助我们: 第一部分:如何登录 我们假设您已经知道如何构建一个login+password html表单,该表单将值发布到服务器端的一个脚本以进行身份验证。下面的部分将处理健全的实际授权模式,以及如何避免最常见的安全陷阱。好的。 去HTTPS还是不去HTTPS?好的。 除非连接已经是安全的(即,通过使用ssl/tls的https进行隧道连接),否则您的登录表单值将以明文形式发送,允许在浏览器和Web服务器之间的行上窃听的任何人都可以在登录通过时读取登录信息。这种窃听通常是由政府进行的,但一般来说,我们不会处理"拥有"的电线,除非这样说:如果您要保护任何重要的东西,请使用https。好的。 本质上,在登录期间防止窃听/数据包嗅探的唯一实用方法是使用HTTPS或其他基于证书的加密方案(例如,TLS)或经验证和测试的质询响应方案(例如,基于Diffie-Hellman的SRP)。任何其他方法都很容易被窃听攻击者规避。好的。 当然,如果你愿意变得有点不切实际,你也可以使用某种形式的双因素认证方案(例如,谷歌认证应用程序、一个物理的"冷战式"代码本或RSA密钥生成器加密狗)。如果应用正确,即使是在不安全的连接上,这也可以工作,但是很难想象开发人员会愿意实现双因素身份验证,而不是SSL。好的。 (不要)滚动你自己的javascript加密/散列好的。 考虑到在您的网站上设置一个SSL证书的非零成本和感知到的技术困难,一些开发人员倾向于在浏览器中使用散列或加密方案,以避免通过不安全的连接传递明文登录。好的。 虽然这是一个高尚的思想,但它本质上是无用的(并且可能是一个安全缺陷),除非它与上述的思想结合在一起——也就是说,要么用强加密保护线路,要么使用一个经过尝试和测试的挑战响应机制(如果你不知道这是什么,只需知道这是最难证明的,最困难的方法之一T到设计,并且最难在数字安全中实现概念)。好的。 虽然散列密码确实可以有效地防止密码泄露,但它很容易受到重播攻击、中间人攻击/劫持(如果攻击者可以在不安全的HTML页面到达您的浏览器之前向其注入几个字节,他们可以简单地在javascript中注释散列),或暴力攻击。(因为您将用户名、salt和哈希密码都交给攻击者)。好的。 反人类船长好的。 是用来验证码是一类特异性thwart /蛮力字典攻击:自动试错和没有人类操作员。有没有怀疑这是一个真正的威胁,然而,当你处理它的方式seamlessly不需要验证码,登录在服务器端的具体设计方案-内节流式我们讨论这些以后。 验证码的实现是不知道谁创造了你;他们不是人力可解,大多数人是真的ineffective打击僵尸,他们都是对第三世界ineffective廉价的实验室(根据OWASP的血汗工厂,目前的测试通过率是12 500美元),和一些实现的技术在一些可能是非法的湖国家(OWASP认证作弊表)。如果你必须使用一个验证码,验证码的使用谷歌,因为它是硬的OCR定义(因为它已经使用OCR错误图书扫描)和强硬的和用户友好的。 就我个人而言,我没有找到,他们只使用,和使用作为最后当一用户登录失败安切洛蒂作为内节流式是maxed时报和延迟退房。这将是可接受的清洁很少发生,它strengthens漫游系统作为一个整体。 保密码登录/核查 这可能是普通的知识,毕竟我们的注册用户数据泄密、黑客和publicized我们见过在最近几年,但它是说:不要在你的数据库中存储的密码cleartext。用户数据库是routinely泄露或gleaned通黑,SQL注入,如果你储存的原始文件,这是密码,登录即时游戏为您的安全。 所以如果你不能存储的密码,它是你如何检查登录密码登录+结合的形式张贴在正确的是?答案是使用密钥的散列函数的推导。每当一个新的用户创建的密码,或是把你的密码和运行它通过KDF,如argon2,bcrypt,scrypt或pbkdf2,转折的cleartext密码("correcthorsebatterystaple")到一个长期的前瞻性,随机字符串,这是很多更安全的存储在你的数据库。验证登录到相同的哈希函数,你在运行时传递进来的密码,这是造成在盐和比较哈希值存储在字符串到您的数据库。argon2 bcrypt和盐,scrypt商店已经在哈希。在这篇文章中sec.stackexchange退房的更多详细信息。 原因一是盐是用散列本身是不足够的-你想添加一个所谓的"盐",保护对彩虹哈希表。a盐有效地防止密码完全匹配从两个相同的哈希值被存储为防止被扫描整个数据库,运行在一个四attacker一直就这样在事后来劝告正在执行一个密码攻击。 密码存储不应使用加密散列,因为用户选择的密码不够强(即通常不包含足够的熵),具有散列访问权限的攻击者可以在相对短的时间内完成密码猜测攻击。这就是使用kdf的原因——这些有效地"拉伸密钥",这意味着攻击者所做的每一个密码猜测都会导致哈希算法重复多次,例如10000次,这会导致攻击者猜测密码的速度减慢10000倍。好的。 会话数据-"您以spiderman69登录"好的。 一旦服务器根据用户数据库验证了登录名和密码并找到匹配项,系统就需要一种方法来记住浏览器已经过身份验证。这个事实应该只存储在会话数据的服务器端。好的。
如果可能,确保会话cookie在发送到浏览器时设置了安全和仅HTTP标志。httponly标志提供了一些保护,防止通过XSS攻击读取cookie。安全标志确保cookie只能通过https发送回,因此可以防止网络嗅探攻击。cookie的值不应是可预测的。如果出现引用不存在会话的cookie,则应立即替换其值以防止会话固定。好的。第二部分:如何保持登录-臭名昭著的"记住我"复选框 持久登录cookie("记住我"功能)是一个危险区域;一方面,当用户了解如何处理它们时,它们与传统登录完全一样安全;另一方面,在粗心的用户手中,它们是一个巨大的安全风险,粗心的用户可能会在公共计算机上使用它们,而忘记注销,他们可能不会现在,什么是浏览器cookie,或者如何删除它们。好的。 就我个人而言,我喜欢经常访问的网站的持续登录,但我知道如何安全地处理它们。如果您确信您的用户也知道这一点,那么您就可以用良心清白的持久登录。如果不是,那么你可以接受这样一种理念:如果用户不小心使用了他们的登录凭证,那么一旦他们被黑客攻击,他们就会受到攻击。这也不像我们去用户的家里,撕掉所有的facepalm诱导贴,上面写着他们在显示器边缘排列的密码。好的。 当然,有些系统负担不起任何帐户被黑客攻击;对于此类系统,您无法证明持久登录是正确的。好的。 如果您确实决定实现持久登录cookie,那么可以这样做:好的。 首先,花些时间阅读Paragon Initiative关于这个主题的文章。你需要把一堆元素弄对,这篇文章对每一个都做了很好的解释。好的。 为了重申最常见的陷阱之一,不要将持久登录cookie(token)存储在数据库中,只存储其中的一个散列值!登录令牌相当于密码,因此如果攻击者掌握了您的数据库,他们可以使用令牌登录到任何帐户,就像他们是明文登录密码组合一样。因此,在存储持久登录令牌时,请使用散列(根据https://security.stackexchange.com/a/63438/5002,弱散列就可以了)。好的。 第三部分:使用秘密问题 不要执行"秘密问题"。"秘密问题"功能是一种安全反模式。从"必须读"列表的链接4中读取纸张。你可以问莎拉佩林关于那个,在她的雅虎之后!在前一次总统竞选中,电子邮件帐户遭到黑客攻击,因为她对安全问题的回答是…"瓦西拉高中"!好的。 即使有用户指定的问题,大多数用户也很可能选择:好的。
总之,安全问题本质上是不安全的,几乎在所有形式和变化中都是不安全的,不应以任何理由将其用于身份验证方案。好的。 安全问题甚至存在于野外的真正原因是,它们方便地节省了一些无法访问电子邮件以访问重新激活代码的用户的支持呼叫成本。这是以牺牲安全和莎拉·佩林的名誉为代价的。值得的?大概不会。好的。第四部分:忘记密码功能 我已经提到了为什么你不应该使用安全问题来处理忘记/丢失的用户密码;也没有说你不应该向用户发送他们的实际密码。在这个领域,至少还有两个太常见的陷阱需要避免:好的。 不要将忘记的密码重置为自动生成的强密码-这种密码众所周知很难记住,这意味着用户必须更改或写下来-例如,在显示器边缘的亮黄色贴纸上。不要设置新密码,只需让用户立即选择一个新密码-这是他们无论如何都想做的。(这可能是一个例外,如果用户普遍使用密码管理器来存储/管理通常不写下来就无法记住的密码)。好的。 总是散列数据库中丢失的密码代码/令牌。同样,此代码是另一个等价密码的示例,因此必须对其进行哈希处理,以防攻击者接触到您的数据库。当请求丢失的密码时,将明文代码发送到用户的电子邮件地址,然后散列它,将散列保存在数据库中——并丢弃原始密码。就像密码或持久登录令牌。好的。 最后一点注意:始终确保用于输入"丢失密码代码"的界面至少与登录表单本身一样安全,否则攻击者只需使用该界面获取访问权。确保生成非常长的"丢失密码"(例如,16个区分大小写的字母数字字符)是一个很好的开始,但是考虑添加与登录表单本身相同的限制方案。好的。第五部分:密码强度检查 首先,您需要阅读这篇小文章来进行实际检查:500个最常见的密码好的。 好吧,所以这个列表可能不是任何系统中最常见密码的规范列表,但它很好地说明了当没有强制执行的策略时,人们选择密码的能力有多差。另外,当你将它与最近被盗密码的公开分析相比较时,这个列表看起来非常接近。好的。 所以:由于没有最低的密码强度要求,2%的用户使用前20个最常见的密码之一。意思是:如果攻击者只有20次尝试,你网站上的50个账户中就有1个会被破解。好的。 要阻止这种情况,需要计算密码的熵,然后应用阈值。国家标准与技术研究所(NIST)特别出版物800-63有一套非常好的建议。当结合字典和键盘布局分析(例如,"qwertyuiop"是一个错误的密码)时,可以在18位熵的水平上拒绝99%的错误选择的密码。简单计算密码强度并向用户显示视觉强度计是好的,但不够。除非强制执行,否则很多用户很可能会忽略它。好的。 为了刷新高熵密码的用户友好性,强烈推荐Randall Munroe的密码强度xkcd。好的。第六部分:更多-或:防止快速登录尝试 首先,看看这些数字:密码恢复速度-密码的有效期有多长好的。 如果您没有时间浏览该链接中的表,下面是它们的列表:好的。 破解一个弱密码几乎不需要时间,即使你是用算盘破解它。好的。 如果不区分大小写,则几乎不需要花费时间破解字母数字9字符密码。好的。 如果密码长度小于8个字符,几乎不需要花时间破解复杂的符号、字母和数字、大小写密码(台式电脑可以在几天甚至几小时内搜索7个字符)。好的。 但是,如果您限制为每秒尝试一次,那么破解一个6个字符的密码需要花费大量的时间!好的。 那么我们能从这些数字中学到什么呢?好吧,很多,但我们可以把重点放在最重要的部分:防止大量快速启动的连续登录尝试(即蛮力攻击)并没有那么困难。但是,正确地预防并不像看上去那么容易。好的。 一般来说,您有三种选择都能有效地抵御蛮力攻击(和字典攻击,但由于您已经采用了强密码策略,因此它们不应该是问题):好的。
最佳实践1:随着失败尝试次数的增加而增加的短时间延迟,例如:好的。
DOS攻击这个方案是非常不切实际的,因为产生的锁定时间略大于前一个锁定时间的总和。好的。
最佳实践2:在n次失败尝试后生效的中等长度时间延迟,例如:好的。
DOS攻击这个计划是非常不切实际的,但肯定是可行的。另外,值得注意的是,这种长时间的延迟对于合法用户来说是非常烦人的。健忘的用户会不喜欢你。好的。 最佳实践3:将这两种方法结合在一起-在n次失败尝试后,固定的短时间延迟生效,例如:好的。
或者,具有固定上限的增加延迟,例如:好的。
该最终方案取自OWASP最佳实践建议(必须阅读的列表中的链接1),应被视为最佳实践,即使该方案确实存在限制性。好的。
DOS攻击这个最终登录限制方案是非常不切实际的。最后一点是,始终允许持久(cookie)登录(和/或验证了验证码的登录表单)通过,这样合法用户在攻击过程中甚至不会被延迟。这样,非常不切实际的DoS攻击就变成了非常不切实际的攻击。好的。 此外,对管理帐户进行更积极的限制是有意义的,因为这些是最有吸引力的入口点好的。第七部分:分布式暴力攻击 和旁白一样,更高级的攻击者会试图通过"散布他们的活动"来绕过登录限制:好的。
在这里,最佳实践是记录失败登录的数量、系统范围,并使用站点错误登录频率的运行平均值作为对所有用户施加的上限的基础。好的。 过于抽象?让我换个说法:好的。 假设你的网站在过去的3个月里平均每天有120次错误登录。使用这个(运行平均值),您的系统可能会将全局限制设置为3倍,即24小时内360次失败的尝试。然后,如果所有帐户的失败尝试总数在一天内超过该数字(或者更好的方法是,监视加速率并在计算的阈值上触发),它将激活系统范围内的登录限制-这意味着所有用户的延迟都很短(但cookie登录和/或备份captcha登录除外)。好的。 我还发布了一个更详细的问题,并讨论了如何避免分布式蛮力攻击中的棘手陷阱。好的。第八部分:双因素认证和认证提供者 无论是通过漏洞攻击、密码被写下来并丢失、带有密钥的笔记本电脑被偷,还是用户登录到网络钓鱼网站,都可能破坏凭据。使用双因素认证可以进一步保护登录,该认证使用带外因素,例如从电话呼叫、短信、应用程序或加密狗接收到的一次性代码。一些提供者提供双因素认证服务。好的。 身份验证可以完全委托给一个登录服务,在该服务中,另一个提供者负责收集凭证。这就把问题推给了一个可信的第三方。谷歌和Twitter都提供基于标准的SSO服务,而Facebook也提供类似的专有解决方案。好的。有关Web身份验证的必读链接 好啊。 最终条款正在发送凭据 唯一可行的100%安全地发送凭证的方法是使用SSL。使用javascript散列密码是不安全的。客户端密码散列的常见缺陷:好的。
还有另一种称为srp的安全方法,但它已获得专利(尽管它是免费许可的),而且几乎没有好的实现可用。好的。存储口令 不要将密码以明文形式存储在数据库中。即使你不关心你自己网站的安全也不行。假设您的一些用户将重用其在线银行帐户的密码。所以,存储哈希密码,并扔掉原始密码。并确保密码不会出现在访问日志或应用程序日志中。OWASP建议使用argon2作为新应用程序的首选。如果不可用,则应使用pbkdf2或scrypt。最后,如果以上都不可用,请使用bcrypt。好的。 散列本身也是不安全的。例如,相同的密码意味着相同的哈希——这使得哈希查找表成为同时破解大量密码的有效方法。相反,把盐腌的土豆泥储存起来。salt是在散列之前附加到密码的字符串-每个用户使用不同的(随机)salt。salt是一个公共值,因此可以将它们与哈希一起存储在数据库中。更多信息请参见此处。好的。 这意味着您不能向用户发送他们忘记的密码(因为您只有散列值)。除非您已经验证了用户身份,否则不要重置用户的密码(用户必须证明他们能够读取发送到存储(和验证)电子邮件地址的电子邮件。)好的。安全问题 安全问题是不安全的-避免使用它们。为什么?任何安全问题都可以,密码更好。阅读第三部分:使用@jens roland中的秘密问题在此wiki中回答。好的。会话cookie 用户登录后,服务器向用户发送会话cookie。服务器可以从cookie中检索用户名或ID,但没有其他人可以生成这样的cookie(要解释机制)。好的。 cookies可以被劫持:它们只有和客户机的其他机器和其他通信一样安全。它们可以从磁盘读取,在网络流量中嗅探,被跨站点脚本攻击解除,从中毒的DNS进行网络钓鱼,因此客户端将其cookie发送到错误的服务器。不要发送持久的cookie。cookie应该在客户端会话结束时过期(浏览器关闭或离开您的域)。好的。 如果要自动登录用户,可以设置持久cookie,但它应与完整会话cookie不同。您可以设置一个额外的标志,用户已经自动登录,并且需要为敏感操作实际登录。这一点很受购物网站的欢迎,这些网站希望为您提供无缝、个性化的购物体验,但仍然保护您的财务细节。例如,当你返回亚马逊时,他们会给你显示一个看起来你已经登录的页面,但是当你去下订单(或者更改你的送货地址、信用卡等)时,他们会要求你确认密码。好的。 另一方面,银行和信用卡等金融网站只有敏感数据,不应允许自动登录或低安全模式。好的。外部资源列表
好啊。 首先,强烈警告说,这个答案不适合这个确切的问题。这绝对不是最好的答案! 我将继续讨论Mozilla提出的browserid(或者更准确地说,是经过验证的电子邮件协议),本着在未来找到更好的身份验证方法的升级路径的精神。 我将这样总结: 这并不是严格的"基于表单的网站认证"。但是,这是一项努力,从当前基于表单的身份验证的规范过渡到更安全的规范:浏览器支持的身份验证。 我只是觉得我会分享这个解决方案,我发现它工作得很好。 我称之为虚拟场(尽管我没有发明这个,所以不要相信我)。 简而言之:您只需将它插入到您的 |