sudo 如何工作(除了 setuid)?

Bil*_*lly 6 setuid sudo shell-script

sudo启动时被提升为 root,因为它的二进制文件已setuid启用。但是,当我赋予/bin/login确切的权限时sudo,并尝试从非 root 用户运行它时,出现错误:

No utmp entry.  You must exec "login" from the lowest level "sh"
Run Code Online (Sandbox Code Playgroud)

我的第一个问题是,这个错误是什么意思?我的第二个是,为什么当我sudo login从同一个用户运行时它会起作用?除了使用asetuuid提升到root之外,还有什么sudo工作?我写了一个简单的dash脚本~/root来运行whoami和退出,但它返回我的非特权用户的用户名。

$ ls -l ./root /usr/bin/sudo
-rwsr-xr-x 1 root root     29 Jul 15 02:40 ./root
-rwsr-xr-x 1 root root 157760 Jan 10  2016 /usr/bin/sudo

$ ./root
unprivileged user
Run Code Online (Sandbox Code Playgroud)

所以我有三个问题:

  1. 我得到的错误是什么login
  2. 为什么loginsudo?
  3. 为什么我要运行的简单脚本whoami不起作用?

cha*_*aos 6

我得到的错误是什么login

在搜索 的源代码时login,我们看到了这样一段话:

amroot = (getuid () == 0);
[...]
utent = get_current_utmp ();
/*
 * Be picky if run by normal users (possible if installed setuid
 * root), but not if run by root. This way it still allows logins
 * even if your getty is broken, or if something corrupts utmp,
 * but users must "exec login" which will use the existing utmp
 * entry (will not overwrite remote hostname).  --marekm
 */
if (!amroot && (NULL == utent)) {
     (void) puts (_("No utmp entry.  You must exec \"login\" from the lowest level \"sh\""));
     exit (1);
}
Run Code Online (Sandbox Code Playgroud)

有趣的部分是最后的 if 子句。getuid()如果不为 0 且没有 utmp 条目,则会出现错误消息。getuid()返回调用进程的真实用户 ID。如果login在设置了 setuid 标志的情况下调用,则实际 uid 和有效 uid 不同。login正如源代码片段中的评论所暗示的那样,在这种情况下是“挑剔的”:它失败并抛出提到的错误。


为什么loginsudo?

sudo本身设置了 setuid 位,因此 euid 和 ruid 不同。但是,sudo 执行二进制文件login并将真实和有效 uid 设置为目标用户。因此它不会再失败了。


为什么我要运行的简单脚本whoami不起作用?

您的脚本中有一条 shebang 行 ( #!)(我假设)。会发生以下情况:内核打开可执行文件(在您的情况下为文本文件)并观察#!. 代替文本文件,shebang 行中给出的解释器被调用(例如/bin/bash/bin/sh),并将脚本名称作为第一个参数。大多数 unix 和 linux 操作系统在脚本上设置时都会忽略 setuid 位,因为这是一个安全问题。

想象一个设置了 setuid 的脚本。然后,攻击者可以创建指向该脚本的符号链接,调用该脚本,然后在解释器打开符号链接后面的脚本(当时是邪恶的)之前,将符号链接更改为他的脚本。