客户端随机数有什么用?

信息安全 密码学 验证 随机数
2021-08-31 04:09:18

在阅读了罗斯·安德森 (Ross Anderson) 的书《安全工程》( Security Engineering ) 的第一部分并澄清了 Wikipedia 上的一些主题之后,我想到了 Client Nonce (cnonce) 的概念。罗斯从未在他的书中提到它,我正在努力理解它在用户身份验证中的作用。

正常的 nonce 用于避免重放攻击,其中涉及使用过期响应来获得特权。服务器为客户端提供一个随机数(使用一次的数字),客户端被迫使用它来散列其响应,然后服务器使用它提供的随机数对它期望的响应进行散列,如果客户端的散列与客户端的散列匹配server 然后服务器可以验证请求是否有效且新鲜。这就是它所验证的一切;有效和新鲜

然而,我为客户 nonce 找到的解释不那么直截了当且值得怀疑。用于摘要访问身份验证的维基百科页面和 Stack Overflow 上的几个响应似乎表明使用客户端随机数来避免选择明文攻击。我对这个想法有几个问题:

  • 如果一个人可以嗅探和插入数据包,那么最大的漏洞是中间人攻击,无论是随机数还是随机数都无法克服,因此两者都毫无意义。
  • 假设攻击者不想进行中间人攻击并想恢复身份验证详细信息,那么 cnonce 如何提供额外的保护?如果攻击者拦截通信并用自己的 nonce 回复请求,那么客户端的响应将是 nonce、data 和 cnonce 的哈希以及未加密形式的 cnonce。现在攻击者可以访问随机数、随机数和散列。攻击者现在可以使用 nonce 和 cnonce 散列其彩虹表并找到匹配项。因此,cnonce 提供零附加保护。

那么,无名氏的目的是什么?

我假设方程式的某些部分我不理解,但我还没有找到关于那部分是什么的解释。

编辑一些答案表明客户可以提供一个随机数,它将用于相同的目的。然而,这打破了挑战-响应模型,这意味着什么?

4个回答

随机是协议中实体选择的唯一值,它用于保护该实体免受“重放”这一非常大的保护伞下的攻击。

例如,考虑一个基于密码的身份验证协议,如下所示:

  • 服务器向客户端发送“挑战”(假定为随机值c
  • 客户端应通过发送h(c || p)进行响应,其中h是安全散列函数(例如 SHA-256),p是用户密码,' || ' 表示连接
  • 服务器在自己的数据库中查找密码,重新计算预期的客户端响应,并查看它是否与客户端发送的内容匹配

密码是适合人类大脑的秘密值;因此,它们不能非常复杂,并且可以构建一个包含用户密码的大字典。我所说的“大”是指“可以在几周内用中等规模的集群枚举”。对于当前的讨论,我们认为攻击者将能够通过花费几周的计算来破解单个密码;这是我们想要达到的安全级别。

想象一个被动攻击者:攻击者窃听但不更改消息。他看到ch(c || p),因此他可以使用他的集群来枚举潜在的密码,直到找到匹配项。这对他来说将是昂贵的。如果攻击者想要攻击两个密码,那么他必须做两次攻击者希望使用预先计算的表在两个攻击实例之间分摊一些成本(“彩虹表”只是一种具有优化存储的预计算表;但构建彩虹表仍然需要枚举完整的字典并对每个密码进行哈希处理)。然而,随机挑战打败了攻击者:因为每个实例都涉及一个新的挑战,所以即使使用相同的密码,每个会话的哈希函数输入也会不同。因此,攻击者无法构建有用的预计算表,尤其是彩虹表。

现在假设攻击者变得活跃。他不会简单地观察消息,而是会主动更改消息、删除一些消息、复制其他消息或插入自己的消息。攻击者现在可以拦截来自客户端的连接尝试。攻击者选择并发送他自己的挑战(c')并等待客户端响应(h(c' || p))。注意不联系真正的服务器;攻击者只是在客户端响应后立即突然断开连接,以模拟良性网络错误。在这个攻击模型中,攻击者做了很大的改进:他还有一个挑战c'和相应的响应,但挑战是攻击者选择的他认为合适的值。攻击者会做的是始终提供相同的挑战c'每次使用相同的挑战允许攻击者执行预计算:他可以构建使用该特殊“挑战”的预计算表(即彩虹表)。现在,攻击者可以攻击多个不同的密码,而不会产生每个密码的字典枚举成本。

