Permissions

setuid 不工作

  • February 22, 2020

我試圖了解如何setuid工作。

所以我做了一個虛擬程序,它只列印目前使用者:

#include<bits/stdc++.h>
using namespace std;


int main(){
   cout << system("id -a") << "\n";
   cout << system("whoami")  << "\n";
}

my-binary我在使用者下編譯並創建了執行檔anmol

-rwxrwxr-x 1 anmol anmol 9972 Feb  1 16:54 my-binary

然後,我setuid使用以下方式設置選項chmod +s

-rwsrwsr-x 1 anmol anmol 9972 Feb  1 16:54 my-binary

如果我正常執行它,我會得到以下輸出:

uid=1000(anmol) gid=1000(anmol) groups=1000(anmol),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),116(lpadmin),122(sambashare)
anmol

現在,如果我使用 更改為另一個使用者su user2,然後執行它,我會得到:

uid=1001(user2) gid=1001(user2) groups=1001(user2)
user2

當我使用 執行它時sudo ./my-binary,我得到:

uid=1001(root) gid=1001(root) groups=1001(root)
root

據我了解,無論我如何執行它,我不應該每次都得到第一個輸出嗎?

我在這裡檢查了其他類似的問題,有些人建議我檢查文件系統是否使用nosuid選項掛載,所以我執行mount | /dev/sda1並得到了輸出:

/dev/sda1 on / type ext4 (rw,relatime,errors=remount-ro,data=ordered)

這意味著此選項未啟用。

關於為什麼我沒有得到預期輸出的任何提示?

system(3)函式通過將其傳遞給 來執行它的命令參數/bin/sh -c,並且/bin/shLinux 上的 (或者或bash)放棄任何 setuid 或 setgid 權限,除非使用該選項呼叫。dash``mksh``-p

bash 手冊頁說:

如果 shell 以不等於真實使用者(組) id 的有效使用者(組) id 啟動,並且未提供-p該選項

$$ … $$有效使用者 id 設置為真實使用者 id。

使用dash/bin/sh來自 Debian/Ubuntu),這是一種新的:在 Debian 9 Stretch (2017) 中還沒有這種情況,這只是 Debian 特定的變化,截至 2020 年 2 月仍然沒有在上游中-04。bash自從它的 2.X 版本(第一次包含在 RedHat 7.X,2000 中)以來就已經有了這個。

對於其他 shell(,等)或其他系統(OpenBSD、FreeBSD、Solaris;但不是 NetBSD,它被更改為像 bash 一樣工作)仍然不是這種情況ksh93``zsh``/bin/sh

如果他們有它,他們的特權模式的工作方式與 bash不同:當 shell 在 setuid 模式下執行時,它預設打開,你必須關閉它才能set +p讓 shell 刪除 setuid 權限。


如果您想直接從您的 setuid 二進製文件中使用system()popen()或執行 shell 或可執行 shell 腳本,那麼您應該放棄任何“分裂個性”並通過以下方式完全切換到您的真實或有效憑據setres[ug]id

% cat a.cc
#include <unistd.h>
#include <stdlib.h>
int main(){
   uid_t euid = geteuid();
   setresuid(euid, euid, euid);
   system("id");
}
% c++ a.cc
% chmod u+s a.out
% ./a.out
uid=1002(fabe)
% su -c ./a.out
uid=1002(fabe)

如果您只想檢查您的二進製文件是否真的切換了其有效憑據,請直接進行,而不是通過以下方式呼叫外部程序system()

#include <iostream>
#include <unistd.h>
#include <pwd.h>
using namespace std;
int main(){
   uid_t euid = geteuid(); struct passwd *pw = getpwuid(euid);
   cout << "euid=" << euid;
   if(pw) cout << ", " << pw->pw_name;
   cout << endl;
}

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