【问题标题】:How 'exposed' do you store a password in a session?您在会话中存储密码的“暴露程度”如何?
【发布时间】:2013-08-16 08:50:23
【问题描述】:

我正在使用 Python 和 Flask 创建一个网站,并且想知道一些对我来说相当重要的事情。

过去,作为未受过教育的程序员,我总是在会话中保存未加密的用户密码,以便可以根据要求重新验证用户名和密码。目前我正在制作我的第一个严肃网站,所以我也想做得更好。

我知道有一些方法可以嗅探会话变量,例如通过一种或另一种方式获取另一个人的会话 ID。我想知道最好以哪种形式存储密码,以便对有权访问会话数据的人隐藏它。

到目前为止我想到的选项:

  • 未加密:逻辑上最糟糕的选择。
  • 散列:例如,将sha256(password) 保存到会话中。这也不是一个好的选择,因为破解者可以使用字典表来检索未加密的密码。
  • Salted & Hashed:例如,将sha256(password+hash) 保存到会话中。这是三个选项中最安全的一个,但它将是数据库条目的副本,这对我来说似乎不是一个好主意。破解者可以将自己的密码与自己的哈希值进行比较,并可能找出如何为整个数据库创建盐和哈希值。我不确定这是否是一个有效的问题,但我想 Stackoverflow 上知识渊博的用户能够告诉我。 ;)
  • Salted & Hashed,数据库保存递归散列字符串:从本质上讲,这似乎是一个不错的选择,但我读到递归散列密码总是一个坏主意。

那么,推荐哪一个?也许是我没想到的第五个?请注意,需要使用此变量来验证用户的凭据,因此我们不能只使用不同的 salt 对其进行哈希处理。

【问题讨论】:

  • 您的问题可能更适合我们的姊妹网站security.stackexchange.com,因为它更多的是关于一般的 Web 应用程序安全实践,而不是特定的编程问题。但是,FWIW,我在下面提供了我的答案。

标签: security session hash passwords session-variables


【解决方案1】:

为什么需要在会话中存储用户的密码?我看不出有什么特别需要它,而且它只是无缘无故地造成潜在的安全风险。

相反,只存储用户名,可能还有一个表明用户已通过身份验证的标志。当然,您应该在用户注销时清除该标志(和/或只是擦除整个会话数据),以便以某种方式访问​​旧会话 cookie 的攻击者无法在注销后恢复会话。

您可能还想在会话中存储“上次访问”时间戳,以便让旧的过时会话超时。或者您可以依赖会话框架的内置会话过期行为,但拥有完全由您的应用直接控制的备份机制仍然是一个好主意。

附言。显然,无论您做什么,请确保您的会话标识符是使用加密安全的随机数生成器(例如 Crypto.Random.random)生成的,并且它们足够长以至于无法猜测(至少 64 位 = 16 个十六进制数字,虽然 128 位更好)。如果出于某种原因您不能这样做,另一种方法是自己生成这样一个随机令牌,将其同时存储在会话和 cookie 中,然后在使用任何实际会话数据之前验证会话和 cookie 令牌是否匹配。

【讨论】:

  • 这听起来不错。不过,我的问题也与常规 cookie 有关——出于某些原因,保存密码以进行身份​​验证可能很有用。例如,如果用户将其凭据保存在一台计算机上的 cookie 中,然后使用另一台计算机更改他们的密码,则保存的 cookie 应该无效。
  • 如果您希望能够使给定用户的 所有 会话(或除一个会话之外的所有会话)无效,我同意这是一个有用的功能,一种方法可以做到这一点将在会话中存储“最后登录”时间戳,在用户数据库中存储“最后登录out”时间戳。然后只需检查每个请求,确保会话中的时间戳晚于数据库中的时间戳。要强制用户注销,只需更新数据库中的时间戳(以及您想要保留的任何会话中的可选时间戳)。
  • 附言。如果您需要在客户端存储这些值(例如在 cookie 中),请在其中包含 MAC 以防止它们被篡改。不要忘记在 MAC 输入中包含用户名。
猜你喜欢
  • 2012-01-22
  • 1970-01-01
  • 1970-01-01
  • 2012-03-19
  • 1970-01-01
  • 1970-01-01
  • 2020-07-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多