为什么像Git中的API密钥这样的秘密是个问题

2020-09-08 23:28:58

像git这样的版本控制系统(Vcs)中的秘密是当前的世界状态,尽管人们普遍认为这是一种糟糕的做法。一旦源代码进入git存储库,它就可以有机地传播到多个位置。这包括其中可能包含的任何秘密。但是,为什么git存储库中的秘密如此普遍呢?

这是关于源代码中的秘密的系列文章中的第二篇,将专门研究为什么git存储库中的秘密是一个瘟疫,为什么它如此危险,以及如何防止它。

经验丰富的开发人员可能会百思不得其解,想知道为什么有人会把秘密放在git存储库中。但事实是,git存储库内部的秘密是当前的世界状况。

在上一篇文章中,我们讨论了在访问和分发机密时,选择阻力最小的路径是如何常见的。Git充当项目的中心真理点,因此,至少从方便的角度来看,将秘密存储在私有的Git存储库中以便于分发和访问是有意义的。

但是,像这样储存秘密是在玩火,只需一个非常小的事件就会被烧毁。

除了故意将秘密存储在git中之外,当秘密管理不当时,很容易丢失它们的踪迹。机密可以硬编码到源代码中、存储为文本文件、在Slake上共享或隐藏在调试应用程序日志中。此外,开发人员可以在大型分布式团队中访问过多的秘密,同时面临更短的发布周期和越来越多的需要掌握的技术。

我们必须记住,源代码是非常容易泄露的。代码被复制和传输到任何地方。Git的设计方式允许,甚至提升,代码可以自由分发。

项目可以克隆到多台机器上,可以分叉成新的项目,可以分发给客户,也可以公之于众等等。每次在GIT上复制它时,该项目的整个历史也会被复制。

为什么将机密存储在公共存储库中是不好的,这将是显而易见的。它们对互联网上的每个人都是免费的,监控公共存储库非常容易,例如,GitHub有一个公共API来获取所有公共提交。

私人存储库不会将您的源代码公开发布到互联网上,但它也没有足够的保护措施来存储这些敏感信息。想象一下,如果有一个纯文本文件,里面有你所有的信用卡号码,你希望不会把它放进公司的git储存库,秘密也同样敏感。

组织中有权访问repo的每个人都可以访问其中的秘密(一个被泄露的帐户可以向攻击者提供访问大量秘密的权限)。

私有存储库可以公开,其中可能有隐藏在GIT历史中的秘密。

另一个重要的注意事项是,从GIT存储库中删除的代码实际上永远不会消失。

Git跟踪所做的所有更改。被删除的代码-或者更确切地说是正确的:过度提交的代码-仍然存在于GIT历史中。

有趣的是,从项目中删除的代码数量几乎相等。这意味着存储库中的代码比第一层要深得多,秘密可能隐藏在git历史的深处,隐藏在大量早已被遗忘的提交中。

备注:您在上面从HashiCorp Vault存储库看到的贡献图是一个项目历史的典型视图。你在项目贡献图中发现的规律性既令人惊讶又有趣(看看一些项目图,这似乎是自然规律)。

如果您在GitHub上搜索提交消息“已删除AWS密钥”,您将找到数千个结果。而这正好在公共储存库中。

仅在公共GitHub内,GitGuardian每天就检测到3000多个泄露的机密,这方面的例子有数千个,但下面是几个最近或值得注意的例子。

如果这似乎只是大公司需要担心的问题,那么事实并非如此。攻击者也在不断地通过密钥利用个人服务。在一个例子中,不良行为者扫描GitHub寻找AWS密钥,并利用它们挖掘加密货币,给开发人员留下了数千美元的债务。

[研究进行中]我们忘记在@GitHub上公开回购的代码中隐藏AWS密钥。在10分钟内,从两个不同的IP利用了密钥。

-鲍勃·迪亚琴科(@MayhemDayOne)2020年7月23日。

Git的一大优势是能够快速而清晰地看到所做的更改,并比较以前的代码状态和建议的代码状态。因此,人们普遍认为,如果机密在源代码中泄露,它们当然会在代码审查或拉请求中被检测到。

代码审查对于检测逻辑缺陷、维护良好的编码实践和保持高代码质量非常有用。但它们不足以保护侦察秘密。

这是因为审查通常只考虑当前状态和拟议状态之间的净差异。而不是分行的整个历史。通常在合并到主分支之前清理分支,添加临时代码然后删除,添加不必要的文件然后删除。但是现在,这些包含机密的高风险候选文件对审查者是不可见的(除非他们想要查看分支机构的整个历史)。

让我们来看看上面的例子。虽然这过于简单化了,但它讲述了一个熟悉的故事。

提交B将添加一个名为main.py的文件。创建了一个新分支来向Commit C中的main.py添加一个新函数,该特性使用API密钥,以节省测试时间,这是硬编码的。一旦功能正常工作,硬编码的API密钥就会被环境变量替换,文件就会被清除。最后,发出并接受拉请求,因为审查者查看了提交B和提交D之间的净差异,忽略了提交C。现在,未检测到的秘密被隐藏在项目的GIT历史中。

虽然这个场景非常基本,但是加上主服务器和开发分支之间的数百个提交和文件,您就可以看到在代码审查中遗漏机密是多么容易。

哇。开源的私人回购。不久之后,@GitGuardian通知我有一个旧的提交(我删除了一个Terraform tfstate文件)。谢谢各位好心人。你是我的后盾GG!https://t.co/2rpvjjuXcI🙏。

-Stefan Scherer(@stefscherer)2019年2月15日。

考虑到我们刚刚讨论的关于GIT内部秘密的所有内容,很明显,这是一个将持续存在的问题,我们不能用人工代码审查来解决这个问题。虽然自动化并不总是答案,检测秘密,特别是GIT内部的秘密,自动秘密检测是解决这个普遍存在的问题的一个明确的解决方案。

不幸的是,由于秘密的概率性质,在git中检测秘密并不像乍看起来那么容易。这使得很难区分真正的秘密和其他随机字符串,如数据库ID或其他散列。

然而,好消息是,GitGuardian已经为开发人员构建了强大的工具来探测Git中的秘密。一个包含本地GitHub和GitLab集成的很棒的仪表板,一个称为GG-Shield的CLI工具,或者您甚至可以使用GitGuardian API构建您自己的GIT秘密扫描器。

让我们快速回顾一下我们所经历的一切。Git存储库是非常常见的发现秘密的地方,它们仍然是秘密散布到多个位置的完美孵化器。Git会跟踪一个项目的历史,这可能会很深入,使得寻找秘密变得困难。由于git创建的工作流,在手动检查过程中遗漏任何机密是很常见的,应该在SDLC中引入自动机密检测。

好奇秘密侦测是如何工作的吗?在“源代码中的秘密”系列的下一集中,我们将深入探讨秘密探测的机制,包括为什么概率算法如此棘手,以及让它们发挥作用的秘诀。