也许这是一个微不足道的问题,但 Linux 中的环境变量在不同用户之间的可访问性如何?
例如,如果 Alice 执行
export FAVORITE_FOOD=`cat /home/alice/fav_food.txt`
夏娃能说出爱丽丝最喜欢的食物是什么吗?(假设 Alice 和 Eve 都是普通用户,并且 Eve 没有读取权限/home/alice/fav_food.txt
)
也许这是一个微不足道的问题,但 Linux 中的环境变量在不同用户之间的可访问性如何?
例如,如果 Alice 执行
export FAVORITE_FOOD=`cat /home/alice/fav_food.txt`
夏娃能说出爱丽丝最喜欢的食物是什么吗?(假设 Alice 和 Eve 都是普通用户,并且 Eve 没有读取权限/home/alice/fav_food.txt
)
让我们追踪机密数据的流向。在这个分析中,可以理解 Alice 可以做的任何事情,root 也可以做。此外,“上一层”的外部观察者(例如,物理访问磁盘总线上的窥探,或者如果代码在虚拟机中运行,则在管理程序中)可能能够访问数据。
首先,从文件中加载数据。假设只有 Alice 对该文件有读取权限,并且文件没有被泄露,那么只有 Alice 可以调用cat /home/alice/fav_food.txt
成功。然后数据在cat
进程的内存中,只有该进程可以访问它。数据通过管道从cat
命令传输到调用 shell;只有涉及的两个进程才能看到管道上的数据。然后数据在 shell 进程的内存中,同样是该进程私有的。
在某些时候,数据最终会进入 shell 的环境。根据 shell 的不同,这可能会在export
执行语句时发生,或者仅在 shell 执行外部程序时发生。此时,数据将成为execve
系统调用的参数。在那次调用之后,数据将在子进程的环境中。
进程的环境与该进程的其余内存一样私有(进程的内存映射中的 frommm->env_start
到mm->env_end
)。它与初始线程的堆栈连续。但是,有一种特殊的机制允许其他进程查看环境的副本:environ
进程/proc
目录中的文件( /proc/$pid/environ
)。该文件只能由其所有者读取,该所有者是运行该进程的用户(对于特权进程,这是有效的 UID)。(请注意,/proc/$pid/cmdline
另一方面,命令行参数是所有人都可以读取的。)您可以审核内核源代码以验证这是泄漏进程环境的唯一方法。
泄漏环境的另一个潜在来源是:在execve
通话期间。系统execve
调用不直接泄漏环境。但是,有一个通用的审计机制可以记录每个系统调用的参数,包括execve
. 因此,如果启用了审计,则可以通过审计机制发送环境并最终保存在日志文件中。在配置得当的系统上,只有管理员可以访问日志文件(在我的默认 Debian 安装中,它是/var/log/audit/audit.log
,只能由 root 读取,并由以 rootauditd
身份运行的守护进程写入)。
我在上面撒了谎:我写了一个进程的内存不能被另一个进程读取。事实上这不是真的:像所有的 unice 一样,Linux 实现了ptrace
系统调用。这个系统调用允许一个进程检查内存,甚至在另一个进程的上下文中执行代码。这就是允许调试器存在的原因。只有 Alice 可以追踪 Alice 的流程。此外,如果进程具有特权(setuid 或 setgid),则只有 root 可以跟踪它。
结论:一个进程的环境只对运行该进程的用户(euid)可用。
请注意,我假设没有其他可能泄漏数据的进程。在正常的 Linux 安装中没有可能暴露进程环境的 setuid root 程序。(在一些较旧的 unice 上,ps
是一个解析一些内核内存的 setuid root 程序;一些变体会很高兴地向任何人和所有人显示一个进程的环境。在 Linux 上,ps
它是无特权的,并且/proc
像其他人一样从它那里获取数据。)。
(请注意,这适用于当前合理的 Linux 版本。很久以前,我认为在 1.x 内核时代,环境是世界可读的。)
我最初打算说“不”。环境变量值是每个用户的,其他用户不能读取或写入其他用户的环境。瓦尔斯。但是,在 SO 上有一个有趣的花絮,表明 root 至少能够通过/proc/<pid>/environ
. 直到现在我才知道这个 Linux 特定的界面。
https://stackoverflow.com/a/532284/643314
话虽如此,看起来这个界面对于其他用户来说仍然是不可读的,即使他们在同一个组中。environ 文件的权限设置为 400,并且 /proc 防止 chmod 影响它。我怀疑跨用户的环境变量分离的安全域仍然完好无损,无法通过正常方式绕过。
尽管 Gilles 给出了理论上正确的答案:我不会将秘密放入环境变量中。
$HOME/.profile
)。单个进程将环境变量记录到世界可读文件中就足够了:env >> env-traces.txt
或类似文件。你无法控制它。
在大多数情况下,其他用户无法读取您的环境变量。然而,众所周知的安全漏洞是 setuid 程序的一个实例与 setuid 程序的任何其他实例以相同的用户身份运行,这一漏洞可以被利用。这意味着如果有人运行一个 setuid 程序,而其他人可以利用另一个对同一用户设置 setuid 的程序进行读取,/proc/<pid>/environ
那么他们可以读取该程序的环境变量。这就是为什么您应该为您编写的任何守护程序使用新用户而不是滥用nobody 用户的原因之一。