首页 文章

基于表单的网站身份验证的权威指南[关闭]

提问于
浏览
5098

基于表单的网站身份验证

我们认为Stack Overflow不仅应该是非常具体的技术问题的资源,而且还应该是关于如何解决常见问题变化的一般指导原则 . “基于表单的网站身份验证”应该是这种实验的一个很好的主题 .

应包括以下主题:

  • 如何登录

  • 如何退出

  • 如何保持登录状态

  • 管理cookie(包括推荐设置)

  • SSL / HTTPS加密

  • 如何存储密码

  • 使用秘密问题

  • 忘记了用户名/密码功能

  • 使用nonces来防止cross-site request forgeries (CSRF)

  • OpenID

  • "Remember me"复选框

  • 浏览器自动完成用户名和密码

  • 秘密网址(公众URL受摘要保护)

  • 检查密码强度

  • 电子邮件验证

  • 以及更多关于form based authentication ......

不应包括以下内容:

  • 角色和授权

  • HTTP基本身份验证

请帮助我们:

  • 建议子主题

  • 提交有关此主题的好文章

  • 编辑官方答案

12 回答

  • 122

    我以为我会分享这个我发现工作得很好的解决方案 .

    我称之为 Dummy Field (虽然我没有信任我) .

    简而言之:您只需将其插入 <form> 并在验证时检查它是否为空:

    <input type="text" name="email" style="display:none" />
    

    诀窍是欺骗机器人认为它必须将数据插入必需的字段,'s why I named the input 374547 . If you already have a field called email that you'重新使用你应该尝试命名虚拟字段,如"company","phone"或"emailaddress" . 只需选择一些您不需要的东西,以及人们通常认为可以填写到网络表单中的东西 . 现在使用CSS或JavaScript / jQuery隐藏 input 字段 - 无论什么最适合你 - 只需 don't 将输入 type 设置为 hidden ,否则机器人不会因此而失败 .

    当您验证表单(客户端或服务器端)时,检查您的虚拟字段是否已填满,以确定它是由人还是机器人发送的 .

    例:

    In case of a human: 用户将看不到虚拟字段(在我的情况下名为"email")并且不会尝试填充它 . 因此,在发送表单时,虚拟字段的值仍应为空 .

    In case of a bot: 机器人将看到一个类型为 text 且名称为 email (或者您称之为它的任何名称)的字段,并且将逻辑上尝试用适当的数据填充它 . 只要它大于 0 个字符,它就不会受到关注 .

    我在留言簿上使用这种方法与CAPTCHA结合使用,之后我没有看过任何一封垃圾邮件帖子 . 我之前使用过CAPTCHA解决方案,但最终每小时产生大约5个垃圾邮件 . 在表单中添加虚拟字段已停止(至少到现在为止)所有垃圾邮件都会出现 .

    我相信这也可以用于登录/身份验证表单 .

    Warning :当然这种方法并非100%万无一失 . 可以将机器人编程为忽略应用了样式 display:none 的输入字段 . 您还必须考虑使用某种形式的自动完成功能的人(如大多数浏览器内置的!)来自动填充所有表单字段 . 他们可能也会选择一个虚拟场 .

    您也可以通过让虚拟区域可见但在屏幕边界之外可以稍微改变一下,但这完全取决于您 .

    要有创意!

  • 47

    我不认为上述答案是“错误的”,但有大量的认证没有涉及(或者更重要的是“如何实现cookie会话”,而不是“有哪些选项可用,什么是交易” -offs” .

    我建议的编辑/答案是

    • 问题在于帐户设置比在密码检查中更多 .

    • 使用双因素身份验证比更聪明的密码加密方法更安全

    • 不要尝试实现自己的密码登录表单或数据库存储,除非在创建帐户和自行生成时存储的数据是无 Value 的(即Facebook 2.0样式,如Facebook,Flickr等)

    • 摘要式身份验证是一种基于标准的方法,支持所有主流浏览器和服务器,即使通过安全通道也不会发送密码 .

    这避免了任何需要“会话”或cookie,因为浏览器本身每次都会重新加密通信 . 它是最“轻量级”的开发方法 .

    但是,除了公共的低 Value 服务之外,我不建议这样做 . 这是上面一些其他答案的问题 - 不要尝试重新实现服务器端身份验证机制 - 这个问题已经解决并且得到了大多数主流浏览器的支持 . 不要使用cookies . 不要在您自己的手动数据库中存储任何内容 . 根据请求,只询问请求是否经过身份验证 . 配置和第三方可信软件应支持其他所有功能 .

    所以......

    首先,我们将初始创建帐户(带密码)与随后重新检查密码混淆 . 如果我是Flickr并且是第一次创建您的站点,则新用户可以访问零值(空白Web空间) . 如果创建帐户的人谎称他们的名字,我真的不在乎 . 如果我正在创建医院内联网/外联网的帐户,则 Value 在于所有医疗记录,因此我关心帐户创建者的身份(*) .

    这是非常困难的部分 . 唯一合适的解决方案是信任网 . 例如,您作为医生加入医院 . 您创建一个托管在您的照片,护照号码和公钥的某个地方的网页,并使用私钥对它们进行哈希处理 . 然后,您访问医院,系统管理员查看您的护照,查看照片是否与您匹配,然后使用医院私钥对网页/照片哈希进行哈希处理 . 从现在开始,我们可以安全地交换密钥和令牌 . 任何信任医院的人都可以(有秘密酱BTW) . 系统管理员还可以为您提供RSA加密狗或其他双因素身份验证 .

    但这是一个很麻烦,而不是非常web 2.0 . 但是,它是创建可以访问非自创的有 Value 信息的新帐户的唯一安全方法 .

    • Kerberos和SPNEGO - 具有可信第三方的单点登录机制 - 基本上用户验证受信任的第三方 . (注意,这绝不是不可信任的OAuth

    • SRP - 一种没有可信第三方的聪明密码验证 . 但在这里我们正在进入"it's safer to use two-factor authentication, even if that's costlier"的领域

    • SSL客户端 - 为客户端提供公钥证书(在所有主流浏览器中都支持 - 但会引发有关客户端计算机安全性的问题) .

    最后,这是一个权衡 - 安全漏洞的成本与实施更安全的方法的成本是什么 . 有一天,我们可能会看到一个被广泛接受的正确的PKI,因此不再拥有自己的滚动身份验证表单和数据库 . 一天...

  • 42

    我不知道最好回答这个问题作为答案或评论 . 我选择了第一个选项 .

    关于第一个答案中的poing PART IV: Forgotten Password Functionality ,我会指出时间攻击 .

    Remember your password 表单中,攻击者可能会检查完整的电子邮件列表并检测哪些已注册到系统(请参阅下面的链接) .

    关于遗忘密码表格,我想补充说,使用一些延迟函数在成功和不成功查询之间等于时间是个好主意 .

    https://crypto.stanford.edu/~dabo/papers/webtiming.pdf

  • 10

    我想补充一点非常重要的评论: -

    • “在公司, intra- 网络设置中,”大多数(如果不是全部)上述内容可能不适用!

    许多公司部署"internal use only"网站实际上是"corporate applications",这些网站恰好是通过URL实现的 . 这些URL可以(据说......)只能在"the company's internal network."内解析(哪个网络神奇地包括所有连接VPN的'road warriors.')

    当用户尽职地连接到上述网络时,他们的身份("authentication")是[已经......] "conclusively known,",因为他们允许("authorization")做某些事情......例如... "to access this website."

    此"authentication + authorization"服务可以由多种不同的技术提供,例如LDAP(Microsoft OpenDirectory)或Kerberos .

    从你的观点来看,你只知道这一点:任何合法地在你的网站上结束的人必须伴随着[一个环境变量神奇地包含......] "token."(即缺少这样的标记必须是 404 Not Found 的直接理由 . )

    令牌的 Value 对你没有意义,但是,如果需要,你的网站可以"[authoritatively] ask someone who knows (LDAP... etc.)"关于你可能有的任何(!)问题 . 换句话说,你做了 not 利用任何"home-grown logic."相反,你询问管理局并暗中信任其判决 .

    嗯......这是"wild-and-wooly Internet."的精神转换

  • 20

    关于身份验证系统我最喜欢的规则是:使用密码而不是密码 . 容易记住,难以破解 . 更多信息:Coding Horror: Passwords vs. Pass Phrases

  • 12

    我想根据防御深度添加一个我使用过的建议 . 您不需要为常规用户提供与管理员相同的auth&auth系统 . 您可以在单独的URL上使用单独的登录表单,为要授予高权限的请求执行单独的代码 . 这个可以做出对普通用户来说完全痛苦的选择 . 我使用过的一种方法是实际加密管理员访问的登录URL,并通过电子邮件向管理员发送新的URL . 由于您的新网址可能是任意困难(非常长的随机字符串),因此立即停止任何暴力攻击,但您的管理员用户唯一的不便是关注其电子邮件中的链接 . 攻击者不再知道POST的位置至 .

  • 5

    第一部分:如何登录

    我们假设您已经知道如何构建登录密码HTML表单,该表单将值POST到服务器端的脚本以进行身份验证 . 下面的部分将讨论声音实用auth的模式,以及如何避免最常见的安全陷阱 .

    To HTTPS or not to HTTPS?

    除非连接已经安全(即使用SSL / TLS通过HTTPS进行隧道传输),否则您的登录表单值将以明文形式发送,这允许任何窃听浏览器和Web服务器之间的线路的人都能够在通过时读取登录信息通过 . 这种类型的窃听是由政府定期完成的,但总的来说,除了这样说之外,我们不会解决“拥有”的电话:如果您要保护任何重要信息,请使用HTTPS .

    本质上,在登录期间防止窃听/数据包嗅探的唯一方法是使用HTTPS或其他基于证书的加密方案(例如,TLS)或经过验证和测试的质询 - 响应方案(例如,基于Diffie-Hellman的方法) SRP) . 窃听攻击者可以轻易地绕过任何其他方法 .

    当然,如果您愿意变得有点不切实际,您还可以采用某种形式的双因素身份验证方案(例如Google身份验证器应用程序,物理“冷战风格”代码簿或RSA密钥生成器加密狗) . 如果应用正确,即使使用不安全的连接,这也可以工作,但是很难想象开发人员愿意实现双因素身份验证而不是SSL .

    (Do not) Roll-your-own JavaScript encryption/hashing

    考虑到在您的网站上设置SSL证书的非零成本和感知技术难度,一些开发人员倾向于推出他们自己的浏览器内哈希或加密方案,以避免通过不安全的线路传递明文登录 .

    虽然这是一个崇高的想法,但它基本上是无用的(并且可以是security flaw),除非它与上述之一相结合 - 即,使用强加密保护线路或使用久经考验的挑战 - 响应机制(如果你不知道那是什么,只要知道它是最难以证明的,最难设计的,也是最难实现的数字安全概念) .

    虽然哈希密码确实对 password disclosure 有效,但它很容易受到重放攻击,中间人攻击/劫持(如果攻击者在到达浏览器之前可以向你的不安全的HTML页面注入几个字节) ,他们可以简单地注释掉JavaScript中的哈希,或者暴力攻击(因为你正在向攻击者发送用户名,盐和哈希密码) .

    CAPTCHAS against humanity

    CAPTCHAs旨在挫败一种特定类型的攻击:自动字典/强力试错,没有人类操作员 . 毫无疑问,这是一个真正的威胁,然而,有一些方法可以无缝地处理它,以后再讨论它们 .

    知道CAPTCHA实现不是一样的;它们通常不是人类可以解决的,其中大多数实际上对机器人无效,所有这些都对廉价的第三世界劳动力无效(根据OWASP,目前的血汗工厂率为每500次测试12美元),并且一些实施可能是在某些国家,技术上是非法的(见OWASP Authentication Cheat Sheet) . 如果你必须使用验证码,请使用谷歌的reCAPTCHA,因为它定义为OCR-hard(因为它使用已经过OCR错误分类的书籍扫描)并且非常努力地使用户友好 .

    就个人而言,我倾向于发现CAPTCHAS很烦人,并且当用户多次登录失败并且节流延迟最大化时,仅将其用作最后的手段 . 这种情况很少能够被接受,并且它会加强整个系统 .

    Storing Passwords / Verifying logins

    在我们近年来看到的所有高度公开的黑客攻击和用户数据泄漏之后,这可能最终是常识,但必须说明:不要在数据库中以明文形式存储密码 . 用户数据库通常会通过SQL注入被黑客入侵,泄露或收集,如果您要存储原始明文密码,那么即时游戏结束也是为了您的登录安全性 .

    因此,如果您无法存储密码,如何检查登录表单中登录的登录密码组合是否正确?答案是使用key derivation function进行哈希处理 . 无论何时创建新用户或更改密码,您都会获取密码并通过KDF(例如Argon2,bcrypt,scrypt或PBKDF2)运行密码,将明文密码("correcthorsebatterystaple")转换为长而随机的字符串,存储在您的数据库中更安全 . 要验证登录,请对输入的密码运行相同的哈希函数,这次传入salt并将生成的哈希字符串与存储在数据库中的值进行比较 . Argon2,bcrypt和scrypt已经将哈希值与哈希一起存储 . 有关更多详细信息,请查看sec.stackexchange上的article .

    使用盐的原因是哈希本身是不够的 - 你需要盐保护哈希对抗rainbow tables . salt有效地防止两个完全匹配的密码被存储为相同的哈希值,从而防止在攻击者执行密码猜测攻击时在一次运行中扫描整个数据库 .

    加密哈希不应该用于密码存储,因为用户选择的密码不够强(即通常不包含足够的熵),并且密码猜测攻击可以在相对较短的时间内由访问哈希的攻击者完成 . 这就是使用KDF的原因 - 这些有效"stretch the key"意味着每个密码猜测攻击者会多次迭代哈希算法,例如10,000次,使攻击者的密码猜测速度慢10,000倍 .

    Session data - "You are logged in as Spiderman69"

    一旦服务器针对您的用户数据库验证了登录名和密码并找到了匹配项,系统就需要一种方法来记住浏览器已经过身份验证 . 这个事实应该只存储在会话数据的服务器端 .

    如果您不熟悉会话数据,可以使用以下方法:单个随机生成的字符串存储在过期的cookie中,用于引用存储在服务器上的数据集合 - 会话数据 . 如果您使用的是MVC框架,那么这无疑已经得到了解决 .

    如果可能的话,确保会话cookie在发送到浏览器时设置了安全和仅HTTP标志 . HttpOnly标志提供一些保护,防止XSS攻击读取cookie . 安全标志确保cookie仅通过HTTPS发回,因此可以防止网络嗅探攻击 . cookie的值不应该是可预测的 . 如果呈现引用不存在的会话的cookie,则应立即替换其值以防止session fixation .

    第二部分:如何保持登录状态 - 臭名昭着的“记住我”复选框

    持久登录Cookie(“记住我”功能)是一个危险区域;一方面,当用户了解如何处理它们时,它们完全像传统登录一样安全;另一方面,它们在粗心用户手中是一个巨大的安全风险,他们可能在公共计算机上使用它们而忘记注销,并且可能不知道浏览器cookie是什么或如何删除它们 .

    就个人而言,我喜欢定期访问的网站的持久登录,但我知道如何安全地处理它们 . 如果您确信您的用户知道相同的内容,则可以使用持久登录并保持良心 . 如果不是 - 那么,你可以赞同这样的理念:如果用户被黑客攻击,那么他们的登录凭证不小心的用户会自行处理 . 这并不像我们去我们用户的房子并撕下所有那些引人注目的Post-It笔记,上面还有他们在显示器边缘排列的密码 .

    当然,有些系统无法承受任何帐户被黑客攻击;对于这样的系统,你无法证明持久登录的合理性 .

    If you DO decide to implement persistent login cookies, this is how you do it:

    • 首先,请花一些时间阅读有关该主题的Paragon Initiative's article . 你需要正确地获得一堆元素,而且这篇文章很好地解释了每一个元素 .

    • 只是重申一个最常见的陷阱, DO NOT STORE THE PERSISTENT LOGIN COOKIE (TOKEN) IN YOUR DATABASE, ONLY A HASH OF IT! 登录令牌是密码等效,所以如果攻击者 grab 你的数据库,他们可以使用令牌登录任何帐户,就好像他们是明文登录一样 - 密码组合 . 因此,在存储持久登录令牌时,使用散列(根据https://security.stackexchange.com/a/63438/5002弱散列将为此目的做得很好) .

    第三部分:使用秘密问题

    Don't implement 'secret questions' . 'secret questions'功能是一种安全反模式 . 阅读MUST-READ列表中链接号4的论文 . 在雅虎之后,你可以向Sarah Palin询问这个问题 . 电子邮件帐户在之前的总统竞选期间被黑了,因为她的安全问题的答案是...... "Wasilla High School"!

    即使有用户指定的问题,大多数用户也很可能会选择:

    • 一个'标准'秘密问题,如母亲的娘家姓或宠物

    • 一个简单的琐事,任何人都可以从他们的博客,LinkedIn Profiles 或类似的东西中解脱出来

    • 任何比猜测密码更容易回答的问题 . 对于任何体面的密码,您可以想象的每一个问题

    In conclusion, security questions are inherently insecure in virtually all their forms and variations, and should not be employed in an authentication scheme for any reason.

    安全问题甚至存在于野外的真正原因是它们可以方便地节省来自无法访问其电子邮件以获得重新激活代码的用户的一些支持呼叫的成本 . 这是以牺牲安全性和Sarah Palin的声誉为代价的 . 值得?可能不是 .

    第四部分:忘记密码功能

    我已经提到为什么你应该 never use security questions 处理忘记/丢失的用户密码;不言而喻,您绝不应该通过电子邮件向用户发送他们的实际密码 . 在这个领域至少还有两个需要避免的常见缺陷:

    • 不要将忘记的密码重置为自动生成的强密码 - 这种密码非常难以记住,这意味着用户必须更改密码或将其写下来 - 例如,在显示器边缘的亮黄色Post-It上 . 不要设置新密码,只需让用户立即选择一个新密码 - 这也是他们想要做的事情 . (例外情况可能是用户普遍使用密码管理器来存储/管理通常无法记住的密码而不将其写下来) .

    • 始终在数据库中散列丢失的密码代码/令牌 . AGAIN ,此代码是密码等效的另一个示例,因此必须进行哈希处理,以防攻击者 grab 您的数据库 . 当请求丢失的密码代码时,将明文代码发送到用户的电子邮件地址,然后对其进行哈希处理,将哈希值保存在数据库中 - 然后丢弃原始密码 . 就像密码或持久登录令牌一样 .

    最后一点:始终确保用于输入“丢失的密码代码”的界面至少与登录表单本身一样安全,或者攻击者只是使用它来获取访问权限 . 确保生成很长的“丢失密码代码”(例如,16个区分大小写的字母数字字符)是一个好的开始,但考虑添加与登录表单本身相同的限制方案 .

    第五部分:检查密码强度

    首先,您需要阅读这篇小文章进行现实检查:The 500 most common passwords

    好吧,也许这个列表不是任何地方任何系统上最常见密码的规范列表,但它很好地表明当没有强制执行的策略时,人们会选择密码的能力有多差 . 此外,当您将该列表与最近被盗密码的公开分析进行比较时,该列表看起来非常接近家 .

    因此:没有最低密码强度要求,2%的用户使用前20个最常用的密码之一 . 含义:如果攻击者只获得20次尝试,则您网站上50个帐户中的1个将被破解 .

    阻止这一点需要计算密码的熵,然后应用阈值 . 美国国家标准与技术研究院(NIST)Special Publication 800-63提出了一系列非常好的建议 . 当与字典和键盘布局分析(例如,'qwertyuiop'是一个错误的密码)结合使用时,可以reject 99% of all poorly selected passwords处于18位熵的水平 . 简单地为用户计算密码强度和showing a visual strength meter是好的,但不够 . 除非强制执行,否则许多用户很可能会忽略它 .

    为了更好地了解高熵密码的用户友好性,强烈推荐Randall Munroe的Password Strength xkcd .

    第六部分:更多 - 或者:防止快速登录尝试

    首先,看看数字:Password Recovery Speeds - How long will your password stand up

    如果您没有时间查看该链接中的表,请按以下列表列出:

    • 几乎没有时间破解弱密码,即使你用算盘破解密码也是如此

    • 如果它是 case insensitive ,几乎没有时间破解字母数字9个字符的密码

    • 几乎没有时间破解复杂的符号和字母和数字大小写密码如果是 less than 8 characters long (台式PC可以在几天内搜索整个密钥空间最多7个字符或者连小时)

    • It would, however, take an inordinate amount of time to crack even a 6-character password, if you were limited to one attempt per second!

    那么我们可以从这些数字中学到什么呢?好吧,很多,但我们可以专注于最重要的部分:阻止大量快速连续登录尝试(即暴力攻击)的事实并不那么困难 . 但是,正确防止它并不像看起来那么容易 .

    一般来说,您有三种选择可以有效抵御暴力攻击(以及字典攻击,但由于您已经采用强密码策略,因此它们应该不是问题):

    • 在N次尝试失败后出现 CAPTCHA (令人讨厌并经常无效 - 但我在这里重复一遍)

    • Locking accounts 并在N次尝试失败后要求进行电子邮件验证(这是DoS等待发生的攻击)

    • 最后, login throttling :也就是说,在尝试N次失败后尝试之间设置时间延迟(是的,仍然可以进行DoS攻击,但至少它们的可能性要小得多,而且拉起来要复杂得多) .

    Best practice #1: 短暂的时间延迟随着尝试失败的次数而增加,例如:

    • 1尝试失败=没有延迟

    • 2次失败尝试= 2秒延迟

    • 3次失败尝试= 4秒延迟

    • 4次失败尝试= 8秒延迟

    • 5次尝试失败= 16秒延迟

    DoS攻击这个方案是非常不切实际的,因为结果锁定时间略大于先前锁定时间的总和 .

    澄清一下:在将响应返回给浏览器之前,延迟不是延迟 . 它更像是登录尝试特定帐户或特定IP的超时或不应期地址不会被接受或评估 . 也就是说,正确的凭据将不会在成功登录时返回,并且不正确的凭据不会触发延迟增加 .

    Best practice #2: 中等时间延迟,在N次尝试失败后生效,如:

    • 1-4尝试失败=没有延迟

    • 5次尝试失败=延迟15-30分钟

    DoS攻击这个计划是非常不切实际的,但肯定是可行的 . 此外,可能需要注意的是,如此长的延迟对于合法用户来说可能非常烦人 . 忘记用户会不喜欢你 .

    Best practice #3: 结合这两种方法 - 在N次尝试失败后生效的固定短时间延迟,如:

    • 1-4尝试失败=没有延迟

    • 5次失败尝试= 20秒延迟

    或者,具有固定上限的增加延迟,例如:

    • 1尝试失败= 5秒延迟

    • 2次失败尝试= 15秒延迟

    • 3次失败尝试= 45秒延迟

    这个最终方案取自OWASP最佳实践建议(来自MUST-READ列表的链接1),并且应该被认为是最佳实践,即使它是公认的限制性方面 .

    但是,根据经验,我会说:您的密码策略越强,您就越不会对延迟的用户造成错误 . 如果您需要强大的(区分大小写的字母数字所需的数字和符号)9个字符的密码,您可以在激活限制之前为用户提供2-4次非延迟密码尝试 .

    DoS攻击这个最终登录限制方案将是 very 不切实际 . 作为最后的触摸,始终允许持久(cookie)登录(和/或验证CAPTCHA的登录表单)通过,因此合法用户甚至不会在攻击进行中被延迟 . 这样,非常不切实际的DoS攻击变成了一种非常不切实际的攻击 .

    此外,对管理员帐户进行更积极的限制是有意义的,因为这些是最具吸引力的切入点

    第七部分:分布式蛮力攻击

    同样,更高级的攻击者会试图通过“传播他们的活动”来规避登录限制:

    • 在僵尸网络上分发尝试以防止IP地址标记

    • 而不是选择一个用户并尝试50.000最常见的密码(由于我们的限制,他们不能这样做),他们会选择最常用的密码并尝试对抗50.000用户 . 这样,他们不仅可以绕过CAPTCHA和登录限制等最大限度尝试措施,而且成功的机会也会增加,因为最常见的1号密码比49.995更容易发生 .

    • 将每个用户帐户的登录请求间隔起来,比如相隔30秒,以便潜入雷达

    在这里,最佳做法是 logging the number of failed logins, system-wide ,并使用您网站的错误登录频率的运行平均值作为您对所有用户施加的上限的基础 .

    太抽象了?让我重新说一下:

    假设您的网站在过去3个月内平均每天有120次不良登录 . 使用它(运行平均值),您的系统可能将全局限制设置为3倍 - 即 . 在24小时内完成360次尝试失败 . 然后,如果所有帐户中的失败尝试总数在一天内超过该数量(甚至更好,监控加速率并触发计算的阈值),则会激活系统范围的登录限制 - 这意味着所有用户的短暂延迟(仍然,cookie登录和/或备份CAPTCHA登录除外) .

    我还发布了一个问题more details and a really good discussion of how to avoid tricky pitfals来抵御分布式暴力攻击

    第VIII部分:双因素身份验证和身份验证提供程序

    凭据可能会受到损害,无论是利用漏洞,密码被记录下来还是丢失,密钥被盗的笔记本电脑,还是用户登录钓鱼网站 . 可以使用双因素身份验证进一步保护登录,该身份验证使用带外因素,例如从电话呼叫,SMS消息,应用程序或加密狗接收的一次性代码 . 一些提供商提供双因素身份验证服务 .

    身份验证可以完全委托给单点登录服务,其中另一个提供程序处理收集凭据 . 这会将问题推送给受信任的第三方 . 谷歌和Twitter都提供基于标准的SSO服务,而Facebook则提供类似的专有解决方案 .

    必读链接关于Web身份验证

  • 3570

    最终文章

    发送凭据

    100%安全地发送凭证的唯一实用方法是使用SSL . 使用JavaScript来散列密码是不安全的 . 客户端密码散列的常见缺陷:

    • 如果客户端和服务器之间的连接未加密,则您所做的一切都是vulnerable to man-in-the-middle attacks . 攻击者可以替换传入的javascript以打破散列或将所有凭据发送到他们的服务器,他们可以收听客户响应并完美地模仿用户等 . 具有可信证书颁发机构的SSL旨在防止MitM攻击 .

    • 如果您不在服务器上执行其他冗余工作,则服务器收到的哈希密码为less secure .

    还有一种名为 SRP 的安全方法,但它已获得专利(虽然它是freely licensed)并且几乎没有很好的实现可用 .

    存储密码

    唐't ever store passwords as plaintext in the database. Not even if you don't关心您自己网站的安全性 . 假设您的某些用户将重复使用其在线银行帐户的密码 . 因此,存储哈希密码,并丢弃原始密码 . 并确保密码不会显示在访问日志或应用程序日志中 . OWASP recommends the use of Argon2作为新应用程序的首选 . 如果不可用,则应使用PBKDF2或scrypt . 最后,如果以上都不可用,请使用bcrypt .

    哈希本身也是不安全的 . 例如,相同的密码意味着相同的哈希 - 这使得哈希查找表成为一次破解大量密码的有效方法 . 而是存储 salted 哈希 . salt是在散列之前附加到密码的字符串 - 每个用户使用不同的(随机)salt . salt是一个公共值,因此您可以将它们与哈希存储在数据库中 . 有关详细信息,请参阅here .

    这意味着您无法向用户发送他们忘记的密码(因为您只有哈希) . 除非您已对用户进行身份验证,否则请勿重置用户的密码(用户必须证明他们能够阅读发送到存储(和验证的)电子邮件地址的电子邮件 . )

    安全问题

    安全问题是不安全的 - 避免使用它们 . 为什么?安全问题,密码做得更好 . 在这个wiki中阅读 PART III: Using Secret Questions 中的 PART III: Using Secret Questions .

    会话cookie

    用户登录后,服务器会向用户发送会话cookie . 服务器可以从cookie中检索用户名或id,但是没有其他人可以生成这样的cookie(TODO解释机制) .

    Cookies can be hijacked:它们仅与客户端的其他部分一样安全's machine and other communications. They can be read from disk, sniffed in network traffic, lifted by a cross-site scripting attack, phished from a poisoned DNS so the client sends their cookies to the wrong servers. Don' t发送持久性cookie . Cookie应在客户端会话结束时过期(浏览器关闭或离开您的域) .

    如果要自动登录用户,可以设置持久性cookie,但它应与完整会话cookie不同 . 您可以设置用户已自动登录的附加标志,并且需要登录才能进行敏感操作 . 这对于希望为您提供无缝,个性化购物体验但仍保护您的财务详细信息的购物网站而言非常受欢迎 . 例如,当您返回访问亚马逊时,他们会向您显示一个看起来像您已登录的页面,但当您下订单(或更改您的送货地址,信用卡等)时,他们会要求您确认你的密码 .

    另一方面,银行和信用卡等金融网站只有敏感数据,不允许自动登录或低安全模式 .

    外部资源清单

  • 396

    使用OpenID ConnectUser-Managed Access .

    因为没有比没有做更有效的事情 .

  • 149

    散列时,不要使用快速哈希算法,如MD5(存在许多硬件实现) . 使用像SHA-512这样的东西 . 对于密码,较慢的哈希值更好 .

    创建哈希值的速度越快,任何强力检查器都可以工作得越快 . 较慢的哈希因此会减慢暴力迫使 . 慢速哈希算法会使更长时间的密码(8位数)变得不切实际

  • 71
  • 48

    首先,一个强烈的警告,这个答案不是最适合这个问题的答案 . 绝对不应该是最好的答案!

    我将继续提及Mozilla提出的BrowserID(或者更确切地说,Verified Email Protocol),其目的是寻找未来更好的身份验证方法的升级途径 .

    我会这样总结一下:

    • Mozilla是一个非盈利组织values,可以很好地找到解决这个问题的方法 .

    • 今天的现实是大多数网站都使用基于表单的身份验证

    • 基于表单的身份验证有一个很大的缺点,即phishing的风险增加 . 要求用户将敏感信息输入到由远程实体控制的区域,而不是由其用户代理控制的区域(浏览器) .

    • 由于隐式信任浏览器(用户代理的整个想法是代表用户行事),因此它们可以帮助改善这种情况 .

    • 这里阻碍进展的主要力量是deployment deadlock . 必须将解决方案分解为自己提供一些增量收益的步骤 .

    • 用于表达内置于互联网基础设施中的身份的最简单的分散方法是域名 .

    • 作为第二级表达身份,每个域管理自己的一组帐户 .

    • 表单“account @ domain”简洁明了,并受到各种协议和URI方案的支持 . 当然,这种标识符最普遍地被认为是电子邮件地址 .

    • 电子邮件提供商已经是在线事实上的主要身份提供商 . 如果您可以证明您控制该帐户的关联电子邮件地址,则当前密码重置流程通常允许您控制帐户 .

    • 经验证的电子邮件协议被提议用于提供一种基于公钥加密的安全方法,用于简化向域B证明您在域A上拥有帐户的过程 .

    • 对于不支持已验证电子邮件协议的浏览器(目前全部都是这样),Mozilla提供了一个在客户端JavaScript代码中实现协议的填充程序 .

    • 对于不支持已验证电子邮件协议的电子邮件服务,该协议允许第三方充当可信中介,断言他们已验证用户对帐户的所有权 . 拥有大量此类第三方是不可取的;此功能仅用于允许升级路径,并且更优选的是电子邮件服务本身提供这些断言 .

    • Mozilla提供自己的服务,就像这样一个值得信赖的第三方 . 实施经过验证的电子邮件协议的服务提供商(即依赖方)可能会选择信任Mozilla的断言 . Mozilla的服务使用传统方式发送带有确认链接的电子邮件来验证用户的帐户所有权 .
      当然,除了他们可能希望提供的任何其他身份验证方法之外,服务提供商可以提供此协议作为选项 .

    • 这里寻求的一个重要的用户界面好处是“身份选择器” . 当用户访问网站并选择进行身份验证时,他们的浏览器会向他们显示他们可能用来向网站标识自己的电子邮件地址(“个人”,“工作”,“政治激进主义”等) .

    • 作为此项工作的一部分,正在寻求的另一个重大用户界面优势是helping the browser know more about the user’s session - 他们当前主要登录的是谁 - 因此它可能会在浏览器中显示Chrome .

    • 由于该系统的分布式特性,它避免了对Facebook,Twitter,Google等主要网站的锁定 . 任何个人都可以拥有自己的域名,因此可以充当自己的身份提供者 .

    这不是严格的“基于表单的网站身份验证” . 但是,这是从当前基于表单的身份验证规范过渡到更安全的东西:浏览器支持的身份验证 .

相关问题