Linux
通過 exec 傳遞能力
我試圖了解 Linux 功能是如何傳遞給另一個程序
exec()
的。根據我的閱讀,為了在 exec 之後保留功能,它必須位於可繼承集中。不過,我不確定的是該集合是如何填充的。我的目標是能夠以通常需要 root 的普通使用者身份執行程序。它需要的能力是
cap_dac_override
它可以讀取私有文件。我不想給它任何其他功能。這是我的包裝:
#include <unistd.h> int main(int argc, char *argv[]) { return execl("/usr/bin/net", "net", "ads", "dns", "register", "-P", NULL); }
當我在生成的執行檔上設置 setuid 權限時,這有效:
~ $ sudo chown root: ./registerdns ~ $ sudo chmod u+s ./registerdns ~ $ ./registerdns Successfully registered hostname with DNS
不過,我想使用功能而不是 setuid。我嘗試
cap_dac_override
在包裝器上設置功能:~ $ sudo setcap cap_dac_override=eip ./registerdns ~ $ ./registerdns Failed to open /var/lib/samba/private/secrets.tdb ERROR: Unable to open secrets database
我還嘗試在執行檔本身的
cap_dac_override
功能上設置可繼承標誌:net
~ $ sudo setcap cap_dac_override=eip ./registerdns ~ $ sudo setcap cap_dac_override=i /usr/bin/net ~ $ ./registerdns Failed to open /var/lib/samba/private/secrets.tdb ERROR: Unable to open secrets database
我需要使用包裝器來確保該功能僅在使用那組確切的參數時才可用;該
net
程序還做了一些其他的事情,這些事情可能會給使用者過於廣泛的權限帶來危險。我顯然誤解了繼承是如何工作的。我似乎無法弄清楚如何設置包裝器以將其功能傳遞給替換過程,以便它可以使用它們。我已經閱讀了手冊頁,以及無數其他關於它應該如何工作的文件,我認為我正在做它所描述的事情。
事實證明,在包裝器上設置 +i 不會為包裝器程序的集合添加能力
CAP_INHERITABLE
,因此它不會通過exec
.CAP_DAC_OVERRIDE
因此,我必須CAP_INHERITABLE
在呼叫之前手動添加execl
:#include <sys/capability.h> #include <stdio.h> #include <unistd.h> int main(int argc, char **argv[]) { cap_t caps = cap_get_proc(); printf("Capabilities: %s\n", cap_to_text(caps, NULL)); cap_value_t newcaps[1] = { CAP_DAC_OVERRIDE, }; cap_set_flag(caps, CAP_INHERITABLE, 1, newcaps, CAP_SET); cap_set_proc(caps); printf("Capabilities: %s\n", cap_to_text(caps, NULL)); cap_free(caps); return execl("/usr/bin/net", "net", "ads", "dns", "register", "-P", NULL); }
此外,我必須添加
cap_dac_override
到允許的文件功能集上/usr/bin/net
並設置有效位:~ $ sudo setcap cap_dac_override=p ./registerdns ~ $ sudo setcap cap_dac_override=ei /usr/bin/net ~ $ ./registerdns Capabilities = cap_dac_override+p Capabilities = cap_dac_override+ip Successfully registered hostname with DNS
我想我現在完全明白髮生了什麼:
- 包裝器需要
CAP_DAC_OVERRIDE
在其允許的集合中,以便可以將其添加到其可繼承集合中。- wrapper的程序可繼承集與其文件可繼承集不同,所以在文件上設置+i是沒有用的;包裝器必須顯式添加
CAP_DAC_OVERRIDE
到CAP_INHERITABLE
usingcap_set_flag
/cap_set_proc
。- 該
net
文件需要CAP_DAC_OVERRIDE
在其可繼承集中,以便它實際上可以將包裝器的功能繼承到其CAP_PERMITTED
集中。它還需要設置有效位,以便自動提升為CAP_EFFECTIVE
.