macOS紅藍對抗:如何QP具有特權的幫助工具以獲取root權限

概述

我們在此前的文章曾經提到過,macOS權限提升通常是通過誘導用戶,而不是利用0-day或未修復的漏洞來實現的。從紅隊的角度來看,有一個可能提供幫助的本地工具——AppleScript。AppleScript可以輕鬆、快速地產生虛假的授權請求,這些請求在用戶看起來可能很有說服力。儘管這並非一項新的技術,但在本文中,我們將探索一些新穎的方式,可以濫用AppleScript的功能來欺騙用戶已經在本地系統上信任的特權進程。

什麼是具有特權的幫助工具?

Mac上的大多數應用程序都不需要權限提升就可以執行工作。如果是從Apple的App Store購買的應用程序,從技術上來看,它們是不允許提升權限的。儘管如此,有時應用程序確實有充分合理的理由,需要獲取比當前登錄用戶更大的特權。我們根據Apple提供的文檔,梳理了幾種情況:

1、操縱文件的權限,文件的所有權;

2、創建、讀取、更新或刪除文件;

3、打開用於TCP或UDP連接的特權端口;

4、打開原始Socket;

5、管理進程;

6、讀取虛擬內存中的內容;

7、更改系統設置;

8、加載內核擴展。

通常,應用程序如果需要執行上述任意功能,通常只是偶爾需要執行一次。針對這種情況,在需要執行的當時要求用戶授權是有必要的。但是,儘管請求用戶授權這件事是為了提升安全性,但如果應用程序在某些場景中過於頻繁請求用戶授權執行這些動作,對用戶而言會造成一些不便。用戶不喜歡重複出現的對話框警告,也不喜歡重複多次輸入密碼。

為了解決這一問題,開發人員提出了特權分離的技術。通過創建功能受限的獨立“幫助程序”來執行這些任務,僅在安裝時要求用戶授權安裝這些幫助工具。在日常使用過程中,我們可能見過類似於以下的權限請求:

macOS紅藍對抗:如何QP具有特權的幫助工具以獲取root權限

幫助程序工具始終會以提升的權限來運行,但是其功能是有限的。至少從理論上講,該公歐只能按照父程序的要求執行特定任務。這些特權幫助工具位於本地“Library”(庫)文件夾的子文件夾中:

/Library/PrivilegedHelperTools

由於它們僅由來自App Store外部的第三方應用程序安裝,因此只有部分用戶會在系統中安裝某些軟件。然而,有一些非常流行、被用戶廣泛使用的macOS軟件已經使用了這類工具。由於操作系統並沒有移除獨立的特權幫助工具,因此,我們對一些操作系統進行排查,很有可能發現其中一些具有特權的幫助工具正在使用中。以我的操作系統為例,我在系統中發現了一些具有特權的幫助工具,具體是:

BBEdit;

Carbon Copy Cloner;

Pacifist。

父進程和特權幫助工具之間可能會濫用這一信任機制(參考CVE-2019-13013漏洞),但這並不是我們今天想要嘗試的方法。相反,我們將利用這樣的一個事實,即用戶非常熟悉這些特權進程的父應用程序,並且會習慣性地信任來自它們的授權請求。

為什麼要使用AppleScript進行欺騙?

有效的社會工程學攻擊需要依賴於良好的上下文環境。當然,我們可以隨時拋出一個虛假的用戶警報,但如果想使其更具迷惑性,我們希望這個警報具有以下的特點:

1、看起來更加真實:包括在警報中使用令人容易信任的文本、具有迷惑性的標題以及具有相關性的圖標。

2、出於令人信任的理由觸發:如果一個與業務無關,或者從沒有要求過特權的應用程序觸發了用戶警報,將會有很大概率引起用戶的懷疑。因此,以具有特權的幫助工具作為目標將非常關鍵,特別是在我們提供足夠真實的詳細信息以便用戶進行確認,這會增加提示信息的可信性。

3、在適當的時間觸發:例如,可以選取當前用戶正在使用我們試圖仿冒成的應用程序時。

利用AppleScript,上述所有要求都非常容易實現。下面是一個例子,我們可以嘗試使用AppleScript來創建。

macOS紅藍對抗:如何QP具有特權的幫助工具以獲取root權限

這個對話框實際上是非常粗糙的。可以看到,這裡沒有使用輸入用戶名和密碼的兩個字段。但即使如此,這個對話框也有一定的迷惑性。其中包含一個有效的標題、一個有效的圖標餓一個有效的進程名稱,如果用戶需要進一步確認,用戶會找到相應的具有特權的幫助工具。具體而言,用戶在驗證的過程中,會發現這個幫助工具確實位於自己的/Library/PrivilegedHelperTools文件夾中。用戶必須深入挖掘,才能真正發現我們的欺詐行為。

