让我们谈谈密码安全性。如何设计一个系统来阻止任何有数据库访问权限的人(如数据库管理员或软件工程师)登录帐户?具体来说,如果一个项目是开源的,其中代码和加密方法是公共知识,那么如何保护每一层以防止欺骗。虽然密码可能在密码上是安全的,但任何人都能不只是关闭开源回购,修改身份验证方法,并将加密值提交登录吗?请允许我设计一个系统,在可能的情况下,通常建议使用该系统。
我们都知道,明文密码永远不应该存储在数据库中。相反,应该存储使用慢速单向加密的加密密码。可以采取其他步骤,但我们现在将从这个场景开始简单介绍。数据库管理员永远不知道什么是纯文本密码。他们只知道用户密码的加密形式。当用户提交登录凭据时,他们可以执行以下选项之一:
- 提交用户名和纯文本密码,然后服务器对其进行加密,并在数据库中检查用户名:encrypted_password keypair。这是一个糟糕的实现,因为未加密的密码通过网络传输,并且可能存储在各种日志中
- 提交用户名和客户端生成的加密密码,然后服务器检查数据库中的用户名:encrypted_password keypair。这样做更好,因为未加密的密码永远不会在网络上传输。然而,这在下面提出了一个不同的问题,这是本文用来理解的根本问题
如果数据库存储用户名和加密密码,那么可以采取哪些额外的安全措施来防止有人修改开源软件以提交用户已知的加密密码重述;如果恶意数据库管理员或软件工程师窥探数据库,获取某人的加密密码,修改fork以始终提交该加密密码(因此永远不会执行客户端哈希),可以使用什么额外的安全层来防止这种形式的攻击?恶意攻击者不知道明文密码,但他们很容易登录到帐户。
显而易见的答案是:
- 根据需要将数据库读取权限限制在少数员工
- 存储在不同数据库中的用户唯一Salt密码,并将访问权限限制在更少的人。这种盐析必须在服务器端进行
- 使用在数据库外部定义的通用全局胡椒,应用程序使用该数据库再次加密所有内容。这种穿插必须在服务器端进行
- 使用不同的身份验证管理器,如LDAP或Active Directory
当使用方法1、2和3时,我们可以开发一个相当严格的密码安全层。那些知道全局胡椒但无法访问数据库的人将无法获得最终的加密密码,因此他们无法执行任何操作,因为他们没有salt and peppered加密密码。但是数据库管理员呢?他们有完全加密的密码和盐,他们只需要胡椒粉,对吗?假设pepper被正确部署,它可能会作为环境变量驻留在服务器主机上,或者驻留在一个配置文件中,该文件没有提交或存储在任何形式的数据库(传统数据库、git等)中。太棒了,因此,我们至少确定了一种防止欺骗的方法,即将数据库和部署访问权限限制在两个不同的个人或部门,从而要求合谋获取执行攻击所需的所有信息
但是,当只有一名员工时,您如何使用这种级别的安全和信任该员工将是数据库管理员、软件开发人员、部署工程等。我们如何向用户灌输信任,并向社区表明,开发人员无法伪造他们的登录信息依赖于LDAP或AD等服务的项目需要额外的配置,了解这些产品的工作方式,而且很多时候对于您正在开发的应用程序来说并不是必需的。
慢速单向加密
单向函数称为hash
提交用户名和纯文本密码。。这是一个糟糕的实现,因为未加密的密码是通过网络传输的
不是。解决方案是使用https(一般为TLS)。没有理由不使用/强制使用https。如果在客户端生成任何内容,则生成的值将变为密码。没有理由重新发明轮子,使其变得比必要的更复杂。
但是数据库管理员呢?
数据库管理员通常比模拟用户拥有更大的权力。如果具有应用程序级凭据,管理员可以读取或修改数据库中的数据,而无需知道用户凭据。恶意管理对任何公司来说都是一场灾难。大多数严肃的数据库都将角色分开(应用程序可以访问数据,管理员可以管理数据库但看不到数据,备份团队管理备份),但主要在小公司中分离角色并不容易,因为在小公司,同一团队管理数据库并配置应用程序部署。
阻止某人修改开源软件以提交用户已知的加密密码?
OSS通常都经过了很好的审查,我更关心的是定制实现做得不对。但事实上,没有什么能阻止任何服务提供商在客户端不知情的情况下以明文形式存储密码。因此,这取决于客户端/用户是否在多个服务中重复使用他们的密码。
当谈到身份验证时,我认为MFA(多因素身份验证)或使用众所周知的可信第三方IdP是当今的最佳实践。尽管如此,它不会保护你免受邪恶的管理员或开发人员的攻击。
如何。。。向社区展示,开发人员不能伪造他们的登录?
如果它在服务器上运行,则无法提供任何保证。使用第三方众所周知的IdP(有很多免费或商业服务),用户至少可以信任开发人员/管理员无法访问用户凭据。