给定一个安全通道,使用 SCRAM 而不是用户名和密码有什么好处?

信息安全 tls 密码 http 授权 挑战-反应
2021-09-03 18:44:25

鉴于通过 HTTP 进行的通信

  • 使用 SSL 加密
  • 使用公钥固定来防止中间人攻击

通过在基本访问身份验证上使用加盐挑战响应身份验证机制(SCRAM) 并随后为每个请求使用令牌,是否以任何方式提高了安全性?

3个回答

tl; dr:我一般不会推荐它,但它在特定情况下可能有用

SCRAM 的优势

  • 密码永远不会发送到服务器。通过网络发送的唯一内容是:
    • 随机数
    • 迭代次数
    • HMAC(PBKDF2(password), "Client Key") XOR HMAC(H(HMAC(PBKDF2(password), "Client Key")), AuthMessage) (说真的,我不是在编造这个!)
    • HMAC(HMAC(PBKDF2(password), "Server Key"), AuthMessage)
  • 服务器永远不知道密码,因此无法在其他服务器上冒充用户(只要这些服务器上的盐与该服务器的盐不同)

SCRAM 的缺点

  • 需要使用 PBKDF2。虽然 PBKDF2 明显优于快速哈希,但 bcrypt 更好(现在你也应该考虑 Argon2)。
  • 要求客户端处理所有计算复杂性

第一点是不幸的,但第二点才是真正的杀手锏。现在智能手机和平板电脑无处不在,您根本无法假设客户端能够通过足够的迭代快速计算 PBKDF2 以确保安全。

SCRAM 什么时候有用?

我看到 SCRAM 的用途是客户端受信任但服务器不信任。这对于 Web 应用程序永远不会正确(因为“客户端”是由...服务器发送的 JavaScript),并且有时对于本地应用程序是正确的。我能想到的最好的例子是Wikipedia 给出的例子:SMTP、IMAP 和 XMPP,在这些例子中,您信任您的电子邮件或聊天客户端,但正在向潜在的恶意第三方服务器进行身份验证。

如果客户端强制使用高迭代次数和唯一盐,它可能会降低 DNS 劫持与流氓 CA 结合的风险,但您已经通过证书固定做到了这一点。唯一需要防御的是您的服务器是恶意的,这在某些情况下可能很有用,但前提是收益超过 SCRAM 的劣势。

如果您知道将使用强密码,SCRAM可能有助于防止服务器获取密码,但该密码也将在其他地方重复使用(如果不重复使用,您为什么要关心服务器是否知道它?) . 不幸的是,这并不能真正强制执行,理想的情况是无论如何都要使用唯一的密码。


SCRAM 是如何工作的?

在 SCRAM 中,服务器存储:

  • 迭代次数
  • ServerKey = HMAC(PBKDF2(password), "Server Key")(其中"Server Key"是已知的恒定 HMAC 密钥)*
  • StoredKey = H(HMAC(PBKDF2(password), "Client Key"))(同上"Client Key"

要进行身份验证:

  1. 客户端发送用户名和随机数
  2. 服务器将自己的随机 nonce 附加到客户端,并回复用户的 nonce、salt 和迭代计数
  3. 客户端计算以下内容:
    1. ClientKey = HMAC(PBKDF2(password), "Client Key")
    2. StoredKey = H(ClientKey)
    3. ClientSignature = HMAC(StoredKey, AuthMessage)AuthMessage所有先前交换的消息和随机数的连接在哪里,用逗号分隔)
    4. ClientProof = ClientKey XOR ClientSignature
  4. 客户端发送随机数和ClientProof服务器
  5. 服务器计算以下内容:
    1. ClientSignature = HMAC(StoredKey, AuthMessage)
    2. ClientKey = ClientProof XOR ClientSignature
    3. ServerSignature = HMAC(ServerKey, AuthMessage)
  6. 服务器验证H(ClientKey) == StoredKey,证明客户端知道密码(或至少ClientKey
  7. 服务器回复ServerSignature
  8. 客户端计算ServerSignature并将其与服务器返回的值进行比较,验证服务器是否知道ServerKey

这是相当简化的,因为它排除了一些东西,如哈希选择、编码、消息格式和通道绑定,但它应该很好地了解它是如何工作的。

* PBKDF2 的所有用途显然也包括盐和迭代计数,SCRAM 设置dkLen为所选哈希的输出长度

RFC指出以下优点:

o 身份验证数据库中存储的身份验证信息本身不足以模拟客户端。如果数据库被盗,信息会被加盐以防止预先存储的字典攻击。

o 服务器无法将客户端模拟到其他服务器(服务器授权的代理除外)。

o 该机制允许使用服务器授权的代理,而不要求该代理对后端服务器具有超级用户权限。

o 支持相互认证,但只有客户端被命名(即服务器没有名字)。

您的问题仅考虑连接安全性,而 SCRAM 也考虑了客户端凭据的安全性。它最明显的优势是它可以防止服务器操作员获取用户凭据,因为它们以加盐和散列格式传输,而在简单的 TLS 连接上它以明文传输。

一个常见的安全漏洞是错误地记录明文密码:

即使你有传输安全,在你的服务器上没有明文密码也是有好处的。传输安全可防止攻击者。如果你想保护自己免受自己的错误,你需要客户端散列。