前兩天,我們討論了如何透過服務枚舉,辨識服務並尋找可能的弱點。不過,千辛萬苦找到漏洞、取得主機上的 shell 之後……資訊蒐集還沒有結束。
進入 Linux 主機後,我們還需要確認:目前是什麼身分?能讀取哪些資料?能修改哪些檔案?這些權限又可能帶來什麼風險? 今天就從 Linux 權限模型開始理解。
本次實驗使用 user 帳號登入靶機(172.16.12.182),練習判讀檔案與目錄權限,為後續的提權枚舉建立基礎。
自主存取控制(Discretionary Access Control,DAC)是 Linux 管理檔案與目錄存取權限的基本機制。檔案擁有者通常可以設定權限,決定哪些使用者可以讀取、寫入或執行檔案。
先來看看 Linux 最基本的權限表示法:

基本權限將適用對象分成擁有者(owner)、所屬群組(group)與其他使用者(other),每一類都有對應的 r、w、x 權限位元。
圖中的
-表示「未設定該權限位元」。是否能完成操作,仍須配合身分及其他權限機制判斷。
權限設定不當,可能讓原本不該存取資料的人讀取或修改檔案。因此,CIS Benchmarks、臺灣政府組態基準(TWGCB)等安全設定基準,也包含檔案權限管理相關要求。接下來,讓我們透過實際情境,理解 Linux 如何判斷這些權限。
先看看下面這張圖的操作:

id 顯示目前的使用者是 user,而這個檔案的擁有者也是 user。檔案的權限是 077:owner 為 ---,group 與 other 都是 rwx。
真奇怪,雖然 owner 那組沒有設定任何讀、寫、執行權限,但群組明明有完整的 rwx,為什麼還是讀不到?我們來看看 Linux man-pages 的說明:

把文件的意思整理成流程圖,就是這樣:

從這個實驗可以得知:在這個沒有擴充 ACL,也未透過特權繞過檢查的情境中,系統會先判斷程序適用哪一類身分,再檢查對應的權限。
三組權限不會相加,也不會因為匹配到的那一組權限不足,就改用另外兩組。 在這個例子中,已經匹配 owner,而 owner 沒有 r,所以讀取被拒絕。
文件依據:Linux path_resolution(7) — Permissions。
技術補充:Linux 檔案存取檢查實際使用的是 FSUID/FSGID,通常與有效使用者 ID(EUID)/有效群組 ID(EGID)相同。本次實驗以一般情況說明。
另外,owner 沒有 rwx,不代表不能進行任何操作。檔案擁有者通常仍可透過 chmod 調整權限,所以這裡的結論是「目前不能直接讀取」,而不是「擁有者永遠無法取得存取權」。相關規則可參考 chmod(2)。
這也提醒我們:枚舉時不能只看到某一組有 w,就認定自己能修改檔案;必須先確認目前程序匹配的是哪一組。
root 居然也有不能直接執行檔案的時候?我們來看看下面的操作。

見鬼了——權限明明是 000,為什麼同一個檔案,root 用 cat 看得到內容,卻不能直接執行?
這要先談談 root 的「超能力」——capabilities。在 Linux 輸入 man 7 capabilities,開頭是這樣說的:

