53

Perhaps this is a trivial question, but how accessible are environment variables in Linux between different users?

e.g. if Alice executes

export FAVORITE_FOOD=`cat /home/alice/fav_food.txt`

Can Eve tell what's Alice's favourite food? (Assuming both Alice and Eve are normal users, and Eve doesn't have read access to /home/alice/fav_food.txt)

edwinksl
  • 109
  • 6
Yoav Aner
  • 5,299
  • 3
  • 24
  • 37

5 Answers5

90

Let's trace the flow of the confidential data. In this analysis, it is understood that anything Alice can do, root can also do. Also an external observer “one level up” (e.g. with physical access to snoop on the disk bus, or in the hypervisor if the code is running in the virtual machine) might be able to access the data.

First, the data is loaded from a file. Assuming that only Alice has read permission on the file and the file is not otherwise leaked, only Alice can call cat /home/alice/fav_food.txt successfully. The data is then in the memory of the cat process, where only that process can access it. The data is transmitted over a pipe from the cat command to the calling shell; only the two processes involved can see the data on the pipe. The data is then in the memory of the shell process, again private to that process.

At some point, the data will end up in the shell's environment. Depending on the shell, this may happen when the export statement is executed, or only when the shell executes an external program. At this point, the data will be an argument of an execve system call. After that call, the data will be in the environment of the child process.

The environment of a process is just as private as the rest of that process's memory (from mm->env_start to mm->env_end in the process's memory map). It's contiguous with the initial thread's stack. However, there is a special mechanism that allows other processes to view a copy of the environment: the environ file in the process's /proc directory (/proc/$pid/environ). This file is only readable by its owner, who is the user running the process (for a privileged process, that's the effective UID). (Note that the command line arguments in /proc/$pid/cmdline, on the other hand, are readable by all.) You can audit the kernel source to verify that this is the only way to leak the environment of a process.

There is another potential source for leaking the environment: during the execve call. The execve system call does not directly leak the environment. However, there is a generic audit mechanism that can log the arguments of every system call, including execve. So if auditing is enabled, the environment can be sent through the audit mechanism and end up in a log file. On a decently configured system, only the administrator has access to the log file (on my default Debian installation, it's /var/log/audit/audit.log, only readable by root, and written to by the auditd daemon running as root).

I lied above: I wrote that the memory of a process cannot be read by another process. This is in fact not true: like all unices, Linux implements the ptrace system call. This system call allows a process to inspect the memory and even execute code in the context of another process. It's what allows debuggers to exist. Only Alice can trace Alice's processes. Furthermore, if a process is privileged (setuid or setgid), only root can trace it.

Conclusion: the environment of a process is only available to the user (euid) running the process.

Note that I assume that there is no other process that might leak the data. There is no setuid root program on a normal Linux installation that might expose a process's environment. (On some older unices, ps was a setuid root program that parsed some kernel memory; some variants would happily display a process's environment to any and all. On Linux, ps is unprivileged and gets its data from /proc like everyone else.).

(Note that this applies to reasonably current versions of Linux. A very long time ago, I think in the 1.x kernel days, the environment was world-readable.)

Gilles 'SO- stop being evil'
  • 50,912
  • 13
  • 120
  • 179
  • 4
    Great answer Gilles! Much more comprehensive and detailed than I expected. Good to know there's quite some safety in environment variables and how (at least modern) linux segregates access between accounts. – Yoav Aner Apr 21 '12 at 09:22
  • I'd like to add the command I use on Linux to view another process' environment (as root or same user): xargs -0 -n1 < /proc//environ I find it useful for debugging. – feitingen Jun 21 '17 at 14:52
5

I was initially going to say "no". Environment variable values are per user and no other user can read or write to another user's env. vars. However, there is an interesting tidbit over on SO that indicates that root is able to at least read this information via /proc/<pid>/environ. I was not aware of this Linux-specific interface until now.

https://stackoverflow.com/a/532284/643314

With that said, it looks like this interface is still unreadable to other users, even if they are in the same groups. The permissions are set to 400 for the environ file and /proc prevents chmod from affecting it. I suspect that the security domain for environment variable separation across users is still intact and cannot be bypassed through normal means.

logicalscope
  • 6,344
  • 3
  • 25
  • 38
  • 1
    While the details are specific to Linux, many unix variants have a `/proc` filesystem that exposes information about a process, possibly including the environment. Where it doesn't exist, there has to be some way (e.g. a system call) for `ps` and similar commands to work. There are (or at least were) even unix variants where `ps` is a setuid root program that reads kernel memory directly. – Gilles 'SO- stop being evil' Apr 20 '12 at 22:25
  • Thanks @logicalscope. Great answer. I would have happily accepted it, but Gilles provided a much more comprehensive and detailed explanation that I simply have to choose his. +1 from me though! – Yoav Aner Apr 21 '12 at 09:21
  • /dev/mem and /dev/kmem both give direct access to memory which would allow reading environment variables (and pretty much anything else). These are also supported on other UNIX variants - https://www.freebsd.org/cgi/man.cgi?query=mem&sektion=4&apropos=0&manpath=FreeBSD+9.1-RELEASE – Michael Aug 01 '19 at 16:19
3

Despite Gilles' theoretically correct answer: I would not put secrets into environment variables.

  • Environment variables are usually defined near the top of the process tree (e.g. through $HOME/.profile).
  • Users do not treat the contents of the environment as secrets.

It's sufficient that a single process logs the environment variables to a world-readable file: env >> env-traces.txt or similar. You cannot control it.

slowhand
  • 131
  • 2
  • 4
    It would be unusual to put confidential data in `.profile`. Usually, confidential data is put in the environment by a program that wants to pass data to a specific subprocess, as an alternative to using command line arguments (which are usually visible to other users). – Gilles 'SO- stop being evil' Apr 30 '14 at 07:36
  • 1
    I'd argue that the paths to specific ssh keys added to ssh-agent and similar things are borderline-confidential, and those go in .profile all the time. I also have some DB2 admins who really like to put connection passwords in their .profile (actually a shared "database admin" account's .profile), but hopefully that's not common at all. :/ – dannysauer Jan 30 '15 at 17:05
0

if there's no strict policies, THEORETICALLY there's a way if this export is made in a bash-login user script for Alice : Eve creates a script to print env and sets SETUIDGID bits in chmod and then chown's it to Alice, then executes. The script will be executed under Alice's uid and it's bash autorun will be Alice's one. Then it leaks out the data via stdout =) But there must be a very weak system setup to perform such a tricks. I saw such an awfully-configurated boxes in my forensics practice, so it's not a joke.

Alexey Vesnin
  • 1,565
  • 1
  • 8
  • 11
  • For Eve to `chown` her hostile script with the SUID flag set she needs root permissions, which would not require this detour in the first place. – Nils Magnus May 10 '21 at 13:42
0

In most cases another user cannot read your environment variables. However, the well known security hole that an instance of a setuid program runs as the same user as any other instance of a setuid program can be exploited. This means that if someone runs a setuid program and someone else can exploit another program that is setuid to the same user to read from /proc/<pid>/environ then they can read the program's environment variables. This is one reason why you should use a new user for any daemon you write instead of abusing the nobody user.