比在配置文件中以纯文本形式存储 mysql 密码更好的方法?

Posted

技术标签:

【中文标题】比在配置文件中以纯文本形式存储 mysql 密码更好的方法?【英文标题】:a better approach than storing mysql password in plain text in config file? 【发布时间】:2011-03-22 05:17:22 【问题描述】:

很多 php 程序要求用户将 mysql 密码以纯文本(字符串或常量)的形式存储在应用程序根目录的配置文件中,这一直困扰着我。

这么多年过去了,还有什么更好的方法吗?

到目前为止,我提出了两个最小的安全提升:

    使用 .htaccess 中的规则使文件无法通过 Web 读取 (以防php失败或读取php源码存在安全漏洞)

    在建立数据库连接后销毁内存中的密码(未设置) (以防止由于安全漏洞、注入等而导致字符串转储)

当然,这些都不能解决最初的问题。

感谢您提出任何其他想法!

【问题讨论】:

技术上不是答案,但您可以将 mysql 配置为仅接受受信任的来源,例如仅使用 unix 域套接字,或仅使用正确的 SSL 证书。 Ontopic:请参阅我的答案以了解如何不存储文字密码。 您是否考虑过可能存在一些包含密码的backup.(tgz|zip) 文件? 甚至比本地备份更糟糕的是带有文本的远程备份 - 因此我提出这些问题,因为纯文本迟早会自找麻烦 【参考方案1】:

就我个人而言,我将数据库连接详细信息等敏感信息存储在我的网络文件夹根目录之外的 config.ini 文件中。然后在我的 index.php 中我可以这样做:

$config = parse_ini_file('../config.ini');

这意味着如果您的服务器不小心开始将 PHP 脚本输出为纯文本(以前发生过这种情况,Facebook 臭名昭著),则变量将不可见;并且只有 PHP 脚本可以访问这些变量。

它也不依赖于 .htaccess,如果您的 .htaccess 文件被移动或破坏,则不会发生意外情况。

警告,2017 年 2 月 14 日添加:我现在将像这样的配置参数存储为环境变量。我已经有一段时间没有使用 .ini 文件方法了。

【讨论】:

【参考方案2】:

由于您的代码需要密码,因此没有完美的安全性。但是你可以让它很难恢复。

我在我的网络配置中放了一些哈希值,作为环境变量,比如MYSQL_PASS_HASH

然后我执行md5(getenv('MYSQL_PASS_HASH').'gibberish$qwefsdf') 之类的操作,这就是密码。当然,如果你偏执,你应该在那之后unsetenv

您的密码实际上不会存储在某个地方,只有当有人同时拥有您的网络配置您的数据库包含时才能恢复它。

这发生在 webroot 之外的文件中(不要完全信任 .htaccess)。

【讨论】:

我认为这是迄今为止对纯文本的真正改进的第一个回复。下一个问题是让其他用户能够轻松地进行这样的配置。 (在某些主机上,移动到 webroot 之外并不总是可行的,也不是真正的解决方案,因为如果可以包含它,file_get_contents 也可以使用它) @symcbean:为什么?我在这里发布它,就像我在自己的服务器上配置它一样!这并不晦涩,而是在所有地方都发布了!我只是将风险分散到 2 个文件上,这两个文件都不应该被访问,并且永远不应该 both 是同一个备份的一部分,plus 不要以明文形式存储它。 短语的“晦涩”部分意味着简单地隐藏(问题),因此实际上 mvds 您的方法在技术上比简单地将纯文本移出 webroot 更好。仅仅移动一个文件绝对是“默默无闻的安全”。【参考方案3】:

将配置文件保存在文档根目录之外是提高配置文件安全性的一种流行方法。

【讨论】:

我只是在打字。我打算指出子条款,即使不是大多数共享主机,也不会让他们的客户访问文档根目录之外的任何内容。 您仍然将文字密码存储在一个文件中的某个位置。这仍然比您需要承担的风险更高。 Peter O'Callaghan,我有专用服务器,甚至无法存储在文档根目录之外【参考方案4】:

当然,您永远不应该将密码存储在文档根目录中的纯文本文件中。您采取哪些进一步的措施来保护它取决于您必须配置网络服务器的访问级别。

您可以在 php.ini 中定义密码(或通过 Apache config 或 .htaccess 中的 ini 设置)。或者在你启动你的网络服务器时在环境中设置它。

仅仅加密密码是没有意义的——这意味着你需要存储一个解密密钥——除非你使用用户提供的密码和仲裁身份验证来解密密码(但这可以防止未经身份验证的会话访问数据库,并且当您需要将新用户添加到仲裁时会变得混乱)。

如果它是一个廉价的托管包,并且您在文档根目录之外没有可访问的存储空间,那么将密码存储在一个 php 包含文件中应该可以防止它被暴露(文件将由 php 解析而不是下载)。或者,简单地在开头使用“.ht”命名文件可能会阻止远程访问。

请注意,您的第二个选项有些多余 - 如果有人可以对您的代码造成如此大的破坏,那么他们不需要从正在运行的代码中提取密码。

真的没有办法解决问题。

C.

【讨论】:

和你一样,我断定这是一个鸡/蛋问题,但我想看看这里的一些伟大的头脑还能想出什么。 在某种形式的加密中显然有一个要点,将恢复密码所需的两个(或更多)部分尽可能分开。 (例如,/etc 下的一部分,另一部分在您的包含路径中,但不在您的 webroot 中)【参考方案5】:

除了正确存储这些敏感数据之外,您还应该create a separate MySQL user 对它需要访问的数据库/表/视图只有所需的privileges and restrict the access。而且由于数据库服务器通常与 Web 服务器在同一台机器上运行,因此还要限制对本地访问的访问。因此,如果只需要从单个数据库/表中读取数据,请不要使用具有 root 权限的用户。

【讨论】:

关于限制权限的好提醒 - 因为许多 PHP 应用程序采取偷懒的方式,让用户只为所有内容配置一个 MySQL 登录名,以便它可以创建表等。当然,即使权限越小仍然需要在大多数应用程序中写入,并且仅此即可造成巨大损失。【参考方案6】:

如果您愿意以可用性换取文件安全性,您可以从配置文件中取出密码,并要求管理员在启动时输入密码并将其存储在全局变量中。

您仍然必须确保自己免受可能将该变量转储出去的注入攻击,当然您在(重新)启动过程中有一个手动步骤。

【讨论】:

不幸的是,这在典型的 PHP/MySQL 应用程序中是不可能的。 同意,但我认为这是一个值得列出的解决方案。【参考方案7】:

它不必位于 webroot 中。您可以将文件移到 webroot 之外并以这种方式调用它。这只是意味着不能直接从网络调用该文件。

如果您的代码中存在安全漏洞,例如在未过滤 GET 数据的情况下包含内容,那么该文件仍然存在风险。真正的关键是确保您的应用程序也是安全的。

【讨论】:

【参考方案8】:

您可以在.htaccess文件中设置环境变量,例如:

SetEnv DBuser sesame
SetEnv DBpass street

稍后在您的代码中读取、使用和删除条目。

【讨论】:

以上是关于比在配置文件中以纯文本形式存储 mysql 密码更好的方法?的主要内容,如果未能解决你的问题,请参考以下文章

数据库凭据以纯文本形式存储可以吗?

将密码以纯文本形式存储在 php 变量或 php 常量中是不是可以?

当 API 调用需要以纯文本形式发送密码时,将密码存储在数据库中的最佳方法是啥?

有没有办法将我的 MySQL 密码安全地存储在 Node.JS 中?

在 CI 环境中保护密码

在签名配置中写入密码是不是安全?