翻成白話:傳統 UNIX 在權限檢查上,主要區分特權程序與非特權程序。前者的有效使用者 ID 為 0,擁有廣泛的特權;後者則根據程序的身分資訊接受權限檢查。
問題是,一個程式可能只需要完成某項特權操作,若因此給它整套 root 權力,風險就會增加。從 Linux 2.2 開始,Linux 將傳統上屬於超級使用者的權力拆成多個可以分別啟用或停用的單位,每一個單位就稱為 capability。
其中,CAP_DAC_OVERRIDE 可以繞過 DAC 的讀、寫與執行權限檢查,但對一般檔案的執行有一項限制:
000 的檔案。x 位元中,至少要有一個被設定,才能透過這項 capability 通過執行權限檢查。
因此,本次實驗的檔案沒有任何 x 位元,root 直接執行時仍然得到 Permission denied。
注意,「可以繞過 DAC」不代表操作一定成功;SELinux、唯讀檔案系統等其他限制仍可能影響結果。具有 x 也不保證程式一定能成功執行。
另外,這裡的檔案是 shell script。「直接執行被拒絕」與「讀取腳本,再交給直譯器處理」是不同的操作,不能把結果解讀成 root 完全無法讓腳本中的指令運作。
文件依據:capabilities(7)、path_resolution(7) — Bypassing permission checks。
這個標題看起來有點驚悚,我們來看看是怎麼一回事。
回到 user 身分。這次比較兩個目錄:r3-nosticky 的權限是 0777,r3b-sticky 的權限是 1777,兩個目錄都由 root 擁有。

截圖中,r3-nosticky/victim.txt 的擁有者是 root,檔案權限為 000。然而,user 執行刪除後得到 rc=0,最後列出目錄內容,也確認檔案已經不存在。
為什麼會這樣?因為刪除檔案涉及的是移除父目錄中的檔名項目。在基本 DAC 規則下,需要檢查父目錄的寫入(w)與搜尋(x)權限,而不是要求被刪除的檔案本身具有寫入權限。路徑上的其他目錄,也必須允許程序搜尋。
在這次實驗中,user 對 r3-nosticky 目錄具有 w+x,也沒有其他限制阻止刪除。因此,即使檔案屬於 root、檔案權限是 000,仍然可以將它刪除。
那為什麼 /opt/lab05/rules/r3b-sticky/victim.txt 刪不掉?因為這個目錄多了一個特殊權限位元——sticky bit。
使用 ls -ld 查看目錄本身的權限時,可以看到 drwxrwxrwt。最後的 t 表示 sticky bit 已設定,而且 other 的 x 也已設定;對應的八進位權限是 1777,開頭的 1 就代表 sticky bit。
它會對目錄內項目的刪除與重新命名加上限制:即使具備目錄的 w+x,通常仍必須是檔案擁有者、目錄擁有者,或具有相應特權的程序,才能進行操作。
這裡的特權具體涉及 CAP_FOWNER,一般完整特權環境中的 root 通常具備它。本次實驗的 user 既不是檔案擁有者,也不是目錄擁有者,因此被拒絕刪除,得到 rc=1。
這正是 /tmp 等共用目錄使用 sticky bit 的重要原因:讓大家可以建立檔案,同時限制彼此刪除對方的檔案。
sticky bit 不會阻止原本就被允許的檔案內容寫入;能不能修改內容,仍要另外檢查檔案權限。另外,sticky bit 也不是刪除操作唯一的限制,immutable 屬性、唯讀檔案系統等同樣可能阻止刪除。
文件依據:Linux unlink(2)。
把今天的實驗整理起來,我們可以得到以下判斷原則:
| 實驗發現 | 判斷原則 | 枚舉時要注意什麼? |
|---|---|---|
| owner 沒有讀取權限,即使 group、other 有權限也讀不到 | 基本 mode bits 依身分選擇適用組別,不將三組相加 | 先確認目前程序的身分,再對照檔案權限 |
root 能讀取 000,卻不能直接執行 |
讀取與執行是不同操作,capability 也有適用條件 | 分開記錄可讀、可寫、可執行,不把 root 當成沒有任何限制 |
| 檔案不可讀寫,卻能被刪除 | 刪除涉及父目錄的權限 | 除了檔案本身,也要檢查父目錄 |
| 加上 sticky bit 後,刪除遭到拒絕 | 目錄可寫,不代表可以任意刪除他人的檔案 | 檢查特殊權限位元及檔案、目錄的擁有者 |
今天先練習確認「我能對哪些資源做什麼,以及判斷依據」。後續遇到可能的提權線索時,就能帶著這些規則繼續追查:誰會使用這個資源?我的操作又能影響什麼?