客户端随机数避免了这个问题。协议变为:

  • 服务器发送一个随机挑战c
  • 客户选择一个随机数n(每次都应该不同)
  • 客户端发送n || h(c || n || p)
  • 服务器重新计算h(c || n || p)(使用其数据库中的p)并查看该值是否与客户端发送的值匹配

由于客户端在每个会话的哈希函数输入中包含一个新的随机值(“nonce”),因此哈希函数输入每次都会不同,即使攻击者可以选择挑战。这会破坏预先计算的(彩虹)表并恢复我们预期的安全级别。

唯一随机数的粗略模拟是用户名。同一系统中的两个不同用户将具有不同的名称。但是,用户在更改密码时将保留其姓名;并且两个不同的用户可能在两个不同的系统上具有相同的名称(例如,每个类 Unix 系统都有一个“root”用户)。所以用户名不是一个好的随机数(但它仍然比没有客户端随机数好)。

总而言之,客户端随机数是关于保护客户端免受重放攻击(“服务器”实际上是一个攻击者,他将向他希望攻击的每个客户端发送相同的挑战)。如果质询是通过包含强服务器身份验证(例如 SSL)的通道执行的,则不需要这样做。Password Authenticated Key Exchange是高级协议,可确保客户端和服务器之间基于密码的相互身份验证,而不需要一些先验信任(SSL 客户端验证 SSL 服务器证书时的“根证书”)并防止主动和被动攻击者(包括对单个密码的“两周集群”攻击,因此这比上面的协议(nonce 或 no nonce)严格地好)。

让我试着回答你的问题的实质:“假设攻击者不想进行中间人攻击并且想要恢复身份验证详细信息,那么 cnonce 如何提供额外的保护?”

通常,客户端不仅在请求中包含一个随机数,而且还会对整个请求进行签名,包括随机数这意味着即使攻击者截获了客户端和服务器之间的消息:

  1. 重放攻击不起作用(因为服务器正在跟踪客户端随机数)。
  2. 攻击者不能只使用新的客户端随机数生成新消息,因为它不知道如何适当地签署新消息(即它缺少客户端密钥或私钥)。

我认为一个好主意是阅读有关如何在Oauth之类的东西中使用 nonce 值的信息。简而言之,当使用 OAuth 的应用程序向支持 OAuth 的服务发出请求时,请求必须包含一堆字段,其中两个是时间戳和随机数。表单的目的很明显:它指示消息发送的时间范围,以便服务器可以更好地猜测消息是否过时。后者显然是一堆随机字符/字节。

当整个 OAuth 标头与消费者机密一起散列时,这两个字段都包括在内。然后将其附加到请求的签名(无论是查询参数还是 HTTP 标头)并发送到服务器。请求的实际正文经过哈希处理。

OAuth 服务器应该跟踪给定客户端的前一组 N 个 nonce 值,以确保它们不会被重用。鉴于消息的正文可以更改(基本上对哈希没有影响),重要的是要有其他会更改的内容(即随机数)以确保请求是唯一的。鉴于 HTTP 的开放/纯文本性质,这非常重要。

这是否有助于澄清其目的?(希望如此 :))。

根据RFC 2617cnoncenc参数可防止选择的明文攻击。这如何防止此类攻击?

如果 Eve 更改服务器发送给客户端的 nonce,Eve 获得了什么?Eve 不能从中生成h(password || nonce)h(password || fake_nonce)理论上它似乎服务器h(password || fake_nonce)无论如何都不应该接受,因为服务器应该知道它发出了什么随机数以及它没有发出什么随机数。