将密码作为环境变量(而不是纯文本)存储在配置文件中是否安全?


109

我在Rails,django(和一点点php)上开发了一些应用程序,在其中一些程序中我开始做的一件事是将数据库和其他密码作为环境变量而不是纯文本存储在某些配置文件中(或在settings.py中(对于Django应用)。

在与我的一位合作者讨论此问题时,他建议这是一种不良做法-也许这并不像最初看起来那样安全。

所以,我想知道-这是安全的做法吗?将密码以纯文本格式存储在这些文件中是否更安全(当然,请确保不要将这些文件保留在公共存储库中或其他内容中)?

Answers:


45

从理论上讲,我倾向于以下列方式(按照强度递增的顺序)来考虑安全级别:

  • 没有安全感。纯文本。任何知道在哪里查看的人都可以访问数据。
  • 通过混淆来保证安全。您将数据(明文)存储在某个位置比较麻烦,例如环境变量,或者存储在看起来像配置文件的文件中。攻击者最终会发现正在发生的事情,或者偶然发现了发生的事情。
  • 加密提供的安全性可以轻易破解(想想凯撒密码!)。
  • 加密提供的安全性可能会被破坏。
  • 加密提供的安全性对于破坏给定的当前硬件不切实际。
  • 最安全的系统是没人能使用的系统!:)

环境变量比纯文本文件安全,因为它们是易失性/一次性的,不保存。即,如果仅设置一个本地环境变量(例如“ set pwd = whatever”),然后运行脚本,并且脚本末尾退出命令外壳,则该变量将不再存在。您的案件属于前两个案件,我想这是相当不安全的。如果要执行此操作,我建议您不要在直接的Intranet /家庭网络之外进行部署,而仅出于测试目的。


1
这取决于操作系统-在最佳情况下,环境变量与纯文本文件一样易受攻击,但可能更糟。使用纯文本文件,您可以在文件/目录上设置读取权限以保护它们。IIRC用于环境变量,它们存在于Shell进程的内存空间中,因此进取的破解者可以扫描该空间来寻找它们。
约翰·卡特

1
等一下:如果将凭据存储在环境变量中,则它们需要首先到达那里。手动或脚本。为了自动启动软件,我建议使用一个脚本。但是猜猜是什么,那么您仍然需要将它们存储在配置文件中(用于环境变量)。除非您没有手动提供env变量的值,否则我看不到配置文件的安全性差异。
数学

59

如前所述,一旦系统受到威胁,这两种方法都不会提供任何额外的“安全性”层。我相信,支持环境变量的最重要原因之一是版本控制:我已经看到太多的数据库配置等被意外地存储在像GIT这样的版本控制系统中,其他所有开发人员都可以看到(呵呵!我也是 ...)。

如果不将密码存储在文件中,则无法将其存储在版本控制系统中。


6
在版本控制中存储秘密配置设置的一种非常合理的选择是将它们存储在版本控制存储库或与代码存储库分开的项目中。
肯尼·埃维特

1
@KennyEvitt仍将不安全的纯文本密码保留在共享位置,任何有权访问该存储库的人都可以找到,也无法跟踪谁访问了该存储库。
FistOfFury

2
@FistOfFury当然,有权访问该存储库的任何人都可以访问该存储库。将机密存储在单独的存储库中的目的恰好是为了使人们可以以与代码本身不同的方式控制对这些机密的访问。但是存储库可以得到保护,例如,您可以将加密的机密存储在“共享位置”中。您甚至可以在共享位置跟踪有关访问存储库的信息。但是,当然,允许任何人访问信息都意味着他们可以复制该信息,从而将来可以在任何时间不受限制或跟踪。
肯尼·埃维特

2
使用配置管理解决方案的重要原因,该解决方案允许您存储加密的机密,然后在渲染时将其替换为配置模板。厨师加密的数据包,具有Ansible拱顶等
布赖恩克莱恩

1
这称为特权访问管理,其中机密存储在具有全面访问控制功能的集中式PAM Vault中。Gartner列出了一些此类产品
阿米特·奈杜

44

每当您必须存储密码时,它都是不安全的。期。无法安全地存储未加密的密码。现在,哪个环境变量与配置文件更“安全”可能值得商bat。恕我直言,如果您的系统受到威胁,那么它的存储位置并不重要,勤奋的黑客可以追踪到它。


12
对于环境变量,我期望在这里使用unix。环境变量的安全性比文件低。任何人都可以检查正在运行的进程的环境,但是文件至少可以具有ACL。
Vatine 2012年

11
鉴于开发人员必须存储这些密码,因此这不是一个非常有用的答案。您建议他在哪里存储它们?
2013年

2
暴露环境变量的@Vatine Places也具有权限。尝试cat /proc/1/environ例如。
克里斯·

4
@Vatine真的吗?我在中看不到我不拥有的进程的任何环境ps axestrace -e open ps axe显示它是从那里获取此信息的,该信息/proc/[pid]/environ具有权限执行(因此有open("/proc/19795/environ", O_RDONLY) = -1 EACCES (Permission denied))。
克里斯·

4
嗯 看看,终于解决了一个问题(以前ps是setuid,可以很高兴地向您展示几乎所有环境)。
Vatine

28

抱歉,我没有足够的代表对此发表评论,但是我也想补充一点,如果您不小心,您的外壳程序也可能会在命令历史记录中捕获该密码。因此,$ pwd=mypassword my_prog手动运行这样的操作并不像您希望的那样短暂。


21
如果您在整个“ env var +命令”
前面

谢谢@shadi。每天学些新东西!我想知道这是否是特定于外壳的/易于关闭的,还是人们可以一直期望的?
贿赂

4
另一种方法是使用read -s MY_PASS_VAR它将保护免受炮弹历史搜索和肩膀冲浪者的攻击。
MatrixManAtYrService

4
@brianclements我想补充一点,只有在当前shell的HISTCONTROL设置为ignorespace或的情况下ignoreboth,才能在命令前加上空格作为前缀,因此从技术上讲可以将其打开/关闭。
摩西

13

我认为您应该尽可能将凭据存储在gitignored文件中,而不应作为环境变量存储。

在将凭证存储在ENV(环境)变量与文件中时,要考虑的一件事是,使用的任何库或依赖项都可以很容易地检查ENV变量。

可以通过恶意或不通过恶意方式进行此操作。例如,库作者可以将堆栈跟踪信息和ENV变量通过电子邮件发送给自己,以进行调试(不是最佳实践,但可以这样做)。

如果您的凭据在文件中,则很难深入了解它们。

具体来说,考虑节点中的npm。对于npm,如果要查看您的凭据是否在ENV中,则很简单process.ENV。另一方面,如果它们在文件中,则还有很多工作要做。

您的凭据文件是否受版本控制是一个单独的问题。并非版本控制您的凭据文件将其暴露给更少的人。无需所有开发人员都知道生产凭据。由于这符合最小特权原则,因此我建议git忽略您的凭据文件。


5
+1表示“库作者可以将堆栈跟踪信息和ENV变量通过电子邮件发送给自己,以进行调试”。从来没有想过这种情况。
netishix

6

这取决于您的威胁模型。

您是否在尝试防止用户在可能被忘记和处理不当的整个文件系统上散布密码?如果是这样,则是,因为环境变量的持久性不如文件。

您是否要防止直接针对您程序的恶意软件的侵害?如果是这样,则否,因为环境变量没有文件具有相同级别的访问控制。

就个人而言,我认为疏忽的用户比有动机的对手更常见,因此我会选择环境变量方法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.