网络应用程序安全指南/密码安全
大多数网络应用程序使用用户名/密码组合来管理访问。
为了保持基于密码的登录机制的安全
- 不要存储明文密码,只存储哈希值
- 使用 Argon2、scrypt、bcrypt 或其他专门为安全密码“存储”而设计的安全哈希算法。[1][2]
- 使用每个用户的盐
- 使用强化(即多迭代哈希来减缓暴力破解尝试)
- 限制每个 IP 的登录尝试次数(而不是每个用户帐户)
- 执行合理但不过于严格的密码策略
- 如果实现了密码重置流程,请确保它具有足够的安全性。诸如“母亲的娘家姓”之类的问题通常可以被攻击者猜测,不足以保护。
原理
用户在多个服务中重复使用密码。如果攻击者获得了对一台服务器的访问权限,并且可以获得密码列表,他可能可以使用此密码攻击其他服务。因此,只能存储密码哈希值。大多数语言中易于使用安全哈希算法,并确保无法轻易恢复原始密码,并且不会错误地接受错误密码。
在密码哈希值中添加盐可以防止使用彩虹表,并显着减缓暴力破解尝试。强化会减缓对被盗哈希值的离线暴力破解攻击以及在速率限制失败的情况下在线暴力破解攻击。但是,它会增加服务器上的 CPU 负载,如果未通过登录尝试限制来阻止,则会打开 DDoS 攻击的途径。良好的强化可以将离线暴力破解攻击的速度降低 10000 倍或更多。
限制登录尝试次数对于防止在线暴力破解攻击和通过密码强化过程的 CPU 使用率进行的拒绝服务攻击是必要的。如果没有限制,攻击者可以直接尝试大量密码来攻击服务器。假设每秒 100 次尝试(对于正常的 Web 服务器来说是合理的),没有显著的强化,并且攻击者使用多个线程,这将导致在一个月内尝试 259,200,000 个密码!
不执行任何密码策略会导致太多用户选择“123456”、“qwerty”或“password”作为他们的密码,使系统容易受到攻击。执行过于严格的密码策略将迫使用户保存密码或将其写下来,通常会让他们感到厌烦并促使他们对所有服务重复使用相同的密码。此外,使用不符合策略的安全密码的用户可能被迫使用更难记忆但未必安全的密码。由 5 个串联的随机选择的 (!) 小写字典词组成的密码比由大小写字母、数字和标点符号组成的 8 字符密码安全得多。如果您没有获得要实施的密码策略,而是必须自己设计密码策略,请牢记这一点。
如果攻击者无法获取密码,他可能会尝试重置密码。通常,密码重置问题的答案很容易找到或猜到。仅靠问题不足以保护。例如,考虑将问题与电子邮件验证一起使用,发送一个新的临时密码。