GitHub安全最佳实践
-
写在前面
-
GitHub安全最佳实践列表
-
1.不要将凭证作为代码/配置存储在GitHub中。
-
2.删除文件中的敏感数据和GitHub历史记录
-
3.限制访问控制
-
4.增加SECURITY.md文件
-
5.严格验证GitHub上的第三方应用
-
6.在PR阶段添加安全性测试
-
7.选择合适的GitHub来满足安全需求
-
8.及时更换SSH key和个人访问token
-
9.创建新项目时就考虑到安全性
-
10.审核任何引入到GitHub的代码
-
引申阅读
写在前面
Github 类的代码平台是个研发和安全人员的大宝库,阿里云效平台的代码权限事件历历在目,密码泄露到公开代码平台的事件层出不穷,为企业内外部的各种源代码管理系统(gitlab\stash\github\gitee)做好合理配置是新生事物。开发各种 github 敏感信息监控工具均属于事后管理,做好安全配置和培养员工良好的习惯才是安全管理的重中之重。
越来越多的公司和个人通过向开源社区贡献代码来提升组织影响力,但是后续维护的安全性很不及格。SRC是否接收在开源项目发现的漏洞?企业容许代码对外开源的审核标准是什么?
本文,以安全维度系统介绍了维护仓库安全应该要做的事,可以作为安全组织对标的cheat sheet。
GitHub 安全最佳实践列表
1. 不要将凭证作为代码 / 配置存储在 GitHub 中。
在 github 上执行一次搜索删除密码操作(https://github.com/search?q=removed+password&type=Commits),
可以发现在 repo 中存储密码的情况是如此普遍,简单的搜索就返回来47万次 commit 记录,这还没有覆盖到没有填写详细的commit 信息,或者已经通过删除历史记录来掩饰活动的情况。总体而言这是由来已久的安全隐患。工具使用者应当遵循最佳实践来防止将敏感数据放置到代码库中。
对于企业内部的存量代码应当也有手段去解决存量的代码中的大量密码。通过工单肯定是不现实的。有一些有用的本地工具比如git-secrets,可以通过在 pre-commit 阶段对 Git 进行 hook 来执行静态分析,以确保不会将任何密码或敏感信息 push 到 GitHub 仓库中。如果该工具配置的正则表达式匹配到任何敏感信息就会拒绝这一次 commit。这样可能会让 push 阶段延时一些,但是还是值得去做的。
还可以在 CI 和 CD 的流水线中使用 git-secrets 之类的工具,以便在代码或配置文件中发现敏感信息时就主动终止构建活动。在团队范围内推行这类的规则是检测目前开发人员工作流程中的 “坏习惯” 的好办法。唯一正确的做法是使用现有 CI/CD 流水线工具如 Jenkins 或 TeamCity 来设置环境变量来保存或者传递敏感信息。当然还可以使用 Vault 之类的工具来帮助进行生产环境的密码管理。最后还可以考虑使用身份和用户管理类的工具链 - 如Keycloak(当前由 Red Hat 的的一些开发人员维护)。
应当在早期就尝试尽可能多使用多种手段去避免将凭据引入到仓库中,但是不可避免有些敏感信息依然有可能会被带入(工具对片段代码的漏报)。隐私应该考虑定期审核代码仓库,利用 GitRob 或 truffleHog 等工具,这两个工具都可以全量扫描代码库,通过模式匹配搜索敏感信息。另外一种好方法是对每次的 git diff 阶段建立 es 索引,不过工作量相对较大。
2. 删除文件中的敏感数据和 GitHub 历史记录
如果已经在 GitHub 仓库中发现敏感数据就需要做一些应急来处理。第一步是需要将曾经过公开的 token 令牌和密码失效。一旦一个口令在互联网上公开,应该假设它已经被掌握在攻击者的手中,并做出相应动作。
当然,肯定还需要从仓库中删除敏感数据,但是不要忘记 GitHub 非常擅长保存所有 commit 的完整历史记录。包括列出敏感信息的修改日志。在从 repo 中删除敏感数据时,清除 GitHub 历史记录非常重要。有关更多信息,参考 https://help.github.com/en/articles/removing-sensitive-data-from-a-repository 。总是有通过git修改了密码,但是commit记录还存在的情况。
所以在应急响应中心发现外部报告的明文密码时,应当考虑下应急处理做的得当了吗?
3. 限制访问控制
我们可以一直专注于分析更复杂的攻击手段,但总是对一些最简单的事情上却失败得很惨。例如只需要一个开发人员在便利贴上留下他们的密码挂在电脑显示器上让攻击者访问。无论是在 GitHub 平台上,还是在一般场景下都应当遵守基本的安全设置。要求贡献者(contributors)遵循以下基本实践:
-
需要在每个贡献者的 GitHub 帐户上启用双因素身份验证。
-
永远不要让用户共享 GitHub 帐号 / 密码。
-
任何可以访问源代码的笔记本电脑 / 设备都必须得到适当的保护。
-
仓库配置管理员应该管理团队对数据的访问。只允许贡献者访问他们工作所需的数据。
-
GitHub 账户通常是个人账户,用户离开公司后不会自然注销。确保及时检查离职用户的访问权限。
4. 增加 SECURITY.md 文件
对于大多数项目所有者和维护者来说为仓库添加 README.MD 是很自然的,事实上人们也不愿意没有这个描述文件。同样,添加一个突出显示项目安全相关信息的 SECURITY.md 文件也变得越来越普遍。它不仅为用户提供了他们需要的重要安全信息,而且还迫使维护人员考虑如何处理安全披露、更新和一般的安全实践。可惜的是目前国内的开源项目大都未满足这样的条件,360代码卫士或者个人研究者提交的漏洞只能以issue方式暴露给大家。
以下是一个 SECURITY.md 文件大致应该涵盖的一些内容:
-
信息披露政策
2017 年 Snyk 开源安全报告显示,只有 21% 没有公开披露政策的维护者私下被告知存在漏洞。这使得 73% 的维护人员是公开的披露政策。安全说明了定义白帽子如何去负责任地披露安全问题的重要性。应该包括与谁联系以及如何联系。这很重要因为它允许从用户那里获得重要的反馈。其他人可能会将漏洞的存在作为一个公开 issue 进行日志记录,从而在修复方案发布之前无意中让全世界意识到漏洞的存在。当发现问题时,确保向用户提供了他们需要的所有信息,以便向项目维护者提供了正确的信息。 -
安全更新策略
软件漏洞每天都在被发现。当应用程序或库中已发现漏洞时,开发者有责任向用户说明。他们可能在关键系统的生产环境中使用的开放源代码。需要一个定义良好的流程来与他们共享相关信息,包括漏洞的严重性、带来的风险以及如何迁移到代码的release版本。预先定义此流程以便将信息推送给用户,允许用户在发现和修复新的安全漏洞时尽早更新这些漏洞。这可能与安全邮件列表一样简单。一个SECURITY.md 文件作为保存此类信息的主页,如果有一个网站可以考虑设置一个独立的页面-以 Express.js的网页https://expressjs.com/en/advanced/security-updates.html为例。 -
相关的安全配置
项目的安全性考虑超出了代码本身。用户可能需要配置的项目并创建设置,以便它在他们的环境中按需工作。应该为用户提供建议设置,以考虑在部署此项目时是否会加强他们的安全性。例如,打开 HTTPS、添加授权,当然还有替换默认密码 (许多 MongoDB 用户希望自己已经获得了这些指导=_=)。请记住,用户通常对安全性的理解相当低,因此提供任何建议都将极大地帮助他们。 -
已知的安全不足和后续的安全提升
很少有项目处于用户所希望的所有安全性改进都已实现的情况。通知用户当前尚未实现的安全控制措施很重要。使用者应了解全部情况,这样他们就可以对如何使用开源项目做出正确的决定。谁知道呢——或许用户可以主动贡献代码去实现你所提到的安全控制措施。在为用户提供加固环境所需的信息和为攻击者提供有限的信息之间需要做出权衡。始终要考虑双方如何使用你所分享出来的信息。
在 Apache Storm 和 TensorFlow 的代码仓库中可以看到 SECURITY.md 的优秀案例。
5. 严格验证 GitHub 上的应用程序
所有好的平台都可以扩展,GitHub 及其应用程序市场也不例外。在将它们添加到代码仓库时要记住第三方应用扩展是由组织和第三方开发人员编写的。在选择和安装 GitHub 应用程序时,请考虑以下几点:
-
不要给应用程序过多的访问权限。
-
询问为什么应用需要它所要求的访问级别,并考虑这种访问级别可能造成的危害。
-
在让应用背后的作者或组织访问代码库之前,验证他们的合法性和可信性,就像引入一个新的提交者一样。
-
安全性取决于最薄弱的环节,因此,如果要访问的应用的安全性较差,那么攻击者可以通过攻击它们的应用来访问你的代码——这是开发者最敏感的资产之一。
-
最后,确保定期检查或审计第三方应用及其贡献者,以确保仍然需要他们、信任他们、认为他们值得赋予权限去访问代码。
6. 向 PR 阶段添加安全性测试
GitHub 有一个功能强大的事件驱动 Git hook 框架,它允许在触发事件时向所选择的服务器发送 HTTP POST 请求。你可以选择处理大量事件,但是对于测试增量代码更改最有用的事件之一是 pull_request 事件。有许多静态代码分析工具支持 Git Hook,当创建 PR 时,会触发一个 HTTP POST 来提示它们测试最新更新的代码。这是确保正在进行的代码和配置更改符合安全预期的最佳时机。
除了方便地集成到 GitHub 之外,pull request 请求比 “中断构建” 更好,因为它们不必阻止 merge(合并),以及 pr 阶段的这些能力用来测试代码变更,而不是已存在的代码(例如,如果你引入了一个易受攻击的库就 pr 会失败,而不是去检测历史已经存在的高危组件)。
Snyk、SonarCloud 和 CodeClimate 工具都可以在自动进行代码 review 审核,自研也是一个出路,可以更好兼容于研发流程。
7. 选择合适的 GitHub 来满足安全需求
根据项目或组织制度,开发者可能被限制使用只能在本地运行的软件。或者这些限制可能是针对源代码存储在何处、哪些其他组织也可以访问。金融机构、政府部门或其他受到严格监管行业的普遍限制如此。然而这并不意味着你不能使用 GitHub!
考虑下完整版的 on-prem GitHub 企业版,它允许在组织中完全托管 GitHub 仓库。这意味着可以断开与 internet 的连接,并且仍然可以访问 GitHub 企业仓库中的项目。甚至 GitHub 都不能访问你的代码库!
8. 及时更换 SSH key 和个人访问 token
GitHub 访问通常使用 SSH 密钥或个人用户令牌 (代替密码,因为已经启用了双因素身份认证!) 但是如果这些 token 被窃取了但你不知道如何处理? 请确保定期更新密钥和 token以降低密钥泄漏造成的任何损失。
9. 在创建新项目时考虑到安全性
当创建一个新项目时,开发人员通常会很愉快地去进行修改、走捷径以便让应用程序启动并运行。这可能会导致开发人员草率处理密码之类的敏感信息,密码可能是硬编码的或者存储在本地配置中比如属性文件。不那么安全的认证措施包括:依赖一个私有加密算法来授权输入,或者暴露如何选择的随机种子。即使对于一个私有的源代码项目,用开源的思想来选择随机数也是一个很好的实践。如果时刻想着去编写其他人将看到并可能去复用的代码,才更有可能编写出更安全的代码。
此外,如果曾经想过要开放源代码,那么就会更容易、更安全,因为已经在以更安全的开放心态考虑问题,所以不会错过隐藏在代码中的密码或密钥。对于数据安全的敏感性组织可以自助度量,有的公司不容许泄露任何个人,但是笔者看到谷歌的项目里甚至都有作者的邮箱地址。
10. 审核导入 GitHub 的任何代码
当你将项目或大量代码引入到 GitHub 时,这里将很好地引导了你要做的事情。 导入到 GitHub 的源代码可能已存在数月或数年,并且可能已在封闭的源代码仓库中开发。 这可能导致在封闭源代码环境中做出的许多曾经合理的假设现在都是无效的。在将任何内容引入 GitHub 之前,一定要确保进行了完整的审计。对于较小的项目来说这可能是个顺手的测试,但是一旦代码库达到一定的大小,团队可能需要花费数周或数月的时间来完全审计、更新和导入一个开源仓库。
要进一步了解 GitHub 安全性,请确保阅读了 GitHub 安全文档和 GitHub 业务安全站点,以获得诸如外部 auth/SAML 支持等额外特性。
引申阅读
-
https://snyk.io/blog/ten-git-hub-security-best-practices/
-
https://www.aqniu.com/news-views/33301.html
-
https://www.jianshu.com/p/2c20cc638534
-
https://www.aqniu.com/news-views/6445.html
-
https://github.com/security
-
https://resources.github.com/downloads/GitHub_eBook_FSI_Secure_Development.pdf