Is it safe to briefly have a user's password in memory in plain text?
考虑到你通常登陆多大的网站,公司服务器在某个时间点以明文形式将你的密码保存在内存中。这是真的吗?安全吗?
这类似于大多数大型网站的登录方式:
在浏览器中输入密码
使用非对称加密公钥在浏览器中加密密码
向网站发送密码
使用非对称加密私钥解密密码
使用单向哈希算法(和salt)哈希密码
将哈希密码与数据库中的哈希密码进行比较
如果哈希匹配,则成功登录。否则,登录失败。
在步骤4和5之间查看
使用非对称加密私钥解密密码
4.5。简单地使用一些带有纯文本密码的服务器端变量
使用单向哈希算法(和salt)哈希密码
这意味着,尽管整个哈希方案是为了防止攻击者访问密码,即使服务器受到攻击,熟练的黑客也可以做到这一点。
有什么我错过的吗?更重要的是,还有更安全的选择吗?
- 需要更多帮助吗?如果是这样,我会更新我的答案。
- @Silverlightfox如果您不介意添加更多信息,我绝对会感激的。我真正关注的领域是安全,即使是在一台受损的机器上。
- 当然,完成了。如果您还需要什么,请告诉我。
- @环境主义者阿法克。安全性是防止攻击者破坏服务器。如果他们在里面,他们读你的密码只是时间问题。你不能保护记忆。您所能做的就是正确地设置用户权限,并尝试及时检测入侵者。注意,这只是我的外行印象,可能其他人更了解这一点。
是的,它是"安全的",因为内存中的内容都在服务器的内存中,不应该能够从外部读取。
安全是引用的,因为一切都是相对的,风险水平取决于你感知到的威胁模型——也就是说,你试图防御什么威胁?
广为宣传的HeartBleed错误允许攻击者以64kb的块从服务器内存中检索项目。然而,这里的策略是建立一个漏洞管理(修补过程),而不是围绕这些类型的问题进行编码。
关于加密密码-这是你应该依靠https而不是用javascript在客户机上加密的东西。当它们到达您的服务器存储并使用慢速算法(如bcrypt、scrypt或pbkdf2)以哈希格式进行比较时。还可以使用标记有"仅安全"和"仅HTTP"标志的cookie,实施HSTS策略,并且应该能够很好地进行密码存储和传输。
这里是CERT关于处理内存中敏感数据的建议。
与您的问题最相关的部分是:
- 禁用内存转储。
- 不要在程序中存储超过使用时间的敏感数据。
- 不要以明文形式(磁盘或内存)存储敏感数据。
- 如果必须存储敏感数据,请首先对其进行加密。
- 安全地从磁盘和内存中删除敏感数据。
This means that while the whole hashing scheme is to prevent an
attacker from gaining access to passwords EVEN IF the server is
compromised, a skilled hacker could get at it anyway.
号
记住,拥有一个安全的系统不仅意味着你需要有安全的编码实践和安全的基础设施。这是因为你永远不能拥有100%的安全性。这将丢失的一个难题是任何形式的入侵检测/预防(ID/IP)。这种观点认为系统在某个时刻会受到威胁,因此,与其试图阻止每种可能的攻击类型,不如检测它,允许您立即采取适当的行动。如果攻击者设法破坏了您的系统,并在登录过程中开始获取凭据,这将覆盖您。
- 我的观点是安全,即使服务器已经被破坏。如果这些公司期望完美的服务器安全性,他们就不会费心散列密码了。在最坏的情况下,攻击者可以对服务器进行根访问,这样做的目的是为了显示数据,但要确保密码的安全。如果密码在某个时刻以纯文本形式存储,即使只是在内存中,情况就不再是这样了。
- 这里的区别在于,如果一个包含密码的数据库表被攻击者窃取,那么他们就可以一次性完成整个任务。如果你已经正确的加了盐和散列,那么这不是一个大问题,因为有时间让用户更改他们的密码。但是,当您的服务器受到攻击时,攻击者只能在使用时获取每个密码。通过在登录处理程序的顶部添加一些代码,他们可以很容易地做到这一点,而不是向他们发送用户名和密码。最终的结果是,这对他们来说是一个慢得多的过程。
- 他们正在制造噪音,他们需要在你的系统上保持活跃以继续攻击。在这两种情况下,您都应该依靠检测和监视来控制漏洞。如果您的系统上有敏感信息,您需要ID,这样您就知道您的系统已被破坏,并且该代码已被添加以提取密码。有了良好的监控和响应攻击的人,您就可以阻止攻击者的成功方法并关闭它们。总之,在处理密码时在内存中包含密码不会带来与不安全存储相同的风险。
- 说得好。最后一点,您认为Mike的想法是散列密码客户端,然后用更强大的东西散列散列服务器端,比如Bcrypt?
- 这完全取决于它是否对您的系统"值得"。所以,这里您的最终目标是保护用户的密码,如果他们在其他系统上使用相同的密码,即使您的系统被破坏?添加代码会增加复杂性。复杂性往往会降低安全性。如果您对客户端进行了哈希处理,则需要添加一个salt,因为您不知道哪个用户正在登录,所以这必须是一个系统范围的salt(称为pepper)。知道这存在,攻击者可以为您的哈希算法预先计算彩虹表。
- 因此,如果他们破坏了您的系统,他们只需通过彩虹表运行客户端散列密码,然后他们就有了密码。实际上,在攻击期间登录的用户的所有密码。因此,在您自己的系统中添加了大量的复杂性和代码,但没有什么好处——这只会使攻击者从您的系统中获取一个可能在用户登录的另一个系统上工作的密码稍微更容易一些。
- 你这里的一些新观点似乎与问题中的行为相反。假设将数据作为程序变量来处理被限定为"存储在内存中"(当然,这是存储变量的地方),那么不要将敏感数据存储在纯文本(磁盘或内存中)中,如果必须存储敏感数据,则首先对其进行加密,这意味着问题中描述的过程在受损机器上是不安全的。基本目标是防止攻击者被动(不更改代码,这是显而易见的)访问密码。你介意详细阐述一下吗?
- @我想说的存储将被定义为半永久性地存储它,例如在会话中。使用与存储不同,但是您可能仍然希望安全地删除变量。
- 最初的问题旨在从攻击者的角度解决安全问题,这往往是识别攻击的最佳角度。如果我想从实现当前最佳安全实践的服务收集密码,我可以从客户机或服务器收集密码。攻击大量的客户机是不现实的,在我们正确实现安全性的假设下,服务器端数据库将只包含盐散列。在这个过程中,唯一一个可以在服务器上以纯文本形式使用密码的步骤是…
- …在解密客户端发送的加密密码和哈希和salt之间进行比较,将其与存储在服务器端数据库中的salt哈希进行比较。此时(原始问题中的步骤4.5,如果您愿意的话),密码将存储在内存中。虽然解析内存相当困难,但如果现代安全体系结构中没有可攻击的部分(没有数学后门,没有服务器发送心跳数据块等),这将是最好的攻击。然后,我可能在后台运行一个从内存中读取的进程,这是我试图阻止的。
- @答:我理解问题所在——我仍然坚持这样做的解决方案:测试您的系统渗透性,并实施入侵检测,这样您就可以知道安全性是否被破坏。如果您试图控制的风险是您的用户密码可能已在其他站点上使用,则客户端上的哈希将阻止服务器端已知的密码。一旦知道用户名,您仍然需要客户端知道salt,以便正确哈希此用户。您需要为不存在的用户返回一致的哈希值,否则您很容易受到…
- @:用户枚举-因此,如果有人试图使用不存在的用户登录,那么每次都需要返回相同的salt,否则攻击者会知道它们不存在。因为攻击者可以得到这个salt,所以他们可以提前为每个用户生成彩虹表。然后,持久性攻击者可以将发送到系统的散列与它们的表进行比较,从而以这种方式获取密码。还要注意,如果攻击者可以读取内存,他们必须以某种方式控制您的机器。他们可以简单地更改为每个人提供的代码
- @并将散列的javascript更改为只发送纯文本的javascript。所以你增加了复杂度,但攻击者改变了策略,并设法立即绕过你的防御。我认为一个比只能读取内存的攻击者是一个假想的威胁——一个达到了那么远的攻击者将付出额外的努力来击败你所设置的任何散列保护。你的方法可能有效——在这种情况下继续——但你的工作只是为了保护重用密码的用户。甚至谷歌也错了…
- @尝试通过添加代码来提高安全性。
This is something like how most big sites have you log in
号
实际上,我从未见过任何站点对客户端的密码进行加密。在客户机上进行加密,然后在服务器上对其进行解密,什么也得不到。这就是SSL证书的用途。在我的生活中,几乎所有我见过的站点都只需将密码以纯文本的形式发送到服务器,然后在那里散列(我们希望如此)。
如果您试图阻止服务器在内存中使用纯文本密码,可以在客户端散列该密码,然后在服务器上散列该密码。请记住,当您在客户机上散列密码时,散列实际上就是密码。
- 请记住,当您在客户机上散列密码时,散列实际上就是密码。我意识到了。我的第一个想法是散列散列,我的第二个想法是有什么安全隐患…一旦你玩了"如果攻击者获得了服务器的控制权,你如何确保安全"的游戏,你最好先放一瓶阿司匹林。
- 我认为你必须首先考虑一下你真正想要阻止的是什么。如果你试图阻止黑客以某种方式破坏了服务器的访问权限,那么…您已经有更大的问题需要担心,如果您的服务器受到威胁,他们已经可以访问他们想要的任何帐户。如果是这样的话,还是用纯文本发送密码。对于哈希客户端,我能想到的唯一有用的事情是防止用户在多个地方使用相同的密码,因此如果您的服务器受到攻击,那么
- 不会泄漏你的用户的银行/贝宝/易趣网/脸谱网密码,因为大多数人使用相同的密码无处不在。当然,您不能为每个用户使用盐,因为用户还必须向这个盐提供哈希,而他们不知道。所以你的系统仍然容易受到彩虹表的攻击。
- 我的建议是尽可能地加强服务器。禁用所有不必要的服务,禁用telnet和ftp,使用公钥身份验证启用ssh,不允许通过任何协议(甚至http)的不安全连接登录,使用安全哈希(例如bcrypt)存储密码,您应该没事。您还可能希望研究应用程序的双因素身份验证。设置像Google认证器这样的东西相对容易。这将大大提高您的Web应用程序的安全性。
你说得对。但是远程攻击者必须更改代码。对于PHP,这很容易做到,但对于编译语言则不是这样。模糊的PHP代码也有一个地方来阻止攻击者的努力。
有时,当攻击者是开发人员之一时,即使是编译或模糊的代码也无法停止攻击。
请注意,当用于用户身份验证时,多方通信和零知识证明可能会以相同的方式被破坏。除了让攻击者很难侵入您的服务器之外,我认为没有其他选择。