「动手亲自在 GitHub 存储库中删掉的数据可能只是表面,实际上并未被删除成功,任何人都有机会访问」,这两天,来自开源安全软件公司 Truffle Security 研究人员的最新发现震惊整个开源圈。
要知道早在去年年初,GitHub 的用户量就突破了 1 亿,其代码库数量在 2022 年时已达到了 1.9 亿,由此成为了世界上最大的代码托管网站。如今这项调查研究发现,「删除」似乎形同虚设,这也使得不少网友开始怀疑,点击删除键究竟有什么用?倘若密码在数据中泄露,那是否任何人都可以随意查看?
更甚的是,研究人员称通过 GitHub 官方回复中可以得知,后者对此事是知情的,并且有意设计成这样的。而这究竟是怎么一回事?Truffle Security 研究人员在官方博客上发布了长文说清了来龙去脉。
定义 CFOR 漏洞
在研究人员看来,对于所有使用 GitHub 的组织来说,这是一个巨大的攻击媒介,为了更好地解释这个问题,他们引入了一个新术语:跨分叉对象引用(Cross Fork Object Reference,CFOR)。当一个存储库 fork 可以访问另一个 fork 中的敏感数据(包括来自私有和已删除 fork 中的数据)时,就会发生 CFOR 漏洞。
与不安全的直接对象引用有些类似,在 CFOR 中,用户提供提交(Commit)哈希值就可以直接访问提交数据,否则这些数据对他们不可见。
访问已删除的 Fork 数据
在使用 GitHub 时,想必不少人都有过这样的操作:
第一步,你见到了一个不错的项目,然后 Fork 了这个公共存储库;
第二步,你将代码提交到你的 Fork 存储库中;
第三步,你删除了你的 Fork 存储库。
想象一下,删除之后,你提交到 Fork 存储库的代码还能访问吗?
按理来说,应该不能,对吧?毕竟你在上面第三步时,你已经做了删除处理。
然而,现实却是,你不仅可以永久访问,而且它不受你的控制。
对此,研究人员分享了一段视频,你可以看到 fork 了一个存储库,向其提交数据,然后删除了 Fork 存储库,结果可以通过原始存储库访问“已删除”的提交数据。
过去,你可能会认为只要知道提交了哈希值,你就会受到保护。但如今事实并非如此,哈希值是可以被发现的。
时隔多久可以从已删除的 fork 中找到数据呢?
答案是:这种情况非常常见。研究人员也调查了一家大型 AI 公司的 3 个经常被 fork 的公共存储库,从中轻松地找到了 40 个来自已删除 fork 存储库的有效 API 密钥。
其推测正常用户的行为模式似乎是这样的:
Fork 存储库。
将 API 密钥硬编码到一个示例文件中。
<做自己的编码工作>
删除 fork 存储库。
但这样做,情况会变得更糟,还会造成反向效果。
访问已删除存储库的数据
考虑以下场景:
你在 GitHub 上有一个公开存储库。
某个用户 fork 了你的存储库。
在他们 fork 之后,你提交了新的数据或代码(用户从不将他们在 fork 存储库提交的代码修改与你的更新合并)。
然后你删除了自己的公共存储库。
那么,你在他们 fork 了你的存储库之后提交的代码还能访问吗?
是的。
GitHub 将存储库和 fork 存储库存储在一个存储库网络中,原始的“上游”存储库作为根节点。当一个已被 fork 的公共“上游”存储库被“删除”时,GitHub 会将根节点角色重新分配给一个下游 fork 存储库之一。然而,所有来自“上游”存储库的提交仍然存在,并且可以通过任何下游的 fork 存储库进行访问。
在下面的视频中,研究人员创建了一个 repo,对其进行 fork,然后展示了在原始存储库被删除后,仍可以通过 fork 存储库访问未与其同步的原始存储库的数据。
这种情况绝非个例。上周就发生了这样的事情:
研究员向一家大型科技公司提交了一个 P1 级别的漏洞报告,显示他们意外地提交了一名员工的 GitHub 账户的私钥,该账户拥有对其整个 GitHub 组织的访问权限。他们立即删除了该仓库,但由于它已经被分叉,研究员仍然可以通过 fork 访问包含敏感数据的 Commit,即使该 fork 存储库从未与原始的“上游”存储库同步。
这里的意义在于,只要有至少一个 fork 存储库,Commit 到公共存储库的任何代码可能会永远可访问。
这也引出下一个问题,情况变得更糟了。
访问私有存储库数据
回想一下,你在 GitHub 上开源新工具的常见工作流程:
你创建一个私有存储库,最终会将其公开。
创建该存储库的一个私有、内部版本(通过 fork)并提交额外的代码,这些代码的功能你不打算公开。
你将你的“上游”存储库设为公开,并保持你的 fork 存储库私有。
那么,请问你的私有功能和相关代码(步骤 2 中的)是否可以被公众查看?
答案同样是肯定的。在你创建工具的内部分支和开源工具期间提交的任何代码都可以在公共存储库中访问。
在将“上游”存储库公开后,对私有 fork 存储库所做的任何提交都不可查看。这是因为更改私有“上游”存储库的可见性会产生两个存储库网络——一个用于私有版本,一个用于公共版本。
在下面的视频中,研究员演示了组织如何在开源新工具的同时维护私有的内部 fork 存储库,然后展示了某人如何通过公共版本访问私有内部版本的 Commit 数据。
不幸的是,这种工作流程是用户和组织开发开源软件时最常用的方法之一。因此,机密数据和秘密可能会无意中暴露在组织的公共 GitHub 存储库中。
如何实际访问数据?
这就引出一个更为重要的话题,即如何访问到真实的数据。对此,研究人员表示,其实很简单,只要直接访问 Commit 就可以。
GitHub 存储库网络中的破坏性操作(如上面提到的三种情况)会从标准 GitHub UI 和正常 git 操作中删除对 commit 数据的引用。
不过,删除之后,这些数据仍然存在,而且可以访问(如果你知道提交哈希值的话)。这就是 CFOR 和 IDOR 漏洞之间的联系——如果知道 commit 哈希值,就可以直接访问不属于自己的数据。
commit hash 使用 SHA-1 值。
如果用户知道他们想看的某个 commit 的 SHA-1 commit hash 值,他们可以直接通过以下端点导航到该 commit:https://github.com///commit/。他们会看到一条黄色横幅,说明 “此 commit 不属于此存储库的任何分支,可能属于存储库之外的 fork”。
那么,从哪里获取这些哈希值?
commit hash 值可以通过 GitHub 的 UI 进行暴力破解,特别是因为 git 协议允许在引用 commit 时使用短 SHA-1 值。短 SHA-1 值是避免与其他 commit hash 值发生冲突时所需的最少字符数,绝对最小值为 4。所有 4 字符 SHA-1 值的密钥空间为 65,536 (16^4)。相对来说,暴力破解所有可能的值是比较容易的。
例如,看一下 TruffleHog 存储库中的此 commit:
要访问此 commit,用户通常会访问包含完整 SHA-1 提交哈希值的 URL:https://github.com/trufflesecurity/trufflehog/commit/07f01e8337c1073d2c45bb12d688170fcd44c637
但用户并不需要知道整个 32 个字符的 SHA-1 值,他们只需要正确猜出短 SHA-1 值,在本例中就是 07f01e。
https://github.com/trufflesecurity/trufflehog/commit/07f01e
但更有趣的是:GitHub 提供了一个公共事件 API 端点。你还可以在事件归档中查询 commit hash 值,该归档由第三方管理,保存了过去十年 GitHub 外部的所有 GitHub 事件,即使在版本库被删除后也是如此。
GitHub 政策
在有了上述发现之后,研究人员也在第一时间通过 GitHub 的 VDP 计划向他们提交了这些发现。以下是 GitHub 的回复。翻译过来的意思是:
感谢你的提交!这是一个故意的设计决策,并且正在按预期工作。我们将来可能会让此功能更加严格,但现在没有任何消息要宣布。
查阅文档后,研究人员发现,GitHub 在设计软件存储库时就考虑到了这一点。
对此,研究人员表示,“我们很欣赏 GitHub 对其架构的透明态度,并花时间清楚地记录了用户在上述情况下应预期发生的事情。”
然而,他们也同样认为:
「普通用户将私有和公共存储库的分离视为安全边界,并认为公共用户无法访问私有存储库中的任何数据,这是可以理解的。遗憾的是,正如我们在上文所述,事实并非总是如此。此外,删除行为意味着销毁数据。如上所述,删除存储库或 fork 并不意味着你的提交数据真的被删除了。」
影响
至此,研究人员表示,我们从中可以得到一些启示:
- 只要一个 fork 版本存在,该存储库网络中的任何提交(即:“上游 ”存储库或 “下游 ” fork 上的提交)都将永远存在。
这进一步证实了研究员的观点,即在 GitHub 公共存储库上安全修复泄漏密钥的唯一方法就是密钥轮转。
GitHub 的存储库架构必然存在这些设计缺陷,而不幸的是,绝大多数 GitHub 用户永远不会了解存储库网络的实际运作方式,因此安全性也会大打折扣。
随着秘密扫描的发展,我们希望扫描存储库网络中的所有 commit,我们将对可能不属于我们自己的秘密(即:它们可能属于某个 fork 存储库的人)发出警报。这就需要使用 GitHub 的开发者更加努力地进行分流。
虽然这三种情况令人震惊,但这还不包括 GitHub 可能从你的存储库中存储删除数据的所有方式。
最后,研究人员也警示道,「虽然我们的研究重点是 GitHub,但需要注意的是,其他版本控制系统产品也存在上述问题」。