CVE-2019-11229詳細分析 --git config可控-RCE

酷酷的曉得哥發表於2019-07-24

作者:LoRexxar'@知道創宇404實驗室

2019年4月15號,gitea曾爆出過一個漏洞,恰逢當時對這個漏洞比較好奇就著手去研究了一下,漏洞的描述是這樣的:

models/repo_mirror.go in Gitea before 1.7.6 and 1.8.x before 1.8-RC3 mishandles mirror repo URL settings, leading to remote code execution.

在和朋友@hammer的一同研究下,成功控制了git config的內容,但是在從git config到RCE的過程遇到了困難,就暫時擱置了,在過了幾個月之後,偶然得到@Lz1y和@x1nGuang兩位大佬的啟發,成功復現了這個漏洞,下面我們就來仔細研究下這個問題。

分析補丁

首先根據cve的資訊,確定漏洞1.7.6和1.8.0-rc3上修復

根據漏洞檔案為 repo_mirror.go 這個資訊鎖定更新的commit,commit主要為 #6593和#6595

根據patch可以大致鎖定問題的關鍵點

/models/repo_mirror.go

當倉庫為mirror倉庫時,settings頁面會顯示關於mirror的配置

if !repo.IsMirror {
        ctx.NotFound("", nil)
        return
    }

patch中將原來的修改配置檔案中的url選項修改為NewCommand。很容易理解,將寫入檔案更改為執行命令,這種修復方式一定是因為寫入檔案存在無法修復這個問題的窘境,那麼這也就說明url這裡可以透過傳入 %0d%0a 來換行,導致修改config中的其他配置。

控制 gitconfig

跟隨前面的邏輯,首先我們新建一個mirror倉庫。

抓包並修改 mirror_address 為相應的屬性。

mirror_address=https%3A%2F%2Ftest%3A%40github.com%2FLoRexxar%2Ftest_for_gitea.git"""%0d%0a[core]%0d%0atest=/tmp%0d%0aa="""

可以傳入各種配置,可以控制config檔案的內容。

比較有趣的是,如果你更新同步設定時,服務端還會格式化配置。

進一步利用

而重要的是如何從config檔案可控到下一步利用。

首先,git服務端只會保留.git裡的內容,並不是完整的類似我們客戶端使用的git倉庫。所以很難引入外部檔案。否則就可以透過設定hook目錄來實現RCE,這種思路的關鍵點在於找到一個可控的檔案寫入或者檔案上傳。

其次,另外一種思路就是尋找一個能夠執行命令的配置,並尋找一個能夠觸發相關配置的遠端配置。

透過寫檔案配合 githook path RCE

在git中,存在一個叫做Git Hook的東西,是用於在處理一些操作的時,相應的hook就會執行相應的指令碼。

在web介面,只有gitea的管理員才能管理git hook,所以對於普通使用者來說,我們就不能直接透過編輯git hook來修改指令碼。

但我們卻可以透過控制git config來修改hook存放的目錄。

當我們構造傳送

mirror_address=https%3A%2F%2Fgithub.com%2FLoRexxar%2Ftest_for_gitea.git"""%0d%0a[core]%0d%0ahooksPath=/tmp%0d%0aa="""

服務端的config檔案變為

這樣我們只要能在服務端的任意位置能夠寫入檔案或者建立檔案,我們就可以設定hookspath到那裡,並觸發git hook來執行命令。

在經過我們的仔細研究之後,我們發現,在漏洞存在的版本1.7.5版本以下,如果編輯服務端的檔案,那麼服務端的檔案就會儲存在gitea的執行目錄下生成。

/data/tmp/local-repo/{repo_id}

而這個檔案在不重啟gitea的情況下不會清除,而這個repo_id可以從其他的api處挖掘到。

具體詳細利用鏈可以看

值得注意的是,這種方式需要知道服務端執行的位置,雖然我們可以認為go的路徑都是比較形似的,也有部分人會在當前編譯目錄下執行。但可以說這種方式還是不算靠譜。

透過控制 git config 配置來 RCE

在@x1nGuang大佬的幫助下,我重新審視了和git config相關的一些配置。

gitProxy

gitProxy是用來針對git協議需要fetch等操作時,需要執行的命令。是一個用來應對特殊場景的配置選項。一般是應用於,在git請求時,可能的需要使用代理應用的場景。

這裡我們設定服務端

[core]
    gitproxy                = calc.exe

然後需要注意,同步的url必須為git開頭

但問題在於,由於gitProxy在git設計中,就是執行一個代理應用,所以無論輸入什麼,都會被當作一個應用執行,也就沒辦法帶引數。

這樣一來,在實際的利用場景中就又受到了很大的侷限,這裡可以嘗試用普通專案中的上傳檔案功能來上傳一個bin,然後抓包獲取檔案路徑,最後透過gitProxy來執行後門。

但同樣的是,這種思路仍舊受限於gitea的執行目錄,不過比起之前的利用方式來說,1.8.0版本也可以利用這種方式來RCE。

sshCommand

在git的文件中,還有一個配置是sshCommand。

這是一個在git中允許透過特殊的配置,使git fetch/git push 透過ssh來連線遠端的系統。在@Lz1y大佬的部落格中也提到了這種利用方式。

我們設定sshCommand為指定的命令

mirror_address=https%3A%2F%2Ftest%3A%40github.com%2FLoRexxar%2Ftest_for_gitea.git"""%0d%0a[core]%0d%0asshCommand=calc.exe%0d%0aa="""

然後設定協議為ssh儲存,並點選同步。

而與gitProxy不同的是,這裡可以跟引數

&mirror_address=https%3A%2F%2Ftest%3A%40github.com%2FLoRexxar%2Ftest_for_gitea.git"""%0d%0a[core]%0d%0asshCommand="touch 2333"%0d%0aa="""

寫在最後

這是一個很特別的關於git類平臺的漏洞例子,由於我在研究git config利用方式的時候遭遇了很多困難,導致這篇文章斷斷續續的復現了很久。整個漏洞利用鏈和git的特性都有強依賴,還算是挺有趣的體驗,有機會再仔細分析一下gitea、gogs和gitlab的程式碼,希望也能挖一個有趣的洞...






來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69912109/viewspace-2651677/,如需轉載,請註明出處,否則將追究法律責任。

相關文章