允许其他用户以我的 ID 身份运行特定脚本

允许其他用户以我的 ID 身份运行特定脚本

我的主目录中有一个脚本。我需要授予其他用户或组权限,以便当他们执行该特定脚本时,它会像我登录并拥有我的 ID 拥有的所有权限一样执行。我不想使用 sudo 或 su 并将它们设置为 sudoers 或输入密码。

答案1

使用 sudo,您可以非常细化您的权限。如果您想授予用户仅运行您的脚本而不执行其他任何操作的权限,您可以将此行添加到您的 /etc/sudoers 中:

user ALL=(yourusername) NOPASSWD: /path/to/your/script

然后,作为其他用途,您将运行:

sudo -u yourusername /path/to/your/script

答案2

使用须藤是最简单的方法。但确实需要系统管理员的配合才能设置。

如果您想在没有特殊权限的情况下执行此操作,您可以使用设置用户标识可执行文件,但您需要小心,不要允许调用者执行超出您预期的操作。

大多数 Unix 变体禁止 setuid shell 脚本;例如,在 Linux 上,内核总是忽略脚本上的 setuid 位。所以你需要一个本机代码的包装器。

请注意,包装器会删除所有可能允许用户调用它来运行代码的内容。例如,白名单环境变量;任何不知道安全的东西(例如TERM)都必须离开。

这是一个仅保留环境变量的 setuid 包装器的提案TERM。请注意,我还没有审查过它或真正测试过它;欢迎反馈。

/* Compilation command:
   c99 -DTARGET='"/absolute/path/to/script"' -o setuid-wrapper setuid-wrapper.c
 */

#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

void die(const char *argv0, const char *obj, const char *msg) {
    if (msg == NULL) msg = strerror(errno);
    fprintf(stderr, "%s: %s: %s\n", argv0, obj, msg);
    exit(127);
}

int env_want(const char *entry) {
    size_t n;
    for (n = 0; entry[n]; n++) {
        if (entry[n] == '=') {
            break;
        } else if (!(isalnum(entry[n]) || entry[n] == '_')) {
            return 0;
        }
    }
    if ((n == 7 && !strncmp(entry, "DISPLAY", n)) ||
        (n == 10 && !strncmp(entry, "XAUTHORITY", n))) {
        return 1;
    }
    if ((n == 4 && !strncmp(entry, "LANG", n)) ||
        (n >= 3 && !strncmp(entry, "LC_", 3)) ||
        (n == 2 && !strncmp(entry, "TZ", n))) {
        return !strpbrk(entry, "/%");
    }
    return 0;
}

int main(int argc, char *argv[], char **environ) {
    size_t i, j;
    const char *program_name = argv[0];
    if (program_name == NULL) program_name = "setuid-wrapper";
    /* Drop privileges */
    if (setgid(getegid())) die(program_name, "setgid", NULL);
    /*if (setgroups(0, NULL)) die(program_name, "setgroups", NULL);*/
    if (setuid(geteuid())) die(program_name, "setuid", NULL);
    /* Sanitize the environment */
    for (i = j = 0; environ[i]; i++) {
        if (env_want(environ[i])) {
            environ[j] = environ[i];
            j++;
        }
    }
    environ[j] = NULL;
    /* Execute the command */
    execle(TARGET, TARGET, NULL, environ);
    die(program_name, TARGET, NULL);
}

请注意,目标程序将与调用者的补充组一起运行,因为如果不是 root,则无法删除补充组。

另一种方法是运行服务器(例如 Web 服务器)并从该服务器调用脚本。有很多支持 CGI 脚本的小型 HTTP 服务器。这种方法的主要优点是更容易保护,因为服务器在目标(代码运行的安全上下文中的一方)选择的上下文中运行,而不是由客户端选择。

这种方法的一个变体是通过保险丝文件系统。例如,安装一个脚本文件系统包含带有allow_other挂载选项的脚本的目录。这需要user_allow_other在 中设置该选项/etc/fuse.conf

相关内容