在nVisium 公司内部,我们都使用Git办公,我们经常使用github来托管我们的源码。 我们有很多客户也是通过git来管理他们程序的源码。 鉴于此,我们觉得保护我们自己和客户托管在Github上的源码非常重要。
我们最近讨论比较多的就是关于Git中 冒名commit 的问题,举个栗子,当用户向源码托管仓库提交了一个包含用户Email 地址的commit,对于像Github 或者Bitbucket这种 基于Git协议的源代码托管系统来说,这些Email地址都会指向一个特定的Git账户。Github 就会标记这个commit来自这个commit 中Email所指向的账户 。从安全角度来看,利用像Email地址这种已知信息进行伪造commit 信息非常有意思。 我们的CTO Ken Johnson 已经多次谈过这个问题, 但是我们觉得还是有必要继续进行深入分析研究。
0×01. 伪造commits实例分析
案例1: 以CTO之名 提交代码
下面是一个简单的例子,用于展示0×00 中提到的commit 伪造提交问题。
我创建了一个公开的Git 仓库,然后push 了一个初始化commit
从上图中可以看出,我们的.gitconfig中配置的Email地址为:john.poulin@nvisium.com,这个commit信息中包含了我所配置的Email地址
如果我更改.gitconfig中的邮件地址(如下图),重新提交,会发生什么呢?
上图修改.gitconfig中的Email地址为我们CTO的账户ken.johnson@nvisium.com
接下来,我们尝试去提交一些包含恶意代码或者安全漏洞代码的commit,作为安全公司的CTO,提交包含漏洞的代码是非常令人难堪的。 好了,我们以他(CTO)的名义提交了一段基于Rails的含有动态渲染漏洞的代码, 如下图:
然后我们去github上查看提交历史,看看有什么有趣的事情发生,如下图:
我以我们CTO的Email地址提交了一个伪造commit
Github接受了这个提交,显示是我们的CTO 提交了这段代码,但是Github认为这个Commit中的Email地址没有和当前账号关联,Github 建议我们将commit 中的Email 标记为提交者的账户关联Email,这个我们稍后再说。
案例2模拟Linus Torvalds 大神 给我们提交代码
让我们再来看一个更有说服力的例子, 我们去看一眼我们CTO的github上的一个示例项目
从图中可以看出来,Linus Torvalds 大神也给这个项目贡献过commit(Linus Torvalds 大神可是很忙的,实际上大神不可能会提交commit的)
为什么会出现上图的问题,这是因为Github 没有对commit 提交进行认证,我们可以很容易的以他人的名义伪造commit信息。 举例例子,一般来说,我们的CTO ken 比公司中其他员工更值得信任吧,因此,相比其他员工,一般我们都会更愿意接受来自我们CTO提交的代码,审核部门的人员对于CTO这种高级别的开发人员提交的代码往往审核不严格(一般走个形式就行了)。如果我们以CTO 的名义(Email) 提交commit 信息,那么审核人员往往会通过。这样就实现了伪造commit信息提交代码。
案例3 在特定场景下劫持其他人的Github commit
我们发现另外一种导致安全隐患的场景,在Github上,特定环境下, 你可以声称你是一个老的邮箱的拥有者, 如果这个账户处于停用状态(也就是说这个停用的账号和其曾经commit中的Email地址没有关联了),任何人都可以声称指定账号曾经的commit是属于他的。 举个例子,我们以前就见过这种例子,当时,我们给我们CTO的一个旧账号贡献了一个commit。
在浏览我们自己的代码仓库的时候,我们发现有一个来自我们CTO账号的commit,当我在github上打开的时候,github询问我是否将commit中的Email地址和本账号关联,很显然,这引起了我的兴趣与注意, 于是将我的账号与此Email关联在一起了。
一旦我选择将此Email 与我的账号关联后, 我在我的账号设置中发现,这个刚刚关联的Email地址被Github标记为 ‘未认证’
一旦我选择将此Email和我的账户关联在一起后,这个Email所有的commit请求都被标记是来自我的提交,事实上,在这段时间内,我压根没有用我的账号提交过任何东西。
在这种场景下,如果选择将账号和其他人的commit中的Email关联, 那么这些来自这个Email的commit 都会属于我。 如果我的公司以在git上提交的数量和频率来考核员工的话,那么我就是赢家, 因为我可以很容易欺骗他们。
0×02. 如何解决commit 伪造的问题
Github已经意识到上述这些问题,但他们认为这是他们有意设计的,不是安全隐患。 其实,根本原因是git协议所致,因为git协议本身没有提供对于commit的认证。 这里需要说清楚的一点就是,如果你没有权限访问一个代码仓库,这些安全隐患是不存在的(也就是不能伪造commit), 也就是说,我没法利用这些安全隐患去劫持一个私有仓库。关于这些问题, 我和github的几位员工有过交流。 解决这些问题的最好的方式就是利用GPG签名这些commit。 具体说来就是,当你提交commit的时候,github会用commit中的Email对应的私钥签名你的commit,然后提交之后github会用当前账号的公钥去校验这些签名,如果通过了校验,这些commit 会被显示为 ‘verified’.
我强烈建议大家开启自己Github中的GPG签名功能,这个功能设置非常简单,有关详情,你可以参考GitHub操作指南
此外,你如果管理着一个项目,或者你是你们单位的安全工程师,我建议你强制所有的github commit 必须经过GPG签名和认证, 这样就可以确认这些commit确实来自这些声称者提交的。这样就不会有了冒名他人提交恶意代码的情况出现。
Origin Refer: https://nvisium.com/blog/2017/06/21/securing-github-commits-with-gpg-signing/
|