Why is passing the secrets via environmental variables considered “extremely insecure”?

Passing secrets (password) to a program via environmental variable is considered “extremely insecure” according to MySQL docs and as poor choice (from security aspect) across other resources.

I would like to know why – what is it that I’m missing? In the mentioned MySQL manual(I’m using this as an example), passing password via -p option in command line is considered as “insecure” and via env var as “extremely insecure“, bold italic font.

I’m not an expert but I do know the fundamentals: simple ps command, even issued by unprivileged user reads every program alongside with command parameters while only the same user (and root, of course) may read environment of the process. So, only root and johndoe may read environment of the johndoe – started process, while hacked www-data script reads all via ps.

There must be some big deal here that I’m missing – so please explain me what am I missing?

My objective is to have a mean of transferring secret from one program to other, generally, non-interactive.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

extremely insecure and should not be used. Some versions of ps include an option to display the environment of running processes. On some systems, if you set MYSQL_PWD, your password is exposed to any other user who runs ps.


This was explained here (via):

Background: in the process image argv[] and envp[] are stored in the same way, next to each other. In “classic” UNIXes /usr/bin/ps was typically setgid “kmem” (or similar group), which allowed it to dig around in /dev/kmem to read information about the active processes. This included the ability to read the process arguments AND the environment, of all users on the system.

These days these “privileged ps hacks” are largely behind us: UNIX systems have all come up with different ways of querying such information (/proc on Linux, etc) I think all(?) of these consider a process’s environment only to be readable by its uid. Thus, security-sensitive data like passwords in the environment aren’t leaked.

However, the old ways aren’t 100% dead. Just as an example, here’s an example from an AIX 5.2 machine I have access to, running as a non-root user

[AIX 5.2 reached end-of-life in 2009. AIX, at least by 6100-09, and also confirmed on 7.2, now prevents non-root users from seeing the environment of other users’ processes with the “ps ewwwax” command.]

For the record, some while back we discovered (on IRC?) that OpenBSD 5.2 has this exact security exposure of leaking the environment to other local users (it was fixed shortly after that release, though).

[OpenBSD 5.2 was released in 2012]
This does not explain why the MySQL manual considered that using an environment variable is extremely insecure, compared to a command line argument. See the other answers to this question. In short, either the manual is confused, or the point is that it can be too easy for environment variables to be “leaked” by mistake.

Method 2

This advice in the MySQL documentation is poorly worded.

Passing a password in an environment variable is not less secure than passing it on the command line, on the contrary. Most modern unices expose command line arguments of processes, but not their environment, to all users through the ps command and other similar software. There are exceptions, but I’ve never heard of a system where it is the opposite (exposing the environment without exposing the arguments).

Including a password in a command that is typed in an interactive shell is a bad idea because the password ends up in the shell history. It’s fine if shell history is turned off but you have to remember to do that. This applies whether the password is passed as an argument or in the environment.

What can be more dangerous with environment variables is if the variable is passed to other processes. For example, setting a database password in .profile would be a very bad idea, since it would be visible to all programs. Likewise running a script with export MYSQL_PWD=… near the top that runs many commands beyond mysql would be a bad idea. But if the environment variable is only passed to mysql commands then there’s nothing wrong with that.

The MySQL documentation should not use language that rates passing a password through an environment variable as less secure than passing it through a command line argument. It’s the other way round. (Unless the environment is set for more than the mysql command but that isn’t the scenario described in the documentation.)

Method 3

The main issue with passing secrets in environment variables is to properly scope that environment to the process that use this secret, and to not give it to processes that should not have it.

It is secure to set an environment variable only for starting a given process that uses it.

But it is not secure to set secrets in environment globally in your shell (for the current session) (and even worse in the global startup files of the shell (.bash_profile, .bashrc, .profile)) because all process launched from that shell will have this secret in their environment. Some may leak them, either on purpose (malware) or not (think about the shell command history or a crash reporting module that dumps the full content of the environment in a log file or on a remote server).

Unfortunately from an application developer point of view, it is impossible to enforce that users of your application will properly scope the environment. I have personally seen so many secrets stored in ~/.profile.

So to avoid bad use of the environment by users, it is safer to not load secrets directly in the environment (to reduce the impact of a leak), and instead use environment variables to pass links to where the secret is really stored: use an additional layer of indirection.

Method 4

Please, think about this scenario:

  • You build a php/ruby/whatever + mysql app.
  • I manage to make your app/server yield an error 500. Some configs will yield ENV to my browser as well as any sort of stack trace.
  • I use the mysql or smtp secrets for fun and profits.

Think about this one too:

  • You fail to properly configure your apache/nginx folders and I manage to get access tho the .env file itself
  • Again, I use the mysql or smtp secrets for fun and profits.

Bottom line: use a secret provider (they are easy to use and not so expensive), but if you cannot afford that, ensure that maximum security is properly set in other aspects of your setup, like webserver’s public disclosure of .env files or env vars.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x