如何在Linux中使用密码验证以root身份使用C或C++运行命令而不使用pam

xqk2d5yq  于 2023-06-21  发布在  Linux
关注(0)|答案(1)|浏览(123)

TL;DR例如su或sudo如何在没有PAM的情况下工作?
你好
我想玩一下suid之类的东西,我已经得到了SUID部分和SUID位之类的东西,但问题是它没有问我密码,因为我想让它问密码,发现su和sudo在源代码中相当混乱,我很困惑。
我查看了setsuid()和getuid()文档,似乎没有任何关于密码验证的内容。
如何在没有PAM的情况下实现密码身份验证,我使用没有PAM的sudo,它工作正常,su和pam,两者都工作正常,我很困惑如何使它工作
这段C++代码就是我现在所拥有的:

// a.cc //

#include <iostream>
#include <unistd.h>
#include <cerrno>
#include <cstring>

int main(int argc, char *argv[]) {
    uid_t user = getuid();
    if (setuid(0) == -1) {
        std::cerr << strerror(errno) << '\n';
        return 1;
    }

    system(argv[1]);

    if (setuid(user) == -1) {
        std::cerr << errno << '\n';
        return 1;
    }
    return 0;
}

并且在用例如GCC编译它并且文件被命名为www.example.com之后a.cc:

$ g++ a.cc -o a

并赋予它执行和SUID权限,并将所有权授予root

$ sudo chown root:root ./a
$ sudo chmod 4555 ./a

它只是工作,但没有密码认证

$ ./a id

uid=0(root) gid=1000(ari) groups=1000(ari),5(tty),10(wheel),27(video),78(kvm),250(portage)

(ari是我的用户)
即使在注销或运行sudo -k以结束sudo超时之后,它仍然可以在没有密码认证的情况下工作。

谢谢提前回答

zbdgwd5y

zbdgwd5y1#

首先,基础知识:每个进程都有一个userid和一个groupid(我将忽略附加的groupid等补充属性)。
用户ID 0是root。就这样,故事结束。
如果你有一个进程的userid是0,那么它就是一个根进程。故事结束了
一个进程如何获得它的userid0是无关紧要的。如果一个进程的userid为0,那么它就是一个根进程,仅此而已。
当您完成设置setuid进程的动作时,setuid(0)本身就完成了。你是根进程。就这样。没什么好说的了。
setsuid()和getuid()文档,似乎没有任何关于密码验证的内容。
正确。他们所做的就是调整/更新用户ID。就这样。没什么了。
susudo进程执行以下操作:
1.它们是setuid可执行文件。

$ ls -al /bin/su /bin/sudo
-rwsr-xr-x. 1 root root  57504 Aug 17 04:59 /bin/su
---s--x--x. 1 root root 185440 Aug  7 13:17 /bin/sudo

你觉得这个眼熟吗?您手工创建的setuid程序的权限看起来与此相同,不是吗?
1.但在进一步操作之前,他们要求您提供一个可接受的密码(或者以某种形式或方式满足其他一些标准,可接受的身份验证标准的确切细节是什么并不重要,在su的情况下是密码,或者在sudo的配置中是可接受的匹配)。如果你不这样做,他们终止与没有进一步的行动发生。
所有的密码验证逻辑,包括PAM或其他一些身份验证框架,都是由susudo进程本身实现的。除非您提供可接受的身份验证凭据(无论对于susudo意味着什么),否则它们将终止,并且不会发生进一步的操作。一个成功的身份验证会导致一个shell,或者一个执行的命令,但这是因为一个非常简单的,基本的原因,susudo程序本身使用setuid(权限位和系统调用)来获得root权限,这是第一要务。

相关问题