Capabilities

如何使用 capsh:我正在嘗試以最少的功能執行非特權 ping

  • November 17, 2021

我正在 Debian Gnu/Linux 上試驗功能。

我已將 /bin/ping 複製到我目前的工作目錄。正如所料它不起作用,它最初是setuid root。

然後,我通過 do 為我的 ping 提供最小功能(不是 root)sudo /sbin/setcap cap_net_raw=ep ./ping,並且我的 ping 正常工作。

然後sudo /sbin/setcap -r ./ping撤銷該能力。它現在沒有按預期工作。

我現在嘗試使用capsh.

capsh沒有特權,所以我需要以 root 身份執行它,然後刪除 root 並因此刪除所有其他特權。

我想我也需要secure-keep-caps,這沒有記錄在 中capsh,但在功能手冊中。我從/usr/include/linux/securebits.h. 它們看起來是正確的,因為輸出--print顯示這些位是正確的。

我已經擺弄了幾個小時,到目前為止我有這個。

sudo /sbin/capsh --keep=1 --secbits=0x10 --caps="cap_net_raw+epi" == --secbits=0x10 --user=${USER} --print -- -c "./ping localhost"

然而ping錯誤ping: icmp open socket: Operation not permitted,當它沒有能力時會發生這種情況。還有--print節目Current: =p cap_net_raw+i,這還不夠我們需要的e

sudo /sbin/capsh --caps="cap_net_raw+epi" --print -- -c "./ping localhost"將能力設置Current: = cap_net_raw+eip為此是正確的,但將我們保留為root.

編輯-1

我現在已經嘗試過sudo /sbin/capsh --keep=1 --secbits=0x11 --caps=cap_net_raw+epi --print -- -c "touch zz; ./ping -c1 localhost;"

這會產生:

touch: cannot touch `zz': Permission denied
ping: icmp open socket: Operation not permitted

第一個錯誤是預期的,secure-noroot: yes 但第二個不是Current: = cap_net_raw+eip

編輯-2

如果我把它放在==之前--print,它現在會顯示Current: = cap_net_raw+i,這樣就解釋了前面的錯誤,但不是為什麼我們在切換出 root 時失去了能力,但我認為這secure-keep-caps應該可以解決這個問題。

編輯-3

據我所知,當呼叫 exec 時,我失去了有效 (e) 和允許 (p)。這是意料之中的,但我認為安全保留上限應該阻止它們失去。我是不是錯過了什麼。

編輯-4

我一直在做更多的研究,並再次閱讀手冊。似乎在以下情況下通常ep功能會失去:您從使用者切換root(或應用secure-noroot,從而使 root 成為普通使用者),這可以用secure-keep-caps;覆蓋 當你打電話時exec,據我所知,這是一個不變數。

據我所知,它是按照手冊工作的。據我所知,沒有辦法對capsh. 據我所知,要使用功能,您需要:使用文件功能或具有不使用exec. 因此沒有特權包裝器。

所以現在我的問題是我錯過了什麼,是capsh為了什麼。

編輯-5

我添加了一個關於環境功能的答案。也許capsh也可以與繼承的功能一起使用,但為了有用,需要在執行檔上設置這些功能。如果沒有環境功能或允許繼承功能,我看不出 capsh 如何做任何有用的事情。


版本:

  • capsh從包libcap2-bin版本1:2.22-1.2
  • 在 edit-3 之前,我從中獲取了最新capshgit://git.debian.org/collab-maint/libcap2.git並開始使用它。
  • uname -a Linux richard-laptop 3.2.0-4-amd64 #1 SMP Debian 3.2.65-1+deb7u2 x86_64 GNU/Linux 使用者域是 32 位的。

能力是過程的屬性。傳統上分為三組:

  • 允許的能力(p):在目前程序中可能被“啟動”的能力。
  • 有效能力(e):目前流程中目前可用的能力。
  • 可繼承的能力 ( i ):可以繼承的文件能力。

以 root 身份執行的程序始終具有完全允許和有效的功能,因此“添加”更多功能不會產生明顯效果。(可繼承的功能集通常為空。)setcap cap_net_raw+ep ping預設情況下,為執行此程序的任何使用者啟用這些功能。

不幸的是,這些功能綁定到執行的文件,並且在執行新的子程序後不會保留。Linux 4.3 引入了環境功能,允許子程序繼承功能。(另請參見能力(7)的 execve() 期間的能力轉換。)

在使用功能時,請注意以下陷阱:

  • 將使用者從 root 更改為非 root 時,將清除有效和允許的功能(請參閱使用者 ID 更改對功能 (7)中功能的影響)。您可以使用--keep=1選項capsh來避免清除集合。
  • 更改使用者或組 ID 時會清除環境功能集。解決方案:在更改使用者 ID 之後,但執行子程序之前添加環境功能。
  • 如果一個能力已經在允許和可繼承的能力集中,則只能將其添加到環境能力集中。

從 libcap 2.26 開始,該程序獲得了通過( commit )capsh等選項修改環境功能的能力。請注意,選項順序很重要。範例用法:--addamb

sudo capsh --caps="cap_net_raw+eip cap_setpcap,cap_setuid,cap_setgid+ep" \
   --keep=1 --user=nobody --addamb=cap_net_raw -- \
   -c "./ping -c1 127.0.0.1"

提示:您可以--print在命令行的任意位置添加該選項capsh並查看其目前功能狀態。

注意:cap_setpcap需要--addambwhilecap_setuid,cap_setgid需要--user選項。

Lekensteyn 的回答似乎準確而完整,但我會嘗試從不同的角度提供另一種解釋,試圖強調環境功能集解決的問題。

當您執行時,sudo capsh --user=<some_user> --有 2 個感興趣的系統呼叫會導致重新計算(並可能丟棄)功能:

  1. setuid: 根據man capabilities:

SECBIT_KEEP_CAPS 設置此標誌允許具有一個或多個 0 UID 的執行緒在將其所有 UID 切換為非零值時保留其功能。如果未設置此標誌,則此類 UID 切換會導致執行緒失去所有功能。

換句話說,在我們上面的capsh命令中,我們需要確保在setuid系統呼叫期間設置了 SECBIT_KEEP_CAPS。否則,所有功能都將失去。這就是它的--keep=1作用。所以現在命令變成sudo capsh --user=<some_user> --keep=1 --

  1. execve:如果我們使用該--keep=1選項,所有的能力集(有效的、允許的、可繼承的)都會保留execve系統呼叫之前,但是也會execve導致重新計算能力(對於非 root 使用者),並且以一種不那麼明顯的方式。簡而言之,在添加環境功能 set 之前,在呼叫之後將功能置於執行緒的“允許”集中execve,可以:
  • 該文件必須在其“允許”集中具有該功能。這可以通過setcap cap_net_raw+p /bin/bash. 這樣做會使整個練習變得毫無用處,因為執行緒的能力集(邊界集除外)不再有任何效果。
  • 文件和執行緒都必須在它們的“可繼承”集中具有這種能力。您可能認為這樣setcap cap_net_raw+i做可以解決問題,但事實證明,execve當非特權使用者(我們目前感謝setuid)呼叫時,這會導致執行緒的可繼承權限被丟棄。所以作為非特權使用者沒有辦法滿足這個條件。

Linux 4.3 中引入的環境功能使執行緒可以保留其功能,即使在setuid一個非特權使用者後跟一個execve而不必依賴文件功能。

引用自:https://unix.stackexchange.com/questions/196483