当表单提交失败时,密码字段被空白,为什么会这样?

信息安全 密码
2021-08-14 01:14:46

我最近问了一个关于为可用性目的在 UX中将密码字段置空的问题,但似乎所有网站都出于安全原因使用这种方法。为什么发回用户输入的同一个通行证是不安全的?

3个回答

好问题。受益于查看一些答案并自己思考这一点,我实际上并没有看到从返回给用户的部分表单中清除密码有任何重大的安全优势,但肯定存在一些值得考虑的风险。

从安全架构的角度来看(正如@Roryalsop 已经提到的那样),您通常希望密码只在一个方向流动。从用户到应用,永不回头。这适用于所有层,并且从安全的角度来看,这种单向系统提供了好处。对此规则有一个例外可能是一个好主意,也可能不是一个好主意。但这就是为什么你的问题很有趣。这种情况值得例外吗?

让我们看看一些攻击向量,看看是否将密码设为空是否可以防止其中任何一种攻击:

  • 嗅探流量- 如果攻击者能够拦截用户和服务器之间的通信,它可以嗅探用户首先发送的密码。我认为在响应中清空它没有任何好处
  • 服务器或客户端上的恶意软件- 相同。它可以拦截初始密码。
  • 缓存数据- @SachinKumar 已经简要提到了这一点,但值得扩展。如果服务器在响应中返回密码,则它可能最终被缓存在某个地方(服务器 memcached、路径上的代理服务器、客户端的浏览器历史记录等)。客户端请求永远不会被缓存。服务器响应是!这可能是我看到的最大风险。可以通过使用 SSL 从等式中消除代理,如果服务器使用正确的缓存头并正确设置输入字段,这也可以减轻浏览器缓存。也就是说,该值仍然有可能被缓存在某个地方,即使是偶然的,这可能是不可取的。

但是,将密码归零很容易,不应该过多地损害用户体验,并且从安全的角度来看可以让事情变得更清洁。我仍然建议你继续这样做。

如果您担心用户体验,请尝试遵循您已经在 UX 上获得的建议- 在客户端执行额外的验证,以便用户获得早期反馈。不要替换服务器上的验证。这是最终最重要的验证。但是对于用户反馈,客户端验证可以创造奇迹来改善用户体验,并且您不必冒密码被缓存的轻微风险(或通过例外更改您的安全架构)。

为什么发回用户输入的同一个通行证是不安全的?

因为如果您随后在发布的后台页面上查看源代码,密码将以纯文本形式显示。这违背了密码只能是一种方式的原则——即密码可以输入但不能输出。例如,当在数据库中存储密码时,应该对这些密码进行散列而不是加密,以防止攻击者设法查看数据时提取密码。处处遵循这一原则将导致更安全的系统。

在这种情况下,它可以防止“肩膀冲浪”,并且可以防止它被浏览器缓存,然后再查看。

有一个好的 UI 并遵循这个原则是可能的。例如,系统可以将散列和加盐的密码存储在服务器端会话状态中,然后在回发时表单只显示其他字段。一旦通过验证,将使用会话状态中的密码,而不是表单提供的密码。当然,如果用户不继续注册过程,则必须注意使会话无效,以便此密码不会覆盖该浏览器的下一位访问者设置的密码。否则可能会发生会话固定攻击。

这里有2个关键点:

  1. 如果您有将密码发回给用户的机制,那么您就可以为攻击者提供获取该密码的方法。
  2. 如果您可以将密码发送给用户,则意味着您没有将其存储为散列,而是使用明文或可逆加密。但是正如@yoav 指出的那样,在特定情况下,IT 还没有被加密,所以这一点在这里无关紧要。

这两者都有风险。

这就是为什么大多数网站都有密码提醒和重置机制,所以他们不需要将密码发回给你。他们可能会向您发送一次性密码作为重置密码,然后您必须更改该密码。

有些人会通过带外路由发送您的密码,但随着风险的不断增加,这种情况变得越来越少。

(当然密码重置机制的安全性是另一回事)