Protecting user passwords in desktop applications (Rev 2)
我正在创建一个Twitter客户端,我正在评估保护用户登录信息的各种方法。
重要提示:我需要保护用户的数据不受其他应用程序的影响。例如,想象一下,如果机器人开始从用户桌面上运行的应用程序窃取Twitter密码或Hotmail或Gmail /雅虎/ PayPal会发生什么。
澄清:我之前问过这个问题,没有"重要"部分,但StackOverflow的用户界面在稍后的问答会话中没有帮助添加细节。
- 散列显然不起作用
- 以一种可逆的方式使人困惑就像试图隐藏在我的手指后面
- 纯文本的声音,很可能是乱七八糟的。
- 每次要求用户输入密码都会使应用程序变得烦人。
有什么想法吗?
这是第22条。要么你每次都让用户输入他的密码,要么你不安全地存储它(模糊,加密,随便什么)。
解决这个问题的方法是让更多的操作系统包含内置的密码管理器,比如OSX的钥匙链。这样,您只需将密码存储在钥匙链中,操作系统就可以保证它的安全,用户只需输入1个主密码。OS X上的许多应用程序(如Skype)都使用keychain来精确地描述您所描述的内容。
不过,既然你可能在使用Windows,我想说的就是进行一些模糊和加密。我认为你可能有点偏执于密码窃取机器人程序;如果你的应用程序没有一个大的用户库,有人将目标锁定并专门尝试窃取密码的可能性非常低。除此之外,他们还必须访问受害者的文件系统。如果是这样的话,他们可能有病毒/蠕虫,并且有更大的问题。
以纯文本形式存储并让用户知道。
这样,就不会有关于您已经达到的安全级别的误解。如果用户开始抱怨,可以考虑在你的网站上发布一个常量。如果用户不断抱怨,"隐藏"代码中的常量并告诉他们这是糟糕的安全性。
如果用户不能将坏人排除在外,那么事实上,他们所拥有的所有秘密数据都是邪恶博士所知道的。不管它是否加密。如果他们能把坏人拒之门外,为什么还要担心以纯文本形式存储密码呢?
当然,我可以在这里说我的屁股。有没有一项研究表明,以纯文本格式存储密码比以模糊的方式存储密码安全性更差?
我认为你错过了更大的画面:
如果桌面被破坏,你就是f*%ed!
要从程序中窃取密码,必须以管理员身份在系统上运行病毒。如果病毒已经做到了这一点,那么从你的程序中窃取密码就大大降低了它想要做的恶意事情的清单。
如果你正在创建一个Twitter客户端,那么使用他们的API
Twitter有非常好的文档,所以我建议你在创建客户之前阅读所有的文档。与这个问题相关的最重要的部分是,您不需要存储密码,而是存储OAuth令牌。您需要使用xauth阶段获取OAuth令牌,然后在必要时将其他TwitterAPI与此OAuth令牌一起使用。
xAuth provides a way for desktop and mobile applications to exchange a
username and password for an OAuth access token. Once the access token
is retrieved, xAuth-enabled developers should dispose of the login and
password corresponding to the user.
号
如果你能摆脱密码,就永远不会存储密码。
使用OAuth最糟糕的情况是第三方(黑帽黑客)可以访问该Twitter帐户,但不能访问密码。这将保护那些天真地为多个在线服务使用相同密码的用户。
使用某种类型的钥匙链
最后,我同意预先制定的解决方案,如osx的keychain,应该用于存储敏感的oauth信息,一台受损的机器只会显示当前未锁定的keychain的信息。这意味着在多用户系统中,只有登录的用户的钥匙链会变得脆弱。
其他损害限制
我可能错过了一些东西,比如谷歌的"最佳安全实践",开始阅读相关内容。
编辑(响应Finnw所需的一般案例解决方案)
如果没有用户输入,您需要访问在线服务。这意味着,通常情况下,您最多可以通过类似keychain的方式对身份验证凭证进行用户级访问控制。
我从来没有用过OSX钥匙链,所以现在我来谈谈SELinux。在SELinux中,您还可以确保这些身份验证凭据只提供给您的程序。如果我们继续使用操作系统级的东西,你也可以对从引导到加密的所有进程进行签名,确保没有其他程序可以模仿你的程序。这完全超出了典型的用户系统,并且考虑到这一级别的设置,您可以确信用户还不够幼稚,不足以被破坏,或者系统管理员也不够完善。在这个级别上,我们可以保护这些凭证。
假设我们在保护这些凭证方面做得不多,那么我们可以假设系统受到了破坏。此时,身份验证凭据将受到威胁,在本地端对这些凭据进行模糊/加密不会增加任何真正的安全性,也不会将其部分或全部存储在第三方服务器上。这很容易看到,因为在没有用户输入的情况下,您的程序需要自我引导以获取这些凭证。如果你的程序可以在没有输入的情况下完成它,那么任何反向设计了你的模糊/加密/服务器协议的人也可以。
此时这是损坏限制,不要将密码存储为身份验证凭据。使用OAuth、cookie会话、salted散列等,它们都只是表示在过去某个时刻您已经证明知道密码的令牌。在任何良好的系统中,这些令牌都可以在活动会话期间被撤销、过期和/或定期交换为新的令牌。
令牌(无论它是什么形式)也可以包含额外的非用户输入身份验证信息,这限制了您在其他地方使用它们的能力。例如,它可以封装您的主机名和/或IP地址。这使得在不同的计算机上使用凭据变得困难,因为模仿这些形式的凭据需要访问适当级别的网络基础设施。
我不明白…为什么加密不好?使用大密钥并将密钥存储在计算机密钥存储区(假定为Windows)。完成,完成。
经过进一步的思考,我想我找到了一条路。我将对我的应用程序桌面应用程序使用ASP.NET身份验证,在线存储它们的凭据,并让Internet Explorer的密码管理器为我处理此辅助对或凭据的本地缓存。
在第一次登录时,我只需要让他们通过类似Facebook API的表单进行身份验证。
使用钥匙链
Windows:使用CryptProtectData和CryptUnprotectData
Linux:使用gnome keyring和kde kwallet