sudo 的内部结构如何工作?

str*_*gee 83 root sudo privileges

sudo内部如何运作?不像 ,它怎么可能在没有 root 密码的情况下成为 root 用户su?该过程涉及哪些系统调用等?这难道不是 Linux 中一个巨大的安全漏洞(例如,为什么我不能编译一个打了很多补丁的补丁sudo,它只是做了常规操作sudo,但没有要求非特权用户的密码)?

我已阅读login 和 su internals。我还阅读了如何使用 sudo?但尽管标题,他们主要是处理之间的差异susudo

slm*_*slm 83

如果你看一下可执行文件sudo

$ which sudo
/usr/bin/sudo
$ ls -la /usr/bin/sudo
---s--x--x 2 root root 208808 Jun  3  2011 /usr/bin/sudo
Run Code Online (Sandbox Code Playgroud)

您会注意到它带有权限位---s--x--x。这些可以分解如下:

-|--s|--x|--x
-      - first dash denotes if a directory or a file ("d" = dir, "-" = file)  
--s    - only the setuid bit is enabled for user who owns file
--x    - only the group execute bit is enabled
--x    - only the other execute bit is enabled
Run Code Online (Sandbox Code Playgroud)

因此,当一个程序启用了它的 setuid 位(也称为 SUID)时,这意味着当有人运行这个程序时,它将使用拥有该文件的用户的凭据运行,也就是。在这种情况下根。

例子

如果我以用户 saml 身份运行以下命令:

$ whoami
saml

$ sudo su -
[sudo] password for saml: 
Run Code Online (Sandbox Code Playgroud)

您会注意到sudo实际上是以 root 身份运行的:

$ ps -eaf|grep sudo
root     20399  2353  0 05:07 pts/13   00:00:00 sudo su -
Run Code Online (Sandbox Code Playgroud)

setuid 机制

如果您对 SUID 的工作方式感到好奇,请查看man setuid. 这是手册页的摘录,它比我能更好地解释它:

setuid() 设置调用进程的有效用户 ID。如果调用者的有效 UID 为 root,则同时设置真实 UID 和保存的 set-user-ID。在 Linux 下,setuid() 的实现方式与 POSIX 版本类似,具有 _POSIX_SAVED_IDS 功能。这允许 set-user-ID(root 除外)程序放弃其所有用户权限,执行一些非特权工作,然后以安全的方式重新使用原始有效用户 ID。

如果用户是 root 或程序是 set-user-ID-root,则必须特别小心。setuid() 函数检查调用者的有效用户 ID,如果它是超级用户,则所有与进程相关的用户 ID 都设置为 uid。发生这种情况后,程序将无法重新获得 root 权限。

这里的关键概念是程序具有真实的用户 ID (UID) 和有效的用户 ID (EUID)。当该位启用时,Setuid 正在设置有效用户 ID (EUID)。

因此,从内核的角度来看,我们知道在我们的示例中,saml它仍然是原始所有者 (UID),但 EUID 已被设置为可执行文件的所有者。

设置标识符

我还应该提到,当我们分解 sudo 命令的权限时,第二组位用于组权限。组位也有类似于 setuid 的东西,称为 set group id(又名 setgid,SGID)。这与 SUID 的作用相同,只是它使用组凭据而不是所有者凭据运行进程。

参考

  • 你应该使用 `sudo -s` 而不是 `sudo su` 因为它是 `su` 的无用用法。:) (4认同)

Ign*_*ams 5

真正的sudo二进制文件是setuid root,你不能只是将文件以这种方式设置存在。

setuid 和 setgid(分别是“执行时设置用户 ID”和“执行时设置组 ID”的缩写)[1] 是 Unix 访问权限标志,允许用户分别以可执行文件的所有者或组的权限运行可执行文件和改变目录中的行为。


Gre*_*hal 5

为了回答似乎没有人接触过的有关系统调用的部分,重要的系统调用之一是 setresuid() 或 setresgid()。我确信还有其他的,但这两个似乎非常特定于 setuid/sudo。