2019年正确实施双因素认证 - Trail of Bits博客
自3月以来,Trail of Bits一直与Python软件基金会合作,为Warehouse(PyPI的代码库)添加双因素认证(2FA)。截至目前,PyPI成员可以启用基于时间的OTP(TOTP)和WebAuthn(目前处于测试阶段)。如果您在PyPI上有账户,请在继续阅读之前启用您偏好的2FA方法!
2018年和2019年是双因素认证的重要年份:
- W3C和FIDO于3月最终确定了Level 1 WebAuthn规范。Chrome和Firefox已经对其提供了成熟支持,Safiri预计也会跟进。
- 即将发布的Android版本将允许用户将手机用作安全密钥,iOS预计也会这样做。
- CTAP2标准的进展持续。虽然WebAuthn不需要CTAP2,但未来的WebAuthn设备将受益于其传输和认证器配置改进。
- 主要网站已开始不鼓励使用SMS和语音代码,这些作为第二因素已经完全失效。Google现在允许G-Suite管理员强制执行无SMS的2FA,防止用户向其2FA方法添加薄弱环节。
总之,现在是为您的服务添加2FA的最佳时机。继续阅读以了解如何正确实施。
什么是2FA,什么不是
在讨论实施双因素认证的正确决策之前,理解第二因素应该是什么和不应该是什么至关重要。
特别是:
- 第二因素方法不应该是可知的。第二因素方法是用户拥有或所是的东西,而不是用户知道的东西。
- 第二因素方法不应替代用户的第一因素(通常是密码)。因为它们是用户拥有或所是的东西,它们是身份证明。WebAuthn是此规则的部分例外:由于其更强的保证,它可以作为单因素使用。
- 第二因素方法可按安全性排序。特别是,WebAuthn总是优于TOTP,因此启用了两者的用户应首先被提示使用WebAuthn。不要让用户默认使用安全性较低的第二因素。如果出于遗留原因支持SMS作为第二因素,请告知用户一旦添加了更好的方法就可以移除它。
- 2FA实现不应在第一因素之前请求用户的第二因素。这对于TOTP来说无论如何都不可行,但您可能会尝试使用WebAuthn凭据的ID或公钥。这本身不会引入安全风险,但不一致的排序只会混淆已经难以理解其安全密钥在认证中作用的用户。
- 恢复代码应可用,并且应为偏好账户失败致命的用户提供足够警告的选择退出。恢复代码不是第二因素——它们绕过了2FA方案。然而,用户不理解2FA(见下文),如果没有直接的恢复方法,他们会出于沮丧而禁用它。当安全存储时,恢复代码代表了可用性和2FA方案健全性之间的可接受妥协。
您的用户不理解2FA,并会尝试破坏它
用户,即使是技术极客(如普通PyPI包维护者),也不理解2FA或其约束。他们会在不同程度上:
| 尝试行为 | 风险 | 补救措施 |
|---|---|---|
| 截图TOTP二维码并留在Downloads文件夹中 | TOTP密钥暴露 | 文档:警告用户不要保存二维码 |
| 使用相同二维码配置多个TOTP应用 | 对第二因素的理解不足 | 文档:告知用户只配置一个设备 |
| 使用允许以未加密文本导出代码的TOTP应用 | TOTP密钥暴露;不安全的密钥管理 | 文档:建议不支持未加密导出的TOTP应用 |
| 使用损坏的TOTP应用或不尊重TOTP参数的应用 | 错误的TOTP代码生成;应用中混淆的TOTP标签 | 几乎没有:几乎所有TOTP应用都忽略或施加额外约束。使用默认配置参数! |
| 用错误应用扫描TOTP二维码 | 丢失第二因素;无法登录 | 要求在接受配置请求前输入TOTP代码 |
| 尝试手动输入配置URI或密钥并出错 | 丢失第二因素;无法登录 | 同上;要求TOTP代码完成配置 |
| 错误标记TOTP登录并混淆 | 错误标记的第二因素;无法登录 | 提供otpauth支持的所有用户名和发行者名字段。不鼓励用户使用只支持服务白名单或需要手动标记的TOTP应用 |
| 在服务前从应用中删除TOTP密钥 | 账户锁定 | 文档:警告用户不要这样做,并推荐提供类似警告的TOTP应用 |
| 将恢复代码保存到桌面文本文件 | 第二因素绕过 | 使恢复代码选择加入,并告知用户只保存恢复代码的打印副本 |
| 混淆不同服务的恢复代码 | 丢失绕过;无法登录 | 在恢复代码前添加站点名称或其他区分标识符 |
| 完全忽略第二因素,只使用恢复代码 | 不是真正的2FA | 跟踪恢复代码使用并警告重复违规者 |
| 尝试使用旧的RSA SecurID、奇怪的企业HOTP令牌或pre-U2F密钥 | WebAuthn不支持 | 在配置失败时提供明确错误。大多数浏览器应对pre-U2F密钥执行此操作 |
| 混淆硬件密钥 | 错误标记的第二因素;无法登录 | 让用户能够在服务上用友好名称标记注册的密钥,并鼓励他们物理标记 |
| 在不取消配置的情况下赠送或转售硬件密钥 | 第二因素泄露 | 文档:警告用户不要这样做。对于更激进的安全,定期挑战他们验证每个WebAuthn凭据 |
技术用户可能更糟:在撰写本文时,一位熟人讲述了使用Twilio和通知推送服务绕过其大学基于SMS的2FA的故事。
这些情景中的许多部分不可避免,并非所有都从根本上削弱或威胁削弱2FA设置的健全性。然而,您应该意识到每一个,并尽可能寻求用户验证您的方案。
WebAuthn和TOTP是您唯一需要的
您不需要SMS或语音代码。如果您目前出于遗留原因支持SMS或语音代码,那么您应该:
- 防止新用户启用它们,
- 告知当前用户移除它们并切换到WebAuthn或TOTP,以及
- 对仍启用SMS和/或语音代码的用户执行额外日志记录和警报。
偏执?是的。但如果您持有任何加密货币,您可能应该偏执。
过度?也许。SIM端口攻击仍然相对不常见(且有针对性),尽管几乎不需要技术技能。通过SMS或语音代码进行2FA仍然比什么都没有好。Google自己的研究表明,仅SMS就能防止几乎所有非针对性钓鱼攻击。针对性攻击的数字更黯淡:近四分之一的针对性攻击对仅基于SMS的2FA用户成功。
担心除了SMS之外的其他方法不实用和/或成本高?别担心。有大量免费的TOTP应用可用于iOS和Android。在WebAuthn方面,Google将以50美元的价格向您出售包含两个安全密钥的套件。您甚至可以购买一个完全开源的密钥,以25美元的价格与WebAuthn配合使用!最重要的是:TOTP不如硬件密钥好,这不是继续允许SMS或语音代码的借口。
对比TOTP和WebAuthn
TOTP和WebAuthn都是为服务添加2FA的可靠选择,如果有机会,您应该支持两者。以下是一些考虑因素:
TOTP是对称且简单的,WebAuthn是非对称且复杂的
TOTP是一种对称加密方案,意味着客户端和服务器共享一个密钥。这加上TOTP相对简单的代码生成过程,使其易于实现,但导致一些陷阱:
- 因为客户端需要存储对称密钥,TOTP的安全性仅与包含应用或设备一样。如果恶意程序可以提取用户的TOTP密钥,则他们可以在用户不知情的情况下生成任意数量的有效TOTP代码。
- 因为TOTP中客户端和服务器之间共享的唯一状态是初始密钥和后续生成的代码,TOTP缺乏设备身份的概念。因此,信息错误的用户可以使用相同的密钥配置多个设备,增加其攻击面。
- TOTP不提供固有的重放保护。服务可能通过拒绝接受有效代码多次来防止重放,但这可能困扰在TOTP窗口内多次登录的合法用户。
- 可能可暴力破解。大多数服务使用6或8位TOTP代码,并提供扩展的验证窗口以适应行动不便的用户(和时钟漂移),使在线暴力破解刚好在可行性边缘。解决方案:限制登录尝试速率。
以上所有因素使TOTP代码成为理想的钓鱼目标。私人和国家团体都成功使用虚假登录表单和其他技术成功欺骗用户共享其TOTP代码。
相比之下,WebAuthn使用非对称公钥加密:客户端在从服务器接收选项列表后生成密钥对,将公钥部分发送到服务器用于验证目的,并安全存储私钥部分用于认证期间的签名操作。这种设计导致 substantially更复杂的证明模型,但产生许多好处:
- 设备身份:WebAuthn设备由其凭据ID标识,通常与用户管理目的的可读标签配对。WebAuthn的身份概念使其易于支持每个用户多个安全密钥——不要人为限制用户每个账户只有一个WebAuthn密钥!
- 反重放和反克隆保护:设备注册和断言方法包括认证方生成的随机挑战,行为良好的WebAuthn设备在每次断言后发送更新的签名计数器。
- 来源和安全上下文保证:WebAuthn在设备注册和证明期间包括来源信息,并仅允许在安全上下文内进行交易,防止常见钓鱼向量。
TOTP是免费的,WebAuthn(目前大部分)不是
如上所述,有许多免费的TOTP应用,可用于用户将使用的几乎所有平台。几乎所有这些都支持Google的otpauth URI“标准”,尽管完整度/正确性各不相同。
相比之下,大多数WebAuthn的潜在用户需要购买安全密钥。各种硬件密钥标准之间的关系令人困惑(可能占据整个单独的博客文章),但大多数U2F密钥应该与WebAuthn兼容。然而,WebAuthn不仅限于安全密钥:如前所述,Google正在努力使其移动设备充当WebAuthn兼容的第二因素,我们希望Apple也在做同样的事情。一旦发生,许多用户将能够无需额外购买就切换到WebAuthn。
使用正确的工具
TOTP的简单性使其成为重新实现的有吸引力的目标。不要这样做——它仍然是一个密码系统,您永远不应该自己编写密码。相反,使用成熟且抗误用的实现,如PyCA的hazmat.primitives.twofactor。
WebAuthn仍然相对较新,因此没有那么多服务器端实现可用。Duo的优秀人员正在努力补救这一点:他们已经开源了Go和Python库,并为用户和实现者提供了优秀的在线演示和文档。
从我们的工作中学习
想为您的服务添加2FA,但不知道从哪里开始?查看我们在Warehouse代码库中的TOTP和WebAuthn实现。
我们的公共接口有详细文档,并且(按照Warehouse标准)所有分支都有测试覆盖。支持多个WebAuthn密钥,并且将在不久的将来添加对可选恢复代码的支持。
如果您有其他更定制的密码学需求,请联系我们寻求帮助。