如何允许用户执行脚本而不泄露受保护的信息

如何允许用户执行脚本而不泄露受保护的信息

假设 root 用户在环境变量中设置了一些凭据(例如,API 密钥),并且给定一个非特权用户 John,我怎样才能让 John 执行一个脚本,该脚本用途所述 API 密钥而不会有将其值泄露给 John 的风险?

答案1

问题好像有点不着重点。

  • 问题是,本身, 谈到从“超级用户环境变量”(即“根环境变量”)获取值。我甚至不确定这是什么意思。您是说 John 应该从以“root”身份登录或以“root”身份通过或运行的(另一个)用户的环境中获取值吗susudo或者您是在谈论过程 (可能是后台进程)以“root”身份运行?

    但是,无论你脑子里想的是什么细节,这听起来像是关键的动态和短暂。由于我不明白这意味着什么,我不会说这是不可能的,但这听起来很难。

  • 但是随后在评论中您谈到使脚本可执行但不可读。这表明您愿意将密钥硬编码到脚本中,只要非 root 用户无法读取它。这表明密钥非常静态,很少更改,因此您愿意每次密钥更改时都修改脚本。

    上层与下层关于这个话题有一个很长的帖子: 脚本是否可以执行但不可读?  遗憾的是,大多数答案都是否定的,或者是转移话题、转移注意力或变通方法,其中一些方法比其他方法更有效。例如,桑塔纳建议创建一个条目,/etc/sudoers 允许 John跑步以提升的权限运行脚本,但无法以自己的身份读取它。但是,如果脚本不需要提升权限(除了获取密钥之外),您就不想以提升的权限运行它。

    然而,这个相关问题(超级用户),我介绍了一种笨拙的方法,即通过将其包装在 C 程序中来使脚本可执行但不可读。正如我在该答案中解释的那样,这种技术并非万无一失;信息可能会通过多种方式泄露。

  • 在我看来,最合理/最可信的解释是密钥保存在 John 无法读取的文件中。实现此类安排的传统方式是 setUID 和/或 setGID。(sudo也很有用。)

下面是一个如何实现的示例。编写如下 C 程序:

#包括 <stdio.h>
#包括 <stdlib.h>

#定义密钥文件        (适当的路径名)
#定义脚本          (适当的路径名)

主要的()
{
        文件*key_fp;
        字符键[80];        (酌情调整)
        gid_t gid;
        uid_t uid;
        字符 *args[10];      (酌情调整)

        key_fp = fopen(KEY_FILE,“r”);
        如果 (key_fp == NULL)
        {
                错误信息(KEY_FILE);
                退出(1);
        }
        (您要阅读并验证的代码)钥匙
        fclose(key_fp);
        如果(setenv(“KEY”,键,1)!= 0)
        {
                fprintf(stderr, "setenv() 存在问题.\n");
                退出(1);
        }
        gid = 获取gid();
        uid = 获取uid();
        // 使用
        // 如果 (setresgid(gid,gid,gid) != 0 || setresuid(uid,uid,uid) != 0)
        // 如果可用;否则
        如果 (setregid (gid,gid) != 0 || setreuid (uid,uid) != 0)
        {
                fprintf(stderr, "删除权限时出现问题。\n");
                退出(1);
        }
        args[0] = "脚本名称";     (酌情调整)
        args[1] = 空;
        execv(脚本,参数);
        错误(脚本);
        退出(1);
}

定义KEY_FILE包含密钥的文件的完整路径名,并定义SCRIPT包含脚本的文件的完整路径名。确保 John 具有脚本的读取权限,但没有密钥文件的读取权限,并且他没有对任何路径中的任何目录的写入权限。通过设置此程序的 setUID 和/或 setGID,使其能够读取密钥文件。它将读取密钥,将其插入环境,放弃权限,然后执行脚本。(您可能需要修改上述代码,以便将提供给程序的命令行参数传递给脚本。)

如上所述,脚本将使用 John 的 UID 和 GID 运行,但密钥在环境中。在某些系统上,John 可能能够从或 使用读取脚本的环境。如果是这样,让脚本立即将密钥复制到本地(非导出)变量并取消设置该变量可能会有所帮助。/proc/(pid_of_script)/environpsKEY

脚本将密钥传递给程序可能是安全的

  • 通过管道(例如),printf "%s" (key_value) | (program)
  • 通过此处的文档,或
  • 通过此处的字符串。

上面提到了通过环境传递值的风险。避免将其作为命令行参数传递,因为这肯定可以被看到ps

如果您想使程序通过 运行sudo,您可能需要对 John 的 UID 和 GID 进行硬编码,因为sudo设置了真实 ID 和有效 ID。

相关内容