如何使用 capsh:我正在嘗試以最少的功能執行非特權 ping
我正在 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
. 它們看起來是正確的,因為輸出我已經擺弄了幾個小時,到目前為止我有這個。
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
,當它沒有能力時會發生這種情況。還有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
如果我把它放在
==
之前Current: = cap_net_raw+i
,這樣就解釋了前面的錯誤,但不是為什麼我們在切換出 root 時失去了能力,但我認為這secure-keep-caps
應該可以解決這個問題。編輯-3
據我所知,當呼叫 exec 時,我失去了有效 (e) 和允許 (p)。這是意料之中的,但我認為安全保留上限應該阻止它們失去。我是不是錯過了什麼。
編輯-4
我一直在做更多的研究,並再次閱讀手冊。似乎在以下情況下通常
e
和p
功能會失去:您從使用者切換root
(或應用secure-noroot
,從而使 root 成為普通使用者),這可以用secure-keep-caps
;覆蓋 當你打電話時exec
,據我所知,這是一個不變數。據我所知,它是按照手冊工作的。據我所知,沒有辦法對
capsh
. 據我所知,要使用功能,您需要:使用文件功能或具有不使用exec
. 因此沒有特權包裝器。所以現在我的問題是我錯過了什麼,是
capsh
為了什麼。編輯-5
我添加了一個關於環境功能的答案。也許
capsh
也可以與繼承的功能一起使用,但為了有用,需要在執行檔上設置這些功能。如果沒有環境功能或允許繼承功能,我看不出 capsh 如何做任何有用的事情。版本:
capsh
從包libcap2-bin
版本1:2.22-1.2
- 在 edit-3 之前,我從中獲取了最新
capsh
的git://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"
提示:您可以
capsh
並查看其目前功能狀態。注意:
cap_setpcap
需要--addamb
whilecap_setuid,cap_setgid
需要--user
選項。
Lekensteyn 的回答似乎準確而完整,但我會嘗試從不同的角度提供另一種解釋,試圖強調環境功能集解決的問題。
當您執行時,
sudo capsh --user=<some_user> --
有 2 個感興趣的系統呼叫會導致重新計算(並可能丟棄)功能:
setuid
: 根據man capabilities
:SECBIT_KEEP_CAPS 設置此標誌允許具有一個或多個 0 UID 的執行緒在將其所有 UID 切換為非零值時保留其功能。如果未設置此標誌,則此類 UID 切換會導致執行緒失去所有功能。
換句話說,在我們上面的
capsh
命令中,我們需要確保在setuid
系統呼叫期間設置了 SECBIT_KEEP_CAPS。否則,所有功能都將失去。這就是它的--keep=1
作用。所以現在命令變成sudo capsh --user=<some_user> --keep=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
,而不必依賴文件功能。