为什么在版本控制中存储密码是个坏主意?

信息安全 账户安全 源代码 证书 威胁建模 内部威胁
2021-08-13 00:58:36

我的朋友刚刚问我:“当我们只将各种密码存储在我们的私有 Git 服务器中时,为什么直接将各种密码直接放在程序的源代码中那么糟糕?”

我给了他一个答案,强调了几点,但觉得它不够有条理,并认为创建一个规范问题可能是有意义的。

此外,在源代码中不存储密码与最小权限原则和其他信息安全基础有何关系?

4个回答

在我看来,不在 Git(或其他版本控制)中存储密码是一种约定我想人们可以决定不以各种结果强制执行它,但这就是为什么通常不赞成这样做:

  1. Git 让从源代码历史记录中删除密码变得很痛苦,这可能会让人们误以为密码已在当前版本中被删除。
  2. 通过将密码置于源代码控制中,您基本上决定与有权访问存储库的任何人共享密码,包括未来的用户。这使得在开发人员团队中建立角色变得复杂,这可能具有不同的权限。
  3. 源代码控制软件往往变得相当复杂,尤其是“一体化”系统。这意味着该系统最终可能会受到威胁,从而导致密码泄露。
  4. 其他开发人员可能不知道密码已存储并且可能会错误处理存储库 - 在源中拥有密钥意味着在共享代码时必须格外小心(即使在公司内部;这可能会产生对加密通道的需求)。

不能说与信息安全相关的每种模式都是好的,但在破坏它们之前,考虑您的威胁模型和攻击向量总是一个好主意。如果这个特定的密码被泄露,攻击者使用它来损害公司的难度有多大?

一、非安全原因:

密码更改工作流程

密码的变化独立于软件应用程序代码。如果 DBA 更改了数据库密码,那么开发人员必须更新代码、获取新的构建并发布到生产环境并尝试计时,这是否有意义?密码是运行时配置工件,而不是开发工件。它们应该通过配置文件、环境变量或您正在使用的任何配置范例注入。

授权范围

通常,版本控制系统提供授权控制,因此只有授权用户才能访问它。但是在存储库中,权限通常要么是读/写,要么是只读的,或者可能是 GitHub 提供的一些花里胡哨的东西。您不太可能找到让开发人员获取源代码而不是密码的安全约束。如果您可以克隆存储库,则可以克隆存储库。时期。在许多环境中,开发人员无法完全访问生产环境。有时他们对生产数据库具有只读访问权限,有时没有访问权限。如果开发人员通常可以访问,但您不希望所有实习生、新员工等都拥有访问权限,该怎么办?

环境

如果您有多个环境,例如开发环境、QA 环境、登台和生产环境,该怎么办?您会将他们所有的密码存储在版本控制中吗?应用程序如何知道使用哪一个?该应用程序需要有一种了解环境的方法,这最终将成为一个配置设置。如果可以将环境名称作为配置设置,则可以将数据库密码作为配置设置(连同连接字符串、用户名等)

历史

正如其他人所提到的,版本控制旨在保留历史记录。所以旧密码仍然可以检索,这可能不是最好的选择。

妥协

我们有多少次在新闻头条看到某些产品的源代码被泄露给全世界?源代码是版本控制中的任何内容。这可能是不将密码放入版本控制的首要原因!

然而...

也就是说,密码需要存储在某个地方以上问题所暗示的不一定是它们根本不应该存储在版本控制中,而是它们不应该存储在版本控制中的产品源代码存储库中。有一个单独的 repo 用于配置管理、操作等是非常合理的。关键是在安全凭证方面将操作与开发分开,不一定要完全避免版本控制。

此外,对于非生产环境,我已将外部系统的密码和 API 密钥作为默认值存储在产品源代码中的配置文件中。为什么?为了让开发人员在签出代码时更加轻松,他们只需构建并运行它,而不必去获取额外的配置文件。这些证书很少更改,不会导致任何商业机密。但我永远不会对生产机密这样做。

