Is it secure to store passwords as environment variables (rather than as plain text) in config files?

97,361

Solution 1

On a more theoretical level, I tend to think about levels for security in the following ways (in order of increasing strength) :

  • No security. Plain text. Anyone that knows where to look, can access the data.
  • Security by Obfuscation. You store the data (plaintext) someplace tricky, like an environment variable, or in a file that is meant to look like a configuration file. An attacker will eventually figure out what's going on, or stumble across it.
  • Security provided by encryption that is trivial to break, (think caesar cipher!).
  • Security provided by encryption that can be broken with some effort.
  • Security provided by encryption that is impractical to break given current hardware.
  • The most secure system is one that nobody can use! :)

Environment variables are more secure than plaintext files, because they are volatile/disposable, not saved; i.e. if you set only a local environment variable, like "set pwd=whatever," and then run the script, with something that exits your command shell at the end of the script, then the variable no longer exists. Your case falls into the first two, which I'd say is fairly insecure. If you were going to do this, I wouldn't recommend deploying outside your immediate intranet/home network, and then only for testing purposes.

Solution 2

As mentioned before, both methods do not provide any layer of additional "security" once your system is compromised. I believe that one of the strongest reasons to favor environment variables is version control: I've seen way too many database configurations etc. being accidentially stored in the version control system like GIT for every other developer to see (and whoops! it happened to me as well ...).

Not storing your passwords in files makes it impossible for them to be stored in the version control system.

Solution 3

Anytime you have to store a password, it is insecure. Period. There's no way to store an un-encrypted password securely. Now which of environment variables vs. config files is more "secure" is perhaps debatable. IMHO, if your system is compromised, it doesn't really matter where it's stored, a diligent hacker can track it down.

Solution 4

Sorry I didn't have enough rep to comment, but I also wanted to add that if you're not careful, your shell might capture that password in it's command history as well. So running something like $ pwd=mypassword my_prog manually isn't as ephemeral as you might have hoped.

Solution 5

I think when possible you should store your credentials in a gitignored file and not as environment variables.

One of the things to consider when storing credentials in ENV (environment) variables vs a file is that ENV variables can very easily be inspected by any library or dependency you use.

