通过不受保护的网络

时间:2017-10-03 01:44:22

标签: security hash salt nonce

我们正在设计一个API端点供客户端用于登录我们的服务。但是,我确实有一个问题,即在使用不受保护的网络时如何确保用户的密码受到保护。

在考虑了这个问题后,我们得出结论,我们可以修改我们的应用程序,在尝试登录之前请求一个nonce [每次登录尝试两个请求],然后在实际尝试发送之前对用户密码进行哈希处理通过网络。这解决了通过未受保护的网络发送用户密码的问题,作为副作用,我们可以检查现时并使其无效以防止任何后来的回复攻击。

然而,为了实现这一点,我没有找到任何方法可以在散列机制中使用Salt,就好像我们这样做,用户无法生成正确的散列,或者我们需要将Salt发送到用户。

我现在的想法如下:

  1. 应用程序要求一次性随机数[时间限制且随机生成]
  2. 应用程序哈希用户密码:[在进程中使用nonce]
  3. sha1(sha1([password]) + [nonce])

    1. 应用程序使用用户名,散列传递和散列的随机数发送身份验证请求以获取JWT令牌

    2. Web服务器根据提供的用户名验证nonce,然后验证提供的密码,如果成功,则将令牌发送给客户端,以便它可以使用其他端点。

    3. [resquestHashedPassword] == sha1([dbHashedPassword] + [nonce])

      1. 客户端使用提供的JWT继续使用服务的其他部分。
      2. 有没有办法可以保证用户的密码安全,同时能够在服务器端数据存储上使用散列盐?

        简而言之,这是一个关于如何使用" Nonce"作为身份验证请求的一部分," Salt"用于密码存储。

        *编辑1 *

        只是添加一些说明:

        1. 我知道我们可以使用HTTPS来加密传输中的数据(我们确实这样做),但HTTPS并不是不可穿透的。所以不是问题的实际答案。

        2. 我不想自己制作密码。我只是试图使用其他明确定义的解决方案,例如发送一个nonce并在密码旁边保留一个盐。但是,我无法找到两种方法。

        3. 我知道其他形式的攻击。但问题是关于用户密码的安全性而不是应用程序/服务安全性。如果我不需要以明文形式提供密码,为什么要通过网络发送密码呢?网络的安全性是问题与此无关的另一个问题。

        4. SHA1只是一个例子。

        5. *编辑2 *

          您如何看待使用用户的用户名(在我们的例子中,这是他们的电话号码,所以10位数,而其中4位实际上并不是随机的)作为盐?与随机盐相比,它确实具有非常小的熵,但这是我到目前为止找到的唯一方法,使我能够使用这两种方法。或者依靠HTTPS完美而放弃使用" Nonce"在哈希函数中呢?

3 个答案:

答案 0 :(得分:1)

首先,don't roll your own crypto

其次,您的系统仍然容易受到多种攻击,例如中间人,轻微攻击,网络钓鱼和会话劫持。如果黑客可以访问密码,他也可以访问哈希,并可以拦截它并自己使用它。他还将能够看到响应并窃取生成的会话密钥,然后冒充客户端。在所有情况下,他都能够查看您要保护的内容。

确保这一点的正确方法是使用SSL / TLS。建立安全隧道后,您可以依靠HTTPS提供的加密“明确地”传递凭据。

答案 1 :(得分:1)

(我假设“应用程序请求”和“API端点”意味着我们在单独的连接中查看消息,如HTTP,而不是使用自己的协议的单个双向连接。)

您提出的方案存在许多问题:

  1. 数据库中的弱哈希:您需要在服务器端存储sha1(password)才能使其正常工作,这还不够强大。你可以通过使用适当的带有盐的PBKDF存储一些东西并将nonce一起发送给客户端来解决这个问题。

  2. 电线上的密码不足。 SHA1非常快。 SHA1两次+盐不是更好。它将防止彩虹表攻击,但字典攻击 反对它仍然是微不足道的。

  3. 重播攻击仍有可能。您可以MITM此连接并将请求内容替换为您想要的任何内容,仅保留身份验证。您需要签署身份验证的哈希以及任何请求数据和相关标头。

  4. 您似乎没有以任何方式将您的请求与时间联系起来。攻击者可以设置一个代理,在发送响应之前保存nonce,响应并丢弃连接。如果您没有在请求中包含已签名的时间戳,则攻击者现在可以收集他们将来可以使用的身份验证哈希/请求。

  5. 建议:请参阅其他地方使用的身份验证,例如AWS v4

    至少,我会将您的计划更改为:

    1. 请求nounce + password salt,授予特定用户,从现在到5秒后的时间范围
    2. 发送请求,其中包括:
      • 当前时间
      • 用户名
      • 请求内容/标题
      • HMAC(k, list_of(nonce, time, username, request data))
      • 的签名
      • (其中kPBKDF(password, salt)
    3. 这仍然没有改变你的数据库现在是有效的明文密码数据库的事实,这是一个非常糟糕的主意。使用HTTPS上的明文密码进行身份验证并获取用于签署请求的临时令牌将是很多更好的解决方案。

答案 2 :(得分:1)

我确实有一个建议,如果你想要考虑某人能够在某个时间点穿透HTTPS,那么我会建议用户特定的对称密钥被配置一次并用于加密用户凭证+通过电汇发送之前的时间戳。

为了配置Fly DSKPP上的对称密钥,可以使用https://tools.ietf.org/html/rfc6063

DSKPP将需要用户在密钥配置阶段输入密码短语,密码短语可以预先生成并存储在服务器数据库中的用户,并可以通过其他渠道(如短信/电子邮件等)与用户安全地共享

但这需要做很多工作......你需要考虑成本中的风险因素。