所以底线是......这取决于。

请务必记住,建议必须根据您的用例量身定制。例如,美国国家安全局(NSA)为保护他们未雨绸缪的所有零日漏洞而采取的安全保障措施,应该比为保护猫图片发布网站上的投票而采取的安全保障措施要严格得多。在一个极端情况下,我可以想到一个将密码/令牌/等保存在私有 git 存储库中的示例可能是合理的:

如果该存储库仅由一个人访问,并且应用程序不存储任何有价值的信息。

在这种情况下,去镇上!请记住@d33tah 在他的回答中所说的内容 - 从 git 存储库中清除内容可能非常困难(毕竟,重点是永远保留所有内容的历史)所以如果你决定在路上与更多人协作,但不希望他们获得对您所有系统的完全访问权限,那么您的手会有些头疼。

这就是它真正归结为的原因。您的代码存储库在某种程度上是“公共的”,即使只与协作者共享。仅仅因为您想要与某人协作并不意味着您想要让他们完全访问您的基础设施(当您将密码/令牌放入代码存储库时实际上会发生这种情况)。很容易想到“是的,但我信任与我合作的人!”,但这只是看待这个场景的错误方式,原因有很多:

  1. 在实际实践中,大部分数据泄漏始于内部参与者(合作者、员工)。根据一项研究,大约 43% 的数据泄露始于内部参与者。其中一半是故意的,一半是偶然的。
  2. 最后一点很重要,为什么这不仅仅是关于信任。大约 20% 的数据泄露是由内部人员意外造成的。我很聪明,知道自己不够聪明,无法始终把所有事情都做好。如果我公开我的存储库以便为一些有趣的集成工具腾出空间而忘记了我在其中有凭据怎么办?如果我有一个我忘记加密的备份硬盘驱动器并且它走出了我的办公室怎么办?如果我的其中一个密码被泄露并且有人用它来猜测我的 git 存储库(咳嗽gentoo github 存储库咳嗽)的帐户密码怎么办?可能会犯很多意外错误,这些错误可能会导致我的 git 存储库被暴露,如果发生这种情况并且我在那里有证件找到他们的人知道他们在看什么,我很可能会被灌醉。这听起来像是很多and,但现实情况是这就是违规发生的方式。
  3. 即使我信任某人,这并不意味着我必须让他们完全访问所有内容[插入关于权力如何腐败的俗气引述]。同样,将凭据放入 git 存储库意味着我可能会向所有合作者授予对所有基础架构的完全访问权限。总是有可能你并不像你想象的那样了解那个人,他们可能会决定做一些他们不应该做的事情。即使您个人认识并信任每个人,您的合作者之一,这并不意味着他们不会犯上述一些错误(或任何我没有提到的无尽选择)意外释放您的代码。

简而言之,良好的安全性在于具有分层防御。大多数黑客攻击的发生是因为黑客发现了一个领域的弱点,从而使他们能够利用另一个领域的弱点,从而导致其他地方,最终使他们获得丰厚的回报。为您的情况制定尽可能多的安全保障措施是确保整个事情安全的原因。这样,当备份硬盘从您的办公室走出来时,您意识到它没有加密,您不必问“这是一次有针对性的攻击吗?我现在是否必须更改我在各处拥有的每一个凭证,因为它们都在那个备份驱动器上的 git 存储库中?”。同样,根据您的情况,这可能不适用于您,但希望这有助于解释在什么情况下这可能很重要。

将机密(密码、证书、密钥)与源代码分开,可以根据不同的策略管理源和机密。就像,所有工程师都可以阅读源代码,只有直接负责生产服务器的人才能访问机密。

这使开发人员的生活更轻松,因为他们不受保护机密所需的严格安全策略的约束。可以使源代码控制策略对他们来说更加方便。