Chrome擴充套件在持久化中的應用
一、前言
2009 年12月,Chrome正式推出了擴充套件程式(extension),使用HTML、JavaScript以及CSS來擴充套件Chrome的功能。擴充套件可以使用Chrome API來阻止廣告(ad)、改變瀏覽器UI、管理cookie,甚至能與桌面應用配合使用。使用者可以在擴充套件安裝過程中授予擴充套件一些許可權,限制擴充套件行為。Chrome擴充套件可以使用許多原生API,因此也是隱藏惡意程式碼的潛在目標。隨著EDR(端點檢測與響應)產品的興起以及macOS、Windows 10新引入的安全功能,端點安全性也得到了不少提升。然而對於macOS上的惡意Chrome擴充套件,現在仍然缺乏較好的檢測機制。因此,Chrome擴充套件已經成為一種非常誘人的入侵及持久化載荷。本文介紹了macOS上利用Chrome擴充套件實現的一種載荷投遞機制,介紹了自動更新功能在攻擊過程中的應用,也介紹了使用 Apfell 的一個實際攻擊樣例,最後提出了一些基本但實際可操作的檢測指南。
二、載荷投遞
在macOS上,我們可以使用一些方法來合法地安裝擴充套件程式。Google要求開發者通過web商店來投放擴充套件程式。 最近 Google修改了相關政策,導致使用者無法從第三方網站安裝擴充套件。攻擊者雖然可以 繼續 在web商店上託管擴充套件程式,但這個策略的推出的確限制了不少潛在風險。此外,我們在macOS上也可以使用移動配置描述檔案(mobile configuration profile, .mobileconfig
檔案)來安裝擴充套件。配置描述檔案是macOS及iOS上的一種機制,可以用來管理各種設定,如桌布、應用(如Google Chrome)等。使用者可以通過滑鼠雙擊或者在命令列中通過 profiles 命令來安裝描述檔案。移動配置描述檔案採用XML格式並遵循相對簡單的格式。為了建立移動配置描述檔案,我們需要輸入PayloadUUID、應用程式ID以及更新url(下文會介紹這一點)。如果想了解配置描述檔案的更多資訊,大家可以參考這兩篇文章( 1 、 2 ),也可以參考 這個 模板檔案。在配置檔案中, ExtensionInstallSources
鍵指定了URL值,表示可以從哪些源安裝擴充套件。在URL的協議、主機以及URI欄位中我們都可以使用萬用字元。 ExtensionInstallForceList
值表示可以未經使用者同意就能安裝且無法解除安裝的擴充套件列表。 PayloadRemovalDisallowed
鍵可以阻止非管理員使用者解除安裝該描述檔案。大家可以參考 此處 資料瞭解可用來管理擴充套件及Google Chrome其他設定的一些鍵值。配置描述檔案可以用來管理macOS的各種設定,我們可進一步深入分析,研究其在攻擊場景中的應用。
關於配置描述檔案有一點非常有趣,這些配置檔案可以通過電子郵件來發送,並且 Gatekeeper 不會向終端使用者提示任何警告(Gatekeeper是MacOS的程式碼簽名強制驗證工具)。然而系統將彈出一個提示視窗,請求使用者確認安裝描述檔案。
如果描述檔案未經簽名,則使用者在輸入管理員憑據前,會看到第二個彈出視窗:
然而在安裝經過簽名的描述檔案時,作業系統只會在安裝過程中彈出一次視窗,然後就需要輸入管理員密碼。安裝完畢後,我們可以在 Profiles
配置面板中檢視描述檔案的內容。如果描述檔案未經簽名,則會以紅色高亮標出。
現在我們已經為Chrome設定了擴充套件策略,當用戶開啟該應用時,就會向描述檔案中設定的更新URL發出一系列web請求。更新URL應當指向一個manifest更新檔案,其中指定了擴充套件檔案( .crx
檔案)的應用ID以及URL。這裡大家可以查閱官方提供的 autoupdate 文件,瞭解manifest示例檔案。隨後,Chrome會下載擴充套件,將其儲存到 ~/Library/Application Support/Google/Chrome/Default/Extensions/APPID
路徑中。此時該擴充套件已經被載入瀏覽器中併成功執行。需要注意的是,在整個過程中,配置描述檔案是唯一涉及到使用者互動的一個環節。同樣,在Windows上我們也可以修改登錄檔來悄悄安裝擴充套件程式(可參考 此處 資料)。然而如果安裝源為第三方網站,Chrome只允許 inline 安裝模式。這種安裝模式需要使用者瀏覽第三方網站,網站需要將使用者重定向到Chrome Web Store,最終完成安裝過程。
三、自動更新
為了便於bug修復及安裝安全更新,擴充套件可以支援自動更新。當擴充套件託管於Chrome Web商店時,Google就會接管擴充套件的更新過程。開發者只需要上傳新版擴充套件,幾個小時後,瀏覽器就會通過Web Store更新外掛。如果擴充套件託管在Web Store之外,開發者可以具備更多的控制權。Chrome會使用 manifest.json
檔案中的更新url來定期檢查版本更新。在這個過程中,Chrome會讀取manifest更新檔案內容,將manifest中的版本資訊與擴充套件的版本資訊作比較。如果manifest版本更高,則瀏覽器會下載並安裝新版擴充套件(大家可以參考 此處 瞭解典型的manifest更新檔案)。manifest更新檔案採用XML格式,包含 APPID
以及指向 .crx
檔案的一個 URL
。對攻擊者而言,自動更新始終是一個非常不錯的機制。如下兩圖所示,惡意擴充套件使用一個域名用來正常的C2通訊,使用另一個域名來託管manifest更新檔案以及擴充套件檔案。設想一下,假如應急響應團隊將某個C2域名標記為惡意域名,阻止與該域名的所有通訊流量(1),然而與更新URL的通訊流量仍然暢通無阻(2 & 3)。攻擊者可以更新manifest版本,修改C2域名(4)、更新URL,設定能修改擴充套件的某些核心程式碼。經過一段時間後,Google Chrome就會向更新URL發起請求,載入帶有新版C2域名的新版擴充套件。
此外,如果攻擊者失去了擴充套件的控制權,或者擴展出現崩潰,那麼就可以通過更新版本來觸發擴充套件執行。一旦擴充套件仍然安裝在瀏覽器中,Chrome就會繼續嘗試並檢查版本更新。如果只更新了manifest版本,Chrome就會重新安裝並執行擴充套件。在下文中,我們將介紹如何使用一個PoC Chrome擴充套件,並使用Apfell來管理C2伺服器。
四、惡意擴充套件
Apfell是一個後利用(post-exploitation)框架,採用定製化和模組化設計思路。該框架預設情況下針對的是macOS平臺,但使用者可以建立針對其他平臺的C2 profile(策略)。對於惡意Chrome擴充套件來說,Apfell是一個理想的框架。接下來我們看一下如何配置自定義的C2 profile、生成攻擊載荷。
1、在初始化配置方面,大家可以參考 此處 的apfell文件。啟動apfell伺服器後,我們可以註冊一個新使用者,將自己設定為管理員(admin)。接下來,我們需要將 apfell-chrome-ext-payload 以及 apfell-chrome-extension-c2server 工程clone到apfell伺服器上。
2、轉到 manage operations -> payload management
頁面,該頁面中定義了 apfell-jxa
以及 linfell
載荷。每個載荷都定義了幾條命令,我們可以在控制檯中修改這些命令,然後在agent中(這裡指的是 apfell-jxa
以及 linfell
)更新這些命令。在載荷頁面左下角有一個“import”按鈕,我們可以使用json檔案匯入自定義載荷以及每條命令。為了節約大家時間,我提供了一個 檔案 ,大家可以直接匯入,建立載荷。如果成功匯入,我們可以看到名為 chrome-extension
的一類新載荷,其中包含一些可操作命令。
3、現在我們在apfell伺服器上開啟一個終端會話,轉到 apfell-chrome-extension-c2server
專案。執行 install.sh
指令碼安裝golang並編譯服務端程式,然後驗證 server
程式已編譯成功,並且位於 $HOME/go/src/apfell-chrome-extension-c2server
目錄中。
4、轉到 Manage Operations -> C2 Profiles
,點選頁面左下角的 Register C2 profile
按鈕。這裡我們需要輸入profile的名稱、描述以及支援的載荷。我們還需要上傳與擴充套件程式對應的C2伺服器程式( $HOME/go/src/apfell-chrome-extension-c2server/server
)以及C2客戶端程式碼( ./apfell-chrome-ext-payload/apfell/c2profiles/chrome-extension.js
)。
5、一旦profile提交成功,頁面就會自動更新,顯示新加入的profile。
6、回到apfell伺服器上的終端會話,編輯 c2config.json
檔案,根據需要設定相關選項。
7、將 c2config.json
拷貝到 apfell/app/c2profiles/default/chrome-extension/
目錄中。將伺服器程式重新命名為 <c2profilename>_server
,我們需要執行該操作才能在apfell UI中啟動C2伺服器。現在我們可以在apfell中啟動C2伺服器。
8、轉到 Create Components -> Create Base Payload
。在C2 profile和載荷型別中選擇 chrome-extension
,填入所需的引數(主機名、埠、端點、SSL以及間隔時間),輸入所需的檔名然後點選提交按鈕。如果一切順利,頁面頂部就會顯示一則成功訊息。
9、轉到 Manage Operations -> Payload Management
下載載荷。現在我們已成功構造擴充套件程式載荷以及C2 profile,我們可以匯出這些載荷,以便後續使用。
10、將載荷的所有程式碼拷貝貼上至chrome擴充套件專案檔案中( ./apfell-chrome-ext-payload/apfell/extension-skeleton/src/bg/main.js
)。編輯 extension-skeleton
目錄中的 manifest.json
檔案,替換其中所有的 *_REPLACE
值。如果我們沒有使用自動更新功能,可以不設定 update_url
值。
11、開啟Google Chrome,點選 More -> More Tools -> Extensions
,然後切換到開發者模式。點選 pack extension
,然後選擇 apfell-chrome-ext-payload
專案中的 extension-skeleton
目錄。再次點選 pack extension
,然後Chrome就會生成帶有私鑰的 .crx
檔案。需要注意的是,我們需要儲存好私鑰,才能更新擴充套件。
12、我們需要知道的最後一個資訊就是應用ID。不幸的是,獲取該資訊的唯一方法就是安裝擴充套件,然後記錄下擴充套件頁面上顯示的ID值。我們可以將擴充套件檔案( .crx
)拖放到擴充套件頁面進行安裝。
13、現在我們已經獲取建立移動配置檔案所需的資訊,可以託管manifest更新檔案以及crx檔案。我們需要在manifest更新檔案中加入應用ID以及指向crx檔案的url,然後在 移動配置示例檔案 中新增應用id及 update_url
。此外,我們還需要填入兩個不同的UUID值。
14、現在我們已配置完畢。如果一切配置正常,那麼安裝移動配置描述檔案後就可以靜默安裝擴充套件程式,也能在apfell的回撥頁面中新增一個新的回撥(callback)。大家可以參考前面的“載荷投遞”內容瞭解如何安裝profile。
大家可以參考 此處 視訊觀看如何通過移動配置描述檔案安裝惡意chrome擴充套件程式。
五、檢測方法
在前文中,我們簡單介紹了投遞chrome擴充套件的一種機制,可以通過移動配置描述檔案實現擴充套件的靜默及隱蔽安裝。從防禦角度來看,檢測這類投遞機制應該重點關注 profiles
命令及相關引數。這種檢測機制對已經獲得受害主機訪問許可權的攻擊者而言非常有效。作為參考,這裡給出安裝profile的示例命令: profiles install -type=configuration -path=/path/to/profile.mobileconfig
。
相應的 osquery
規則類似於: SELECT * FROM process_events WHERE cmdline=’%profiles install%’;
。對於企業環境來說這可能不是最佳答案,但的確行之有效。另外還要注意一點, osquery
現在已經包含了一個chrome擴充套件 表 。此外,當用戶通過UI安裝profile時, MCXCompositor
程序會將一個二進位制plist寫入 /Library/Managed Preferences/username/
目錄中。這個plist檔案是移動配置描述檔案的一個副本,檔名由配置描述檔案中的 PayloadType
鍵值決定。
可能還有其他資料來源,能夠更加可靠地檢測使用移動配置描述檔案的攻擊技術,這裡我們拋磚引玉,希望大家繼續研究。
在獲得初始訪問許可權及持久化方面,我們可以考慮使用Google Chrome擴充套件程式。紅隊人員及安全研究人員可以進一步研究Chrome API,瞭解更多可用功能。