查看原文
其他

糟糕!超100000万个 GitHub 仓库泄露了 API 及加密密钥!

Adrian Colyer CSDN 2019-04-16


日前,来自北卡罗来纳州大学(NCSU)的团队对全球知名的开发者社区 GitHub 开展了一项深入的研究,研究人员在使用 GitHub Search API 获取并分析了代表681784个代码库的4394476个文件,以及代表谷歌的BigQuery数据库中记录的3374973个代码库的另外2312763353个文件之后,令人诧异的结果出现了,其中,研究人员发现了575456个 API 和加密密钥,其中 201642 个是唯一的,所有这些密钥分布在100000多个 GitHub 项目中,而且使用 Google Search API 找到的密钥和通过 Google BigQuery 数据集找到的密钥是几乎没有重叠。

最终,该团队表示,他们跟踪的 API 和加密密钥中有6%在泄漏后一小时内被删除,超过12%的密钥在一天后被删除,而19%的密钥暴露了16天。

作者 | Adrian Colyer

译者 | 弯月

责编 | 屠敏

出品 | CSDN(ID:CSDNnews)

以下为译文:

北卡罗来纳州大学(NCSU)的团队发布的论文《How bad can it git? Characterizing secret leakage in public GitHub repositories》

  • https://www.ndss-symposium.org/wp-content/uploads/2019/02/ndss2019_04B-3_Meli_paper.pdf

你可能会说,这不是什么新鲜事。我们知道开发人员不应该提交密钥,我们也知道泄漏到GitHub上的密钥很快就会被人发现和利用。不过这篇论文进行了更深入的研究,所以能够为我们提供一些非常切合实际的信息。

“……我们不仅注意到了泄漏发生的情况,而且还对泄漏进行了保守的纵向分析,以及对其根本原因的分析和当前缓解措施的局限性。”

