Anm*_*ggi 1 filesystems users setuid permissions
我试图了解如何setuid
工作。
所以我做了一个虚拟程序,它只打印当前用户:
#include<bits/stdc++.h>
using namespace std;
int main(){
cout << system("id -a") << "\n";
cout << system("whoami") << "\n";
}
Run Code Online (Sandbox Code Playgroud)
我my-binary
在用户下编译并创建了可执行文件anmol
:
-rwxrwxr-x 1 anmol anmol 9972 Feb 1 16:54 my-binary
Run Code Online (Sandbox Code Playgroud)
然后,我setuid
使用chmod +s
以下选项设置选项:
-rwsrwsr-x 1 anmol anmol 9972 Feb 1 16:54 my-binary
Run Code Online (Sandbox Code Playgroud)
如果我正常执行它,我会得到以下输出:
uid=1000(anmol) gid=1000(anmol) groups=1000(anmol),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),116(lpadmin),122(sambashare)
anmol
Run Code Online (Sandbox Code Playgroud)
现在,如果我使用 更改为另一个用户su user2
,然后执行它,我会得到:
uid=1001(user2) gid=1001(user2) groups=1001(user2)
user2
Run Code Online (Sandbox Code Playgroud)
当我使用 执行它时sudo ./my-binary
,我得到:
uid=1001(root) gid=1001(root) groups=1001(root)
root
Run Code Online (Sandbox Code Playgroud)
据我了解,无论我如何运行它,我不应该每次都得到第一个输出吗?
我在这里检查了其他类似的问题,有些人建议我检查文件系统是否使用nosuid
选项挂载,所以我执行mount | /dev/sda1
并得到了输出:
/dev/sda1 on / type ext4 (rw,relatime,errors=remount-ro,data=ordered)
Run Code Online (Sandbox Code Playgroud)
这意味着未启用此选项。
关于为什么我没有得到预期输出的任何提示?
小智 6
该system(3)
库函数将其传递到运行其命令参数/bin/sh -c
,而/bin/sh
在Linux(或bash
,dash
或mksh
)放弃任何setuid或setgid特权,除非调用的-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 年)以来就有此功能。
这是还没有的情况下与其他炮弹(ksh93
,zsh
,等),或者与/bin/sh
其他系统(OpenBSD的,FreeBSD的,的Solaris;它被而不是NetBSD的改变工作诸如bash)。
如果他们有它,他们的特权模式下工作不同比在bash:它原来在当外壳在setuid的方式运行在默认情况下,你必须把它关闭与set +p
以有壳下降了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)
Run Code Online (Sandbox Code Playgroud)
如果您只想检查您的二进制文件是否真的切换了其有效凭据,请直接执行此操作,而不是通过以下方式调用外部程序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;
}
Run Code Online (Sandbox Code Playgroud)