當然,一些對其懷疑的用戶很可能會直接按下“取消”鍵,而不會進行過多的深入挖掘。但幸運的是,使用AppleScript,我們可以使得用戶在按下“取消”按鈕後殺死父應用程序,或產生無限循環的代碼,從而使這一請求看起來更具說服力,並且阻止目標用戶再次點擊“取消”鍵。

但是,無限次重複的情況可能還會引起用戶的懷疑,但是殺死父應用程序併發出合適的警報來“解釋”這種情況似乎更為合理。當用戶重新啟動父應用程序,並再次觸發我們的授權請求時,用戶會更有可能輸入密碼,並繼續其工作。

為了實現良好的效果,我們還可以針對用戶首次嘗試輸入的密碼彈出錯誤提示,並讓用戶輸入兩次。由於輸入的內容不會在用戶屏幕上顯示,因此用戶也並不清楚自己是否在第一次時無意出現錯誤。強制用戶輸入兩次時,我們可以判斷第一次用戶的輸入是否正確,並在第二次輸入驗證通過之前,先驗證用戶密碼。在本文中,我們將不會過多描述這一技術細節,此前我們已經進行了大量的研究工作。

創建欺騙腳本

如果我們不熟悉AppleScript,或者不瞭解自Yosemite 10.10以來的macOS最新特性,我們可能會驚訝地發現,可以將Objective-C代碼嵌入到腳本之中,並直接調用Cocoa和Foundation API。這意味著,我們就擁有了本地API的所有功能,例如:NSFileManager、NSWorkspace、NSString、NSArray等等。在下面的示例中,我使用的是商業版AppleScript編輯器,但它也有免費版本。與內置的Script Editor應用程序相比,AppleScript編輯器更加便於作為開發環境使用。

與其他任何腳本或編程語言一樣,我們需要“導入”所需使用的框架,在AppleScript中是使用use關鍵字來完成的。我們可以將以下內容放在腳本的最開始部分:

macOS紅藍對抗:如何QP具有特權的幫助工具以獲取root權限

這些既能充當快捷方式,也能作為AppleScript與ObjectiveC腳本之間的“橋樑”,同時還可以讓我們以便捷的方式訪問命名的API,如下所示。

接下來,我們編寫一些“處理程序”(函數)來遍歷PrivilegedHelper工具目錄。在下圖中,左邊展示了我們將要編寫的處理程序,右邊是在我的計算機上返回的示例。

macOS紅藍對抗:如何QP具有特權的幫助工具以獲取root權限

如我們所見,這個處理程序只是另一個處理程序enumerateFolderContents:的包裝器,這個處理程序是我們從社區論壇借鑑而來的。我們來仔細分析一下它的代碼,代碼部分有一些複雜:


# adapted from a/>on enumerateFolderContents:aFolderPath
set folderItemList to "" as text
set nsPath to current application's NSString's stringWithString:aFolderPath
--- Expand Tilde & Symlinks (if any exist) ---
set nsPath to nsPath's stringByResolvingSymlinksInPath()

--- Get the NSURL ---
set folderNSURL to current application's |NSURL|'s fileURLWithPath:nsPath

