密码加密,将密码存储在会话中。

19

我需要存储密码并再次使用它,但我认为这样做并不安全。

场景:

我想创建一个 Web 邮件程序,用户使用用户名和密码登录后可以查看他们的电子邮件。该工具不打算将密码存储在数据库中。但是在 PHP 中,我们需要在用户导航到每个页面时连接到邮件服务器。因此,需要用户名和密码来连接邮件服务器。如何以最安全的方式完成此操作?


请澄清一下,您正在创建一组PHP网页,这些网页将通过浏览器访问,是吗?而且这些页面将提供对某个其他邮件服务器的访问,需要输入用户名和密码,是吗?您是否需要存储用户输入的单个用户名/密码,并将其与其会话相关联?提供更多细节可以增加获得有用答案的可能性。 - David Schwartz
我猜问题是,当用户提供登录信息并连接到邮件服务器后,您是否可以缓存邮件会话? - Jared Farrish
Jared,我相信我们无法使用PHP缓存与POP/IMAP服务器的连接。因此,下一步是如何在其他页面上建立连接,而无需在用户导航到每个页面时询问登录详细信息。 - Kiran
看起来我理解错了。你基本上只是想将某人提供的用户名和密码转发到邮件服务器以登录您的站点?那么,为什么不将其保留在会话中缓存呢?当然,拥有访问计算机权限的人可以读取会话存储,但您无法保护这种数据(加密不会有任何作用)。 - Damon
1
你可以随时查看SquirrelMail是如何做的 - Jared Farrish
显示剩余4条评论
1个回答

25

因为不想存储密码,但又不希望多次输入密码,我唯一看到的解决方案是:

  • 使用足够长度的随机密钥(例如AES)对密码进行加密。
  • 将加密后的密码和用户名存储在会话中。
  • 最好也加密用户名和邮件服务器,以防万一。这并不会伤害任何人,并且一个攻击者没有已知的用户名。
  • 将加密密钥存储在cookie中。

虽然不完美,但应该可以很好地运作,并且可能是你可以得到的最好的权衡。

每次请求时,用户的浏览器将发送cookie,PHP脚本可以使用cookie解密存储在会话中的数据并对IMAP / POP服务器发出请求。

入侵您的服务器并获得对会话存储的访问权限的人将能够窃取加密密码,但如果您的随机密钥足够长且具有良好的随机质量,则这是相当无用的。

关键是,您只能使用您不知道的秘密来确保某些东西真正安全。如果您拥有解密服务器上某些信息(在本例中为IMAP密码)所需的信息,例如在会话存储中,每个入侵您的服务器的人都可以做到同样的事情。无论您的加密有多强,都没有任何区别。
确保秘密保持秘密的唯一方法是使用您不知道的东西来进行加密,只有用户(或在本例中为用户的浏览器)知道。

这导致了无法解决的问题:在某个时刻,您显然必须知道,至少有几分之一秒。那是网络服务器接收cookie并退出PHP脚本之间的时间。理论上,如果某个具有root访问权限的人在那段时间内读取进程内存,他也会知道秘密。但遗憾的是,这是您真正无法防止的事情。
只要不将信息存储在任何地方(即使不在会话中),它就应该相当安全。

当然,这一切都假定您的网站至少登录页面(最好是所有页面)通过https://提供,并且使用TLS / SSL与邮件服务器通信。否则,您将面对更为轻松的攻击。

1
很好的答案,但是存储应该是相反的。加密密钥应该存储在会话中,而加密后的用户名和密码应该存储在cookie中。如果有人获得了会话存储,他们将拥有许多密钥,但没有任何用户名和密码可以尝试暴力破解。 - user3332631
@user3332631:这通常是正确的,而且消除每一个可能的泄漏也绝对没有坏处。但实际上,如果您选择非平凡的密钥长度,例如128位,则暴力破解是不切实际的。即使对于像美国间谍机构这样的大型机构来说,由于热力学限制(无论CPU功率如何),他们也几乎不可能暴力破解单个128位密钥。如果第三次世界大战的结果取决于它,他们可能只能做一个密钥,但对于您服务器上的任何密钥(更不用说其中许多密钥)都是不切实际的。您并不重要到需要暴力破解128位密钥。 - Damon
只是为了澄清我所说的“不切实际”和“不重要”,在128位计数(密钥设置和16轮AES还有另外一个故事!)中,假设有一台完美的CPU,将消耗美国总铀产量的几年电能。这意味着你必须拥有一个非常重要的秘密,才会发生这种情况(然后他们宁愿对你使用扳手攻击)。这不是你在某个随机服务器上执行的例行程序,只是为了读取某人不重要的电子邮件。 - Damon
好的,那么暴力破解已经不是一个选择。只想提一下其他系统这样做的方式,将密钥存储在会话中,密码存储在cookie中。参考:http://squirrelmail.org/docs/devel-code/squirrelmail/_functions---strings.php.html#functionOneTimePadCreate不知道除了避免会话存储的暴力破解之外是否还有其他原因。也许这只是取决于你的舒适度。 - user3332631
@user3332631:基本访问认证是为了让您访问特定页面,它对OP想要做的事情没有帮助(至少我无法想象它如何有所帮助)。问题陈述为如何存储用户名+密码而不将其存储在数据库中并保持安全。唯一保持安全的方法是如果您不知道密码或者不知道加密密钥。最安全的方法是根本不将其发送到服务器。然而,服务器必须最终拥有密钥,因为它代表用户发出请求。 - Damon
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接