纵向分析数百万个 GitHub 存储库,超 10 万个存在 API 或密钥泄露

近日,北卡罗莱纳州立大学 (NCSU) 学者研究了数百万个 GitHub 存储库中的数十亿个文件。据悉,研究人员使用 GitHub search API 捕获并分析了 681784 个库中的 4394476 个文件,并在 Google 的 BigQuery 数据集中记录了 3374973 个库中的 23237633353 个文件。

研究人员使用了两种互补的方法来检查了收集到的数十亿个文件,包括扫描到的近六个月的 GitHub 存储库实时 commit 和 13% 的开源存储库的公共快照。为了确保准确性,采用了手工和自动评估两种方法。

研究发现,GitHub 存储库的 API 令牌和密码密钥泄露无处不在,受影响的 GitHub 存储库超 10 万个,且每天还有新的 API 和密钥泄露在不断发生。

针对 GitHub 存储库的泄露,研究人员做了大量的纵向分析,得到了如下结论:

  • 使用 GitHub API 可以很容易地实时检测到秘密泄漏,即使在仅使用单个 API 密钥并保持在默认速率限制内的实现中也是如此。该方法实现了目标文件 99% 的覆盖率。
  • 很多密钥被泄露了,平均每天有 1793 个密钥泄露。
  • 使用本文概述的搜索方法,发现 GitHub 密钥泄露的平均时间为 20 秒,时间范围大约为从 0.5 秒到 4 分钟以上。
  • 泄漏的密钥中 89% 是敏感的,也就是说它们并不是测试密钥。
  • 对于“multi-factor”秘密(如 google oauth id),当一部分泄露时,其它一部分也有 80% 的泄露可能性。
  • 许多泄露的密钥长期保存在 Github Repos 中,其中 81% 保存时间在 16 天以上。
  • 密钥一旦被泄露,重写、改写都没有用,必须立即撤销。

数据泄露并不全是开发者的锅,即使是由经验丰富的开发人员来运行高价值的项目也可能出现数据泄露的情况,例如美国一个负责大学申请的网站的 AWS 安全凭证疑似被承包商泄露,西欧某个国家的政府机构网站的 AWS 安全凭证也疑似遭泄露。

如何在 GitHub 中检测机密信息

目前比较好的用于机密信息检测的信息源有两个:GitHub search API 和在 Google BigQuery 中维护的 GitHub 公共数据集。检测的第一个阶段是使用精心设计的一组搜索词查询可能包含机密的候选文件。

选定一组候选文件之后,接下来需要的是一组流行密钥格式的正则表达式。研究人员研究了一些流行系统和服务的关键结构,并得到了一组在揭示机密方面非常准确的正则表达式。

使用正则表达式扫描第一阶段的候选文件,如果匹配,那就标记为“候选机密”。这一操作是为了减少假阴性错误,例如,在测试用例中使用“AKIAXXXEXAMPLEKEYXXX”模式的密钥可能就在这一阶段被过滤掉了,而通过过滤器的一组密钥可能就是真正泄露的机密。

为了确保这一方法的准确性,笔者手工验证了随机的密钥样本,结果发现 89.1% 被发现的机密确实是敏感的。

GitHub search

GitHub search API 的速度是有限的,但使用一个 API key,仍然可以每 30 分钟运行一次所有候选文件的查询。研究人员发现,这个速度足以覆盖 99% 的、在没有速度限制情况下被发现的所有可能文件。

这一结果表明,在 GitHub 规定的 API 速率限制内合法运行的单个用户能够近乎完美地覆盖 GitHub 上为敏感搜索查询提交的所有文件。相应的,有动机的攻击者也可以获得多个 API 密钥并实现完全覆盖。

另外,研究人员还做了另外一个测试,故意将“机密”推送到一个已知的存储库,并不断地查询 API,直到字符串出现为止,每分钟进行一次,总共持续了 24 小时。

结果发现,发现“机密”的时间从 0.5 秒到 4 分钟不等,中位数为 20 秒。这个实验证明 GitHub search API 实现了近乎实时的“机密”发现。

Github search API 从 2017 年 10 月 31 日运行至 2018 年 4 月 20 日,期间,共收集了 440 万份候选文件,其中 307000 份文件包含 40 多万个机密。根据调查发现,平均每天会有 1793 个密钥泄露。

Google BigQuery dataset

谷歌使用许可文件维护公共 GitHub repos 的 BigQuery 数据集。2018 年 4 月 4 日,其扫描了 330 万 repos 中的 23 亿份文件,结果发现了 73799 个独特的秘密字符串。

Validity Filters

以下三个过滤器可以有效过滤掉假阴性错误:

entropy filter:捕捉到 entropy 很低的机密;

words filter:捕捉包含至少 5 个长度的普通字典单词的机密;

pattern filter:查找重复字符 (如’ AAAA ‘)、升序字符 (’ ABCD ‘) 和降序字符 (’ DBCA ‘);

由正则表达式匹配的字符串中 99.29% 都通过了过滤器,正则表达式检测到的机密中只有一小部分是“伪机密”。

研究人员仔细研究了泄露的每种密钥类型,其中最常见的泄露的密钥类型是针对 Google API。

研究人员认为所有密钥类型的泄露概率是一样的,而泄露概率的高低则反映了 GitHub repos 中不同 API 的流行程度。

History rewriting

显然,实时监视 commit 的人可以及时发现被泄露的机密,即使是被删除了、commit 被改写了,机密照样可以被恢复。

研究人员发现,仅使用 commit 提交的 SHA-1 ID 就可以从 GitHub 恢复已删除 commit 的全部内容。另外,通过 Events API 可以轻松地恢复所需的 commit 散列,API 历史数据也可以通过 GitTorrent 项目获得。

写在最后

通过上文我们发现公共存储库平台上的机密泄露是非常严重的,开发人员和服务始终处于妥协和滥用的风险中。最关键的是,这个泄露问题现在还没有很好的解决方案。

GitHub 中有一个令牌扫描功能,可以从一组有限的提供者中寻找令牌,如果密钥被提交到公共存储库中,那么它就会通知提供者。

原文链接: How bad can it git? Characterizing secret leakage in public GitHub repositories