This can be done maliciously or not. For example a library author could email stack traces plus the ENV variables to themselves for debugging (not best practice, but it's possible to do).

If your credentials are in a file, then peaking into them is much harder.

Specifically, think about an npm in node. For an npm to look at your credentials if they are in the ENV is a simple matter of process.ENV. If on the other hand they are in a file, it's a lot more work.

Whether your credentials file is version controlled or not is a separate question. Not version controlling your credentials file exposes it to fewer people. There's no need for all devs to know the production credentials. Since this lives up to the principle of least privilege, I would suggest git ignoring your credentials file.

Share:
97,361

Related videos on Youtube

jay
Author by

jay

Iā€™m software engineer / software consultant with 11 years experience working with teams in Shanghai, New York, and London. Read more about me at: http://joshuaballoch.github.io/about

Updated on July 08, 2022

Comments

  • jay
    jay almost 2 years

    I work on a few apps in rails, django (and a little bit of php), and one of the things that I started doing in some of them is storing database and other passwords as environment variables rather than plain text in certain config files (or in settings.py, for django apps).

    In discussing this with one of my collaborators, he suggested this is a poor practice - that perhaps this isn't as perfectly secure as it might at first seem.

    So, I would like to know - is this a secure practice? Is it more secure to store passwords as plain text in these files (making sure, of course, not to leave these files in public repos or anything)?

    • Hans Ginzel
      Hans Ginzel about 3 years
      Use HashiCorp Data Vault, hashicorp.com/products/vault.
    • Maciej Pulikowski
      Maciej Pulikowski over 2 years
      It is not secure, there are many exploits to steal environment variables and there is šŸ¦„šŸ”’ Awesome list of secrets in environment variables šŸ–„ļø: github.com/Puliczek/ā€¦
  • Vatine
    Vatine over 11 years
    For environment variables, I am expecting unix here... Environment variables are way less secure than files. Anyone can check the environment of a running process, but files can at least have ACLs.
  • John Carter
    John Carter over 11 years
    It depends on the operating system -- At best case, environment variables are as vulnerable as plaintext files, but likely are worse. With plaintext files you can set the read permissions on the files/directories to protect them. IIRC for environment variables, they live in the memory space for the shell process, so an enterprising cracker could scan that space looking for them.
  • Peter Nixey
    Peter Nixey almost 11 years
    Given that the developer has to store these passwords this isn't a terrifically helpful answer. Where do you suggest that he does store them?
  • Chris Pratt
    Chris Pratt almost 11 years
    @PeterNixey: That's the point. If he has to store them, then he can store them wherever he darn well pleases. He might as well make it the sysmessage at login. Insecure is insecure. Once you've thrown security out the window, it's an open field.
  • Neil McGuigan
    Neil McGuigan over 10 years
    @Vatine really Windows is more secure than *nix in this case? In Windows, User Environment Variables are only accessible to that user and to admin.
  • Vatine
    Vatine over 10 years
    @NeilMcGuigan There may be some differences between unix environments, but in the general case, yes, if you can see the arguments given to a binary, you can see the environment of the binary. Also, the process-listing program usually needs to have complete system privileges (although that is less true, these days).
  • Ben McCann
    Ben McCann over 10 years
    @ChrisPratt are you suggesting there's a better alternative? If I want to deploy a web server that needs to connect to a DB what else would I do to give the password to the web server?
  • Chris Pratt
    Chris Pratt over 10 years
    It depends on your environment. In an ASP.NET environment, you can private key encrypt your database credentials. Other environments may offer similar functionality. Sometimes, you may not have a choice; my only point was that the question, in general, is a useless intellectual thought exercise -- plain text passwords are insecure, period. Trying to figure out which of various insecure methods is somewhat more secure than the other insecure method is a waste of time.
  • Kenny Evitt
    Kenny Evitt over 9 years
    A pretty reasonable alternative to not storing secret configuration settings in version control is storing them in a version control repository or project separate from the repository for the code.
  • Chris Down
    Chris Down almost 8 years
    @Vatine Places exposing environment variables have permissions, too. Try cat /proc/1/environ for example.
  • Vatine
    Vatine almost 8 years
    @ChrisDown Try ps axe to see that being bypassed.
  • Chris Down
    Chris Down almost 8 years
    @Vatine Really? I don't see any environment for processes not owned by me in ps axe. strace -e open ps axe shows it's getting this info from /proc/[pid]/environ, which has permission enforcement (hence a bunch of open("/proc/19795/environ", O_RDONLY) = -1 EACCES (Permission denied)).
  • Vatine
    Vatine almost 8 years
    Huh. Look at that, a problem has finally been fixed (used to be that ps was setuid and would happily show you the environment of pretty much everything).
  • FistOfFury
    FistOfFury about 7 years
    @KennyEvitt that still leaves unsecured, plaintext passwords in a shared location that anyone with access to the repository can find and no way to track who accessed it.
  • Kenny Evitt
    Kenny Evitt about 7 years
    @FistOfFury Sure, anyone with access to the repository ... can access the repository. The point of storing secrets in a separate repository is exactly so that one could control access to those secrets differently than the code itself. But repositories can be secured, e.g. you can store the secrets encrypted in the 'shared location'. And you could even track info about access to the repository in the shared location. But, of course, allowing anyone to access info implies that they can copy that info and thus access it anytime in the future without restriction or tracking.
  • Shadi
    Shadi almost 7 years
    if you prefix the whole "env var + command" with a space, then it doesn't get stored in the history
  • Brian Cline
    Brian Cline almost 7 years
    Great reason to use a config management solution that lets you store encrypted secrets, then substituting them in config templates at render time. Chef has encrypted data bags, Ansible has vaults, etc.
  • brianclements
    brianclements over 6 years
    thanks @shadi. Learn something new every day! I wonder if that's shell specific/easy to turn off or if it's something one can expect pretty consistently?
  • MatrixManAtYrService
    MatrixManAtYrService almost 6 years
    Another way is to use read -s MY_PASS_VAR which will protect from both shell-history searches and shoulder surfers.
  • Amit Naidu
    Amit Naidu about 5 years
    This is called Privileged Access Management, where secrets are stored in a centralized PAM Vault with comprehensive access controls. Gartner lists some such products.
  • netishix
    netishix over 4 years
    +1 for "a library author could email stack traces plus the ENV variables to themselves for debugging". Never thought about this scenario.
  • Mousa Halaseh
    Mousa Halaseh over 4 years
    @brianclements I would like to add that prefixing the command with a space only works if the current shell's HISTCONTROL is set to ignorespace or ignoreboth , so technically it can be turned on/off.
  • math
    math almost 4 years
    wait a minute: if you store the credential inside of an environment variable, they need to get there first. Either by hand, or by script. In order to automate startup of your software, I would recommend a script. But guess what, then you need to store them in a config file (for env variables) nonetheless. Unless you are not providing values for env variables by hand, I can see no security difference to config files.
  • Max Ivanov
    Max Ivanov over 3 years
    @math it depends on the build/startup flow but there's a 3rd option - the startup script (whichever form it takes, whether a bash script or a IaC tool or whatever) fetching credentials from some kind of a (encrypted) secrets storage: Hashicorp Vault, Azure Vault, AWS Parameter Store.
  • timgeb
    timgeb over 3 years
    "and then you're toast if you execute this code" <- Well but you are always toast if you execute untrusted code. An attacker does not need to know the credentials if they have the means to run arbitrary code on the system in question, no?
  • FiftiN
    FiftiN over 2 years
    You should have deployment system (Ansible for example) which creates configuration files on the server. In this case your configs can't be stored in git.
  • Gostega
    Gostega over 2 years
    @timgeb Yes but the point is some untrusted code is much easier to write and much more effective than others. Therefore by using one method (env variables) over another (not obviously named files) you're increasing your attack surface from "cleverly written code which searches within your codebase for references to things which look like secrets files, then reads them" which is quite small, to "a oneliner anyone can copy and paste from stackexchange".
  • TomDogg
    TomDogg over 2 years
    @MaxIvanov : But in order to fetch (encrypted) credentials from a 3rd party provider, this startup script would need to provide credentials for authentication, right? Where would you put those, then?