Linux

setuid root 不起作用

  • June 8, 2017

目標:以 root 身份執行程序(C++ 二進製文件)。同:SetUID 位在 Ubuntu 中不起作用?

並且:為什麼 setuid 不適用於執行檔?

./a.out 輸出:

E: Could not open lock file /var/lib/dpkg/lock - open (13: Permission denied) E: Unable to lock the administration directory (/var/lib/dpkg/), are you root? psurana //output for "whoami" Look below for the code.

ls -l 輸出:

-rwsrwxr-x 1 root root 46136 Jun 7 20:13 a.out

編碼 :

#include <string>
#include <stdlib.h>
int main(int argc, char *argv[]){
       std::string input = "apt-get install " + std::string(argv[1]);
       system(input.c_str());
       system("whoami");
       return 0;
}

詳情: : 編譯程序然後做了chown root:root a.out && chmod u+s a.out。請在上面查看 ls -l 輸出。

我仍然沒有獲得 root 權限,並且程式碼中 system(“whoami”) 的輸出是我自己在機器上的使用者名。

閱讀這兩個相關的問題並沒有讓我有所收穫。:(。文件的創建者和所有者都是 root。setuid 位已設置,所以它應該可以工作。文件系統也不是外部的,它是我自己的機器。我怎樣才能使它工作?

如果您像這樣更改程式碼,您可以看到有效和真實的 UID:

#include <string>
#include <stdlib.h>
int main(int argc, char *argv[]){
       system("id");
       system("bash -c id");
       return 0;
}

在我的系統上,這將返回這兩行(我用 … 跳過不相關的組):

uid=1001(roaima) gid=1001(roaima) euid=0(root) groups=1001(roaima),24(cdrom),...,103(vboxsf)
uid=1001(roaima) gid=1001(roaima) groups=1001(roaima),24(cdrom),...,103(vboxsf)

如您所見,原始呼叫id返回的有效 UID 為 0(根),但真實 UID 仍然是我自己的。這是你所期望的。

但是,您可以看到該bash -c id呼叫已將有效 UID 剝離,因此它不再以 root 身份執行。這記錄man bash如下:

如果 shell 以不等於實際使用者(組) id 的有效使用者(組) id 啟動,並且-p未提供該選項,則不讀取啟動文件,不從環境繼承 shell 函式,則SHELLOPTS, BASHOPTS, CDPATH,和GLOBIGNORE變數,如果它們出現在環境中,將被忽略,有效使用者 id 設置為真實使用者 id。如果-p在呼叫時提供了該選項,則啟動行為是相同的,但不會重置有效使用者 ID。

所以這裡的解決方案應該是包含-p標誌。

(您可以了解bash在 Setuid 位重置其 UID似乎對 bash 沒有影響的過程。)

但是,故事到這裡還沒有結束,因為我知道你會說你沒有呼叫bash. 對您來說不幸的是,這幾乎是system()代表您所做的,並且不允許您指定-p.

strace丟棄 root 權限,但這裡的strace -f ./a.out輸出足以讓您了解發生了什麼:

execve("./a.out", ["./a.out"], [/* 44 vars */]) = 0
brk(0)                                  = 0x24f1000
...
clone(child_stack=0, flags=CLONE_PARENT_SETTID|SIGCHLD, parent_tidptr=0x7ffee0d42a1c) = 4619
wait4(4619, Process 4619 attached
<unfinished ...>

此時子程序啟動,準備執行我們的id

[pid  4619] rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f100eb270e0}, NULL, 8) = 0
[pid  4619] rt_sigaction(SIGQUIT, {SIG_DFL, [], SA_RESTORER, 0x7f100eb270e0}, NULL, 8) = 0
[pid  4619] rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
[pid  4619] execve("/bin/sh", ["sh", "-c", "id"], [/* 44 vars */]) = 0
[pid  4619] brk(0)                      = 0x7f849dd71000
[pid  4619] brk(0)                      = 0x7f849dd71000
...
[pid  4619] clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f849d1d89d0) = 4620

現在我們執行了一個 shell,它會丟棄我們的有效 UID。接下來,您將看到它啟動id命令並將其輸出寫入標準輸出

Process 4620 attached
[pid  4619] wait4(-1,  <unfinished ...>
[pid  4620] execve("/usr/bin/id", ["id"], [/* 44 vars */]) = 0
[pid  4620] brk(0)                      = 0x1785000
...
[pid  4620] write(1, "uid=1001(roaima) gid=1001(roaim"..., 149) = 149
uid=1001(roaima) gid=1001(roaima) groups=1001(roaima),24(cdrom),...,103(vboxsf)
...

您在這裡的解決方案將是exec*()直接使用其中一個系列,或者包括對 的呼叫setuid(0),或者配置一個工具,例如sudo允許您直接呼叫您的目標程序並且(可能)沒有密碼。

在這些選項中,我個人會選擇sudo解決方案。其作者花了很長時間確保程式碼可以安全地抵禦(非)有意升級的特權攻擊。

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