在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/
|