在我看来,避免密钥提交的最佳时机在提交之前。而在Git的pre-commit钩子中使用这篇论文附录中介绍的正则表达式就是个非常好的办法。TruffleHog(https://github.com/dxa4481/truffleHog)就采用了pre-commit钩子的方法,但是在该论文撰写的时候,TruffleHog的密钥检测机制(仅能检测到25-29%)明显低于这篇论文的成果(§VII.D节)。你还可以看一下为防止AWS密钥提交而开发的git-secrets(https://github.com/awslabs/git-secrets),你可以在这个工具的基础上自行用其他正则表达式进行扩展。为了做到万无一失,你还可以考虑与GitHub集成,在密钥被泄漏时提醒你,这样你就可以及时废除密钥了。

下面来简要介绍一下这篇论文的主要内容:


前言


  • 使用GitHub API可以很容易地实时检测到密钥的泄漏,即使在实现中仅使用一个API key,并采用默认的速率限制,也能达到很好的效果。这篇论文中介绍的方法实现了99%的目标文件覆盖率。

  • 即使我们都心怀善意,但还是有很多密钥被泄漏(每天被泄漏的密钥中位数为1793个)。

  • 通过论文中介绍的搜索方法,找到泄露到GitHub上的密钥的时长为半秒到4分钟以上,中位数为20秒。也就是说,一眨眼的功夫就能找到,等你发觉自己不小心提交了密钥时就已经晚了。

  • 泄露的密钥中看似非常敏感的密钥占了很高的比例(89%),也就是说这些都不是用于测试的密钥。

  • 使用多元认证方式(例如Google OAuth ID)的情况下,如果其中一个密钥key被泄漏时,另一个也会被泄漏的概率高达80%。

  • 许多泄漏的密钥都会在GitHub代码仓库中保存很长一段时间(16天后仍有81%还在)。

  • 即使重写历史记录也无法在密钥泄露后隐藏密钥。(你需要立即废除密钥,这很显然,对吧?)

如果没有保护措施,人类就很容易犯错。(也就是说,如果你的流程不完善,请不要责怪开发人员!)。

“我们的数据显示,即使是由经验丰富的开发人员负责的重要密钥也有可能泄漏。举个例子,美国数百万学生申请大学时使用的一个主要网站采用了AWS认证,然而我们发现该认证使用的密钥可能被一个工作人员泄漏了。我们还发现西欧国家的主要政府机构的网站也采用了AWS认证……”


如何检测GitHub中的密钥


至少有两个非常好的信息来源可以用来检测密钥:GitHub Search API以及Google BigQuery维护的GitHub公共数据集。检测过程的第一步是通过精心设计的一组搜索词,查询可能包含密钥的候选文件:

拿到一组候选文件后,接下来你需要的是一组流行密钥格式的正则表达式。论文的作者研究了很多流行系统和服务的关键结构,并发现了下图所示的结果。事实证明,论文附录中提供的下列正则表达式在寻找密钥时非常准确。例如:

然后,你可以使用这些正则表达式扫描上述第一阶段获得的候选文件,所有的匹配都可能是“候选密钥”。然后,通过一组过滤器筛查这些候选密钥。例如,密钥模式“AKIAXXXEXAMPLEKEYXXX”很可能是在测试时使用的,该密钥将在这个阶段被过滤掉。顺利通过这些过滤器的密钥集即是真正遭到泄漏的密钥。论文的作者手动验证了一个随机的密钥集合样本,这个过程发现的密钥中估计有89.1%确实属于敏感信息。


GitHub搜索


GitHub Search API具有速率限制。但是只需要使用一个API key,那么每隔30分钟就可以运行完所有用来查找候选文件的查询。论文的作者发现,这个频率足以发现99%可能包含密钥的文件,而且没有速率限制。

“这一结果表明,一个用户在GitHub的API速率限制内,完全可以合法地运行敏感搜索查询,从而几近完美地找到所有提交到GitHub上的文件。当然,有强烈动机的攻击者可以获取多个API key,并实现全面的覆盖。”

在另一项测试中,论文的作者故意将“密钥”push到了某个已知的代码库中,并持续查询API,直到该字符串出现。该实验以每分钟一次的频率进行了24小时。

“我们发现找到密钥的时长为半秒到4分钟,中位数为20秒,而且没有明显的时段影响。重要的是,这项实验表明我们的搜索API方法几乎可以立即发现密钥,也就是说几乎可以实时地发现密钥。”

GitHub Search API搜索了从2017年10月31日到2018年4月20日的所有文件。在此期间收集了440万候选文件,并从30.7万文件中找到了40万个密钥。这项搜索每天发现新密钥的中位数为1793个。


Google BigQuery数据集


Google在许可下维护着公共GitHub代码仓库的BigQuery数据集。论文作者的这个数据集是于2018年4月4日查询到的,当时扫描了330万个代码仓库中的23亿个文件,总共发现了73,799个唯一的密钥字符串。


有效性过滤器


该数据集使用了如下三个有效性的过滤器来过滤掉假阳性:

  • 熵过滤器,可以过滤掉熵非常低的密钥。

  • 单词过滤器,可以过滤掉包含长度不小于5的常用单词的密钥。

  • 模式过滤器,可以过滤掉重复字符(例如'AAAA'),升序字符('ABCD')和降序字符('DBCA')。

至少这些过滤器表明,正则表达式检测到的密钥中只有一小部分是虚假密钥。与正则表达式相匹配的字符串中99.29%通过了过滤器。如果你的工作中也需要实现这样的过滤器,那么可以使用“所有虚假的密钥中都包含EXAMPLE之类的单词”这种更为简单的实现。


作者团队发现了哪些类型的密钥?


作者团队提出的每一种密钥类型中都找到了泄露的密钥!下表只给出了一部分,而最常见的泄露密钥是针对Google API的密钥。

我认为所有密钥类型的泄漏概率应该都差不多,因此上述表格表明GitHub代码仓库中不同API的流行程度。


重写历史记录


“很明显,实时监控代码提交的人可以马上发现泄漏的密钥,即使泄漏的密钥被简单地删除也能被捕获到。然而根据我们的发现,即使重写提交历史记录,密钥也仍然可以被恢复……我们发现只需要使用commit的SHA-1 ID就可以从GitHub中恢复已删除提交的全部内容。”

通过Events API可以很容易地恢复提交的哈希值。这个API的历史数据也可通过GitTorrent项目获得。


总结


“这项工作表明公共代码仓库平台上的密钥泄漏问题非常严重,这个问题尚未得到解决,开发人员和服务都置身于泄漏和滥用的风险之中。”

GitHub的测试版中有一个扫描token的功能,该功能可以从一组有限的提供者中查找token,并在密钥提交到公共代码仓库时通知提供者(不是你)。

原文:https://blog.acolyer.org/2019/04/08/how-bad-can-it-git-characterizing-secret-leakage-in-public-github-repositories/

本文为CSDN翻译,转载请注明来源出处。

【End】

 热 文 推 荐 

☞京东“地震”

☞掌握 Android 系统架构,看这一篇就够了!| 技术头条

☞漫画:如何给女朋友解释什么是乐观锁与悲观锁 | 技术头条

☞频繁跳槽涨工资?会影响征信的! | 畅言

☞39个国外SCI抢发6万篇中国英文论文?然而,真正的问题是……

☞偷电、挖矿、赚快钱,这些大学生到底怎么了?

终于有人把5G和边缘计算的关系说清楚了  | 技术头条

☞程序员为什么都爱穿冲锋衣?(最全总结)

System.out.println("点个在看吧!");
console.log("点个在看吧!");
print("点个在看吧!");
printf("点个在看吧!\n");
cout << "点个在看吧!" << endl;
Console.WriteLine("点个在看吧!");
Response.Write("点个在看吧!");
alert("点个在看吧!")
echo "点个在看吧!"

点击阅读原文,输入关键词,即可搜索您想要的 CSDN 文章。

你点的每个“在看”,我都认真当成了喜欢

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存