在 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 命令,接著測試其許可權,然後透過 chownchmod 命令修改檔案擁有者和設定 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)。這三種許可權可以分別用 rwx 來表示。例如,檔案的許可權可以設定為 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 的精細控管,可以有效提升系統的安全性,並確保系統資源的合理使用。