我的主目录中有一个脚本。我需要授予其他用户或组权限,以便当他们执行该特定脚本时,它会像我登录并拥有我的 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
。