在 Linux 系統管理中,經常需要讓某些程式以更高的許可權執行特定任務,setuid 位元就是早期達成此目標的機制。然而,setuid 潛在的安全風險促使 Capability 機制的誕生。本文將深入探討這兩種機制,並以 ping 命令為例,說明如何在賦予程式必要許可權的同時,最大程度地降低安全風險。
setuid 位元允許程式以檔案擁有者的許可權執行,而非執行者的許可權。這意味著即使一般使用者執行設定了 setuid 的程式,也能暫時擁有檔案擁有者(例如 root)的許可權。然而,這種「全有或全無」的許可權賦予方式容易被濫用,導致系統安全漏洞。
為瞭解決 setuid 的安全問題,Linux 核心引入了 Capability 機制。Capability 將 root 使用者的特權細分為多個獨立的單元,程式可以根據需求被賦予特定的 Capability,而非繼承 root 的所有許可權。如此一來,即使程式存在漏洞,其影響範圍也會被限制在被賦予的 Capability 內,有效降低安全風險。
ping 命令就是 Capability 機制的一個典型應用。ping 需要開啟網路 Socket,這項操作通常需要 root 許可權。在過去,ping 命令會設定 setuid 位元,以 root 許可權執行。但現在,ping 使用 Capability 機制,僅要求 CAP_NET_RAW
這個 Capability,使其能夠開啟網路 Socket,而無需完全以 root 身份執行,大幅提升了安全性。
以下實驗示範如何複製 ping 程式並測試其許可權:
cp /bin/ping ./myping # 複製 ping 程式
ls -l ./myping # 檢視許可權,應為 -rwxr-xr-x
./myping 10.0.0.1 # 以一般使用者執行,應會失敗
sudo chown root ./myping # 將擁有者改為 root
sudo chmod +s ./myping # 設定 setuid 位元
ls -l ./myping # 檢視許可權,應為 -rwsr-xr-x
./myping 10.0.0.1 # 以一般使用者執行,應會成功
內容解密
這段程式碼首先複製系統的 ping 命令,接著測試其許可權,然後透過 chown
和 chmod
命令修改檔案擁有者和設定 setuid 位元,最後再次測試許可權,觀察 setuid 位元的效果。
graph LR A[複製 ping 程式] --> B{檢視許可權}; B -- 一般使用者 --> C[執行失敗]; B -- root --> D[修改擁有者]; D --> E[設定 setuid]; E --> F{檢視許可權}; F -- 一般使用者 --> G[執行成功];
圖表翻譯
此圖示展示了複製 ping 程式並測試其許可權的流程。首先複製 /bin/ping
程式,然後檢查其許可權。接著以一般使用者身份執行,預期會失敗。然後將檔案擁有者改為 root,並設定 setuid 位元。再次檢查許可權後,以一般使用者身份執行,此時預期會成功。這個流程圖清楚地展現了 setuid 位元如何影響程式執行許可權。
總結來說,setuid 雖然能提升程式許可權,但伴隨著安全風險。Capability 機制提供更細緻的許可權管理,允許程式在最小許可權原則下執行,有效提升系統安全性。在現代 Linux 系統中,應優先考慮使用 Capability 機制,而非 setuid 位元,以確保系統安全。
Linux 中的 setuid 位
在 Linux 中,setuid 位是一種特殊的許可權設定,它允許程式以擁有該檔案的使用者的身份執行,而不是以執行該程式的使用者的身份執行。這意味著,即使普通使用者執行該程式,它也可以獲得超級使用者的許可權。
設定 setuid 位
要設定 setuid 位,可以使用 chmod
命令。例如,要設定一個名為 mysleep
的可執行檔案的 setuid 位,可以使用以下命令:
chmod +s mysleep
這將設定 mysleep
檔案的 setuid 位,使其以擁有該檔案的使用者的身份執行。
示例
假設我們有一個名為 mysleep
的可執行檔案,屬於 vagrant
使用者。我們可以使用 ps
命令檢視該檔案的屬性:
vagrant@vagrant:~$ ls -l mysleep
-rwxr-xr-x 1 vagrant vagrant 35000 Oct 17 08:49 mysleep
現在,我們設定 mysleep
檔案的 setuid 位:
vagrant@vagrant:~$ chmod +s mysleep
檢視 mysleep
檔案的屬性,我們可以看到 setuid 位已經被設定:
vagrant@vagrant:~$ ls -l mysleep
-rwsr-sr-x 1 vagrant vagrant 35000 Oct 17 08:49 mysleep
現在,如果我們執行 mysleep
程式,它將以擁有該檔案的使用者(即 vagrant
使用者)的身份執行,而不是以執行該程式的使用者的身份執行。
ping 命令的例子
ping 命令是另一個使用 setuid 位的例子。ping 命令需要開啟網路通訊端以傳送 ICMP 資料包,但普通使用者沒有足夠的許可權來開啟這些通訊端。為了解決這個問題,ping 命令的可執行檔案設定了 setuid 位,使其以超級使用者的身份執行。
但是,ping 命令實際上並不想以超級使用者的身份執行。相反,它使用 capability 機制來取得所需的許可權。這意味著,ping 命令可以在不需要以超級使用者身份執行的情況下開啟網路通訊端。
setuid 位是一種特殊的許可權設定,它允許程式以擁有該檔案的使用者的身份執行,而不是以執行該程式的使用者的身份執行。這可以用於給予程式額外的許可權,但也需要謹慎使用,以避免安全風險。
Linux 系統呼叫、存取許可權與特權
在 Linux 中,系統呼叫(System Call)是應用程式與核心溝通的橋樑。然而,為了確保系統的安全性,Linux 會對不同使用者和程式施加存取許可權和特權的限制。
存取許可權
Linux 的存取許可權是根據使用者 ID 和群組 ID 來實作的。每個檔案和目錄都有一套存取許可權,定義了哪些使用者可以存取它們。存取許可權包括讀取(read)、寫入(write)和執行(execute)三種。
- 讀取許可權:允許使用者讀取檔案或目錄的內容。
- 寫入許可權:允許使用者修改檔案或目錄的內容。
- 執行許可權:允許使用者執行檔案或目錄。
特權
Linux 的特權是根據 setuid 和 setgid 位元來實作的。當一個程式被設定為 setuid 時,它會以檔案擁有者的身份執行,而不是以執行使用者的身份執行。這樣可以讓程式獲得更高的許可權,例如 root 使用者的許可權。
實驗:複製 ping 程式並測試其存取許可權
首先,複製 /bin/ping
程式到目前目錄,並命名為 myping
:
cp /bin/ping./myping
然後,檢查 myping
的存取許可權:
ls -l./myping
輸出結果應該類別似於:
-rwxr-xr-x 1 vagrant vagrant 64424 Nov 24 18:51./myping
接下來,嘗試以一般使用者的身份執行 myping
:
./myping 10.0.0.1
應該會出現錯誤訊息,指出沒有足夠的許可權。
然後,使用 sudo
指令將 myping
的擁有者改為 root:
sudo chown root./myping
再次檢查 myping
的存取許可權:
ls -l./myping
輸出結果應該類別似於:
-rwxr-xr-x 1 root vagrant 64424 Nov 24 18:55./myping
接下來,嘗試以一般使用者的身份執行 myping
:
./myping 10.0.0.1
仍然會出現錯誤訊息,指出沒有足夠的許可權。
最後,使用 sudo
指令設定 myping
的 setuid 位元:
sudo chmod +s./myping
再次檢查 myping
的存取許可權:
ls -l./myping
輸出結果應該類別似於:
-rwsr-sr-x 1 root vagrant 64424 Nov 24 18:55./myping
接下來,嘗試以一般使用者的身份執行 myping
:
./myping 10.0.0.1
這次應該可以成功執行 myping
程式,並且以 root 的身份執行。
Linux 許可權與特權
在 Linux 中,許可權與特權是兩個重要的概念。許可權是指使用者或程式對檔案、目錄或其他資源的存取控制,而特權則是指程式或使用者執行特定動作的能力。
許可權
Linux 中的許可權可以分為三種:讀取(read)、寫入(write)和執行(execute)。這三種許可權可以分別用 r
、w
和 x
來表示。例如,檔案的許可權可以設定為 rwx
,表示該檔案可以被讀取、寫入和執行。
特權
特權是指程式或使用者執行特定動作的能力。Linux 中的特權可以分為兩種:設uid(setuid)和設gid(setgid)。設uid 是指程式在執行時可以以檔案擁有者的身份執行,而設gid 是指程式在執行時可以以檔案群組的身份執行。
設uid
設uid 是一個特殊的許可權,允許程式在執行時以檔案擁有者的身份執行。當設uid 標誌被設定時,程式將以檔案擁有者的身份執行,即使該程式是由其他使用者執行的。
例如,假設有一個名為 myping
的程式,該程式需要以 root 身份執行才能正常工作。可以設定 myping
的設uid 標誌,以便該程式在執行時以 root 身份執行。
sudo chown root myping
sudo chmod +s myping
設gid
設gid 是另一種特殊的許可權,允許程式在執行時以檔案群組的身份執行。當設gid 標誌被設定時,程式將以檔案群組的身份執行,即使該程式是由其他使用者執行的。
特權的影響
設uid 和設gid 特權可以對系統安全產生影響。如果一個程式具有設uid 或設gid 特權,則該程式可以以檔案擁有者或檔案群組的身份執行,這可能會導致安全漏洞。
例如,假設有一個名為 bash
的程式,該程式具有設uid 特權。如果該程式被設定為以 root 身份執行,則任何使用者都可以使用該程式以 root 身份執行命令,這將是一個嚴重的安全漏洞。
深入解析 Linux 的 SetUID 與 Capabilities 機制
在 Linux 系統中,安全模型的核心概念之一就是使用者許可權。為了允許特定程式執行需要特權等級的操作,Linux 提供了 SetUID 機制。然而,SetUID 機制也存在安全風險。為此,Linux 發展出了更細緻的 Capabilities 機制,允許更精確地控制程式許可權。本文將深入探討 SetUID 與 Capabilities 的運作原理、應用場景,以及如何兼顧安全與效能。
SetUID:以檔案擁有者身分執行
SetUID 是一種特殊許可權位元,設定於可執行檔案上。當設定了 SetUID 位元,執行該檔案的使用者,將暫時擁有檔案擁有者的許可權。這讓一般使用者得以執行需要 root 許可權的特定操作,例如 ping
指令需要開啟網路 Socket。
ls -l /bin/ping
-rwsr-xr-x 1 root root ... /bin/ping
ping
指令的 SetUID 位元已設定 (s),因此即使一般使用者執行,也會以 root 許可權執行。
內容解密
上述指令 ls -l /bin/ping
顯示了 ping 檔案的許可權資訊。-rwsr-xr-x
中的 s
代表 SetUID 位元已設定。這表示任何使用者執行 /bin/ping
時,都會以檔案擁有者,也就是 root 的身分執行。
graph LR A[使用者執行 ping] --> B{檢查 SetUID} B -- 已設定 --> C[以 root 許可權執行] B -- 未設定 --> D[以使用者許可權執行]
圖表翻譯
此圖示展現了 SetUID 的運作流程。當使用者執行 ping
指令時,系統會檢查該檔案是否設定了 SetUID 位元。如果已設定,則程式會以檔案擁有者 (root) 的許可權執行;如果未設定,則以執行指令的使用者許可權執行。
Capabilities:更細緻的許可權控管
SetUID 機制賦予程式檔案擁有者的所有許可權,這可能造成安全漏洞。Capabilities 機制提供更細粒度的許可權控管,允許程式僅取得必要的特權,而非全部的 root 許可權。
Capabilities 以位元集合表示,每個位元代表一項特定的能力,例如 CAP_NET_RAW
(允許使用 RAW socket) 或 CAP_SYS_TIME
(允許設定系統時間)。程式可以被賦予特定的 Capabilities,即使非 root 使用者執行,也能執行對應的操作。
#include <sys/capability.h>
#include <stdio.h>
int main() {
cap_t caps;
caps = cap_get_proc();
if (caps == NULL) {
perror("cap_get_proc");
return 1;
}
// ... 檢查或設定 Capabilities ...
cap_free(caps);
return 0;
}
內容解密
這段 C 程式碼示範如何使用 libcap
函式庫操作 Capabilities。cap_get_proc()
函式取得目前程式的 Capabilities 集合。後續可以透過其他 libcap
函式檢查或設定特定的 Capabilities,例如 cap_get_flag()
、cap_set_flag()
等。最後,cap_free()
釋放資源。
graph LR A[程式啟動] --> B{取得 Capabilities} B --> C{檢查 Capabilities} C -- 擁有必要 Capabilities --> D[執行特權操作] C -- 缺少必要 Capabilities --> E[操作失敗]
圖表翻譯
此流程圖說明程式如何使用 Capabilities。程式啟動後,會取得自身的 Capabilities 集合。接著,程式會檢查是否擁有執行特定操作所需的 Capabilities。如果擁有,則可以執行特權操作;如果缺少,則操作會失敗。
ping:SetUID 與 Capabilities 的實務應用
ping
指令是一個 SetUID 與 Capabilities 協同運作的典型案例。雖然 ping
檔案設定了 SetUID 位元,但它並非真的需要完整的 root 許可權。它只需要 CAP_NET_RAW
能力即可開啟 RAW socket。透過 setcap
等工具,可以設定 ping
僅擁有 CAP_NET_RAW
能力,降低安全風險。
SetUID 提供了簡便的方式讓程式取得特權,但 Capabilities 機制更為精細且安全。現代 Linux 系統鼓勵使用 Capabilities 取代 SetUID,在賦予程式必要許可權的同時,最大限度地降低安全風險。在設計需要特權的程式時,應優先考慮使用 Capabilities,並謹慎評估 SetUID 的使用。透過 Capabilities 的精細控管,可以有效提升系統的安全性,並確保系統資源的合理使用。