set theURLs to (NSFileManager's defaultManager()'s enumeratorAtURL:folderNSURL includingPropertiesForKeys:{} options:((its NSDirectoryEnumerationSkipsPackageDescendants) + (get its NSDirectoryEnumerationSkipsHiddenFiles)) errorHandler:(missing value))'s allObjects()
set AppleScript's text item delimiters to linefeed
try
set folderItemList to ((theURLs's valueForKey:"path") as list) as text
end try
return folderItemList
end enumerateFolderContents:

現在,我們有了具有特權的幫助工具的列表,我們需要在路徑中提取出文件名,因為我們希望在消息文本中使用這些名稱來增強可信度。此外,我們可以從幫助工具的二進制文件中找到父應用程序,並將其顯示給用戶,同時還需要查找應用程序對應的圖標。

這是我們執行第一個任務的方式,下圖左側是我們的代碼,右側展現了輸出內容:

macOS紅藍對抗:如何QP具有特權的幫助工具以獲取root權限

現在,我們已經有了目標,接下來的工作就是找到父應用程序。為此,我們將借鑑Erik Berglund的腳本並進行微調。

macOS紅藍對抗:如何QP具有特權的幫助工具以獲取root權限

在上面的示例中,我們可以看到父應用程序的Bundle Identifier是“com.barebones.bbedit”。我們可以通過多種方式從字符串中提取標識符子字符串,比如我們可以使用awk之類的命令行使用工具(類似於Erik使用的方法),或者使用cut to slice字段。但是,出於效率的考慮,同時為了避免不必要地產生更多進程,我選用了Cocoa API的方法。請注意,無論使用哪種技術,標識符都不會始終出現在同一位置,並且可能不會以“com”開頭。不過,在我們嘗試的所有場景中,它都是緊隨在“identifier”之後的。因此,我將其作為主要的分隔符。在這裡,需要確保我們的代碼考慮了一些特殊情況,由於空間不足,我在這裡將省略錯誤檢查的環節。

macOS紅藍對抗:如何QP具有特權的幫助工具以獲取root權限

在上面的代碼中,我使用Cocoa API首先在分隔符的任意一邊拆分字符串。我們在第二個子字符串的開頭部分找到實際的Bundle Identifier。在這裡,需要注意後面的as text。在混合AppleScript與Objective C時,我們必須解決的一個難題時如何在NSString和AppleScript文本之間來回轉換。

有了父應用程序的Bundle Identifier之後,藉助NSWorkspace,我們可以找到父應用程序的路徑。我們還將添加一個循環,以對PrivilegedHelperTools文件夾中的所有項目執行相同的操作。

macOS紅藍對抗:如何QP具有特權的幫助工具以獲取root權限

請關注我在這裡是如何將文本轉換從bundleID變量中移走的,因為現在仍然需要NSString來進行NSWorkspace調用。文本轉換將被延遲,直到在AppleScript調用中再次需要改字符串,該調用發生在repeat方法的末尾。

至此,我們現在有了每個具有特權的幫助工具的名稱及其路徑,以及Bundle Identifier和每個幫助工具父應用程序的路徑。有了這些信息,我們就幾乎擁有了授權請求所需的一切。接下來的最後一步,就是從每個父應用程序中獲取應用程序圖標。

獲取父應用程序的圖標圖像

應用程序圖標通常位於應用程序包的“Resources”(資源)文件夾中,並具有.icns擴展名。由於我們已經擁有了應用程序的路徑,因此獲取圖標的過程應該非常簡單。

在繼續之前,我們首先需要為接下來的工作添加幾個“幫助處理程序”,以保證代碼的簡潔。

macOS紅藍對抗:如何QP具有特權的幫助工具以獲取root權限

此外,在腳本的最上方,我們定義了一些常量。目前,我們將其保留為純文本格式,但在最終版本中我們可以藉助各種方法對其進行混淆處理。

macOS紅藍對抗:如何QP具有特權的幫助工具以獲取root權限

注意其中的defaultIconStr常量,它提供了我們的默認值。如果要查看其詳細內容,可以使用以下命令來進行調用:


-- let's get the user name from Foundation framework:
set userName to current application's NSUserName()
display dialog hlprName & my makeChanges & return & my privString & userName & my allowThis default answer "" with title parentName default button "OK" with icon my software_update_icon as «class furl» with hidden answer


macOS紅藍對抗:如何QP具有特權的幫助工具以獲取root權限

這個顯示的圖標還不錯,但還有繼續優化的空間,如果使用應用程序的實際圖標,看起來會好很多。圖標的名稱被定義在應用程序的Info.plist中。我們可以添加另一個處理程序來對其進行抓取:

macOS紅藍對抗:如何QP具有特權的幫助工具以獲取root權限

這是獲取整理後的圖標的代碼:

macOS紅藍對抗:如何QP具有特權的幫助工具以獲取root權限

下面是我們的腳本目前生成的一些示例:

macOS紅藍對抗:如何QP具有特權的幫助工具以獲取root權限

macOS紅藍對抗:如何QP具有特權的幫助工具以獲取root權限

總結

至此,我們產生的授權請求看起來非常具有說服力。在這些請求中,現在已經包含了一個真實的應用程序名稱和一個進程名稱。如果用戶對它們進行深入調查,會發現它們都是合法的。此外,我們還有一個適當的密碼字段,並且在消息文本中包含用戶名稱。在這一點上,並沒有觸發Mojave和Catalina版本中對AppleScript的增強安全機制,因此使用時也無需預先調查受害者計算機的版本信息。最重要的時,這一過程中完全不需要任何特權。

這樣一來,我們就獲得了想要的權限。在下一部分的文章中,我們將繼續深入探究如何捕獲用戶輸入的密碼、如何在用戶計算機上找到適當的時間來啟動欺騙腳本,以及如何找到恰當的應用程序。我們將研究如何採用相同的技術來針對使用kexts和LaunchDaemons的其他特權應用程序。除此之外,我們將研究其他AppleScript技術,以構建具有兩個文本字段的增強型對話框,敬請關注我們接下來的文章!

說明:本文中所提及的所有技術和操作過程都是完全合法的,且全程未利用任何漏洞,文章未涉及到任何漏洞的詳細信息。僅供安全研究者與開發人員學習使用,不得用於非法用途。

如果你對macOS對抗感興趣,可以點擊下方擴展鏈接,查看更多相關內容。


分享到:


相關文章: