如何在PHP中保护数据库密码?

时间:2008-09-18 23:27:04

标签: php database security

当PHP应用程序建立数据库连接时,它当然通常需要传递登录名和密码。如果我正在为我的应用程序使用单个最小权限登录,那么PHP需要知道某处的登录名和密码。保护密码的最佳方法是什么?看起来只是在PHP代码中编写它并不是一个好主意。

17 个答案:

答案 0 :(得分:223)

有些人误以为这是关于如何在数据库中存储密码的问题。那是错的。它是关于如何存储密码,让您数据库。

通常的解决方案是将密码从源代码中移出到配置文件中。然后将管理和保护配置文件保留给系统管理员。这样开发人员就不需要了解生产密码,也没有源代码控制中的密码记录。

答案 1 :(得分:98)

如果您在其他人的服务器上托管并且无法访问您的webroot,您可以随时将您的密码和/或数据库连接放在一个文件中,然后使用.htaccess锁定该文件:

<files mypasswdfile>
order allow,deny
deny from all
</files>

答案 2 :(得分:41)

最安全的方法是根本不具备PHP代码中指定的信息。

如果您正在使用Apache,则意味着在httpd.conf或虚拟主机文件文件中设置连接详细信息。如果你这样做,你可以调用没有参数的mysql_connect(),这意味着PHP永远不会输出你的信息。

这是在这些文件中指定这些值的方法:

php_value mysql.default.user      myusername
php_value mysql.default.password  mypassword
php_value mysql.default.host      server

然后你打开你的mysql连接:

<?php
$db = mysqli_connect();

或者像这样:

<?php
$db = mysqli_connect(ini_get("mysql.default.user"),
                     ini_get("mysql.default.password"),
                     ini_get("mysql.default.host"));

答案 3 :(得分:39)

将它们存储在Web根目录之外的文件中。

答案 4 :(得分:34)

对于极其安全的系统,我们在配置文件中加密数据库密码(配置文件本身由系统管理员保护)。在应用程序/服务器启动时,应用程序然后提示系统管理员提供解密密钥。然后从配置文件中读取数据库密码,解密并存储在内存中以备将来使用。仍然不是100%安全,因为它存储在解密的内存中,但你必须在某些时候称它为“足够安全”!

答案 5 :(得分:14)

此解决方案是通用的,因为它对开源和闭源应用程序都很有用。

  1. 为您的应用程序创建OS用户。请参阅http://en.wikipedia.org/wiki/Principle_of_least_privilege
  2. 使用密码
  3. 为该用户创建(非会话)OS环境变量
  4. 以该用户身份运行应用程序
  5. 优点:

    1. 您不会意外地将密码检查到源代码管理中,因为您无法
    2. 您不会意外搞砸文件权限。好吧,你可以,但不会影响这一点。
    3. 只能由root或该用户读取。 Root无论如何都可以读取所有文件和加密密钥。
    4. 如果使用加密,如何安全地存储密钥?
    5. Works x-platform
    6. 请务必不要将envvar传递给不受信任的子进程
    7. 这种方法是由Heroku建议的,他非常成功。

答案 6 :(得分:11)

是否可以在存储凭据的同一文件中创建数据库连接。内联连接语句中的凭据。

mysql_connect("localhost", "me", "mypass");

否则最好在connect语句之后取消设置凭据,因为凭据不在内存中,不能是read from memory;)

include("/outside-webroot/db_settings.php");  
mysql_connect("localhost", $db_user, $db_pass);  
unset ($db_user, $db_pass);  

答案 7 :(得分:7)

您的选择有限,因为您说需要密码才能访问数据库。一种通用方法是将用户名和密码存储在单独的配置文件中,而不是主脚本中。然后一定要将其存储在主Web树之外。那就是如果有一个Web配置问题,你的php文件只是显示为文本而不是被执行,你没有公开密码。

除此之外,您所使用的帐户访问权限最少。添加到

  • 不要将用户名/密码组合用于其他任何内容
  • 将数据库服务器配置为仅接受来自该用户的Web主机的连接(如果数据库位于同一台计算机上,localhost甚至更好)这样即使凭据被公开,除非他们有其他人,否则它们对任何人都没用访问机器。
  • 对密码进行模糊处理(即使是ROT13也会这样做)如果有人能够访问该文件,它将不会提供太多防御,但至少会阻止随意查看它。
彼得

答案 8 :(得分:7)

如果您正在使用PostgreSQL,那么它会自动查找~/.pgpass中的密码。有关详细信息,请参阅the manual

答案 9 :(得分:5)

将数据库密码放入文件中,使其对提供文件的用户只读。

除非你有一些方法只允许php服务器进程访问数据库,否则这就是你所能做的一切。

答案 10 :(得分:5)

以前我们将DB user / pass存储在一个配置文件中,但是后来一直处于偏执模式 - 采用深度防御的策略。

如果您的应用程序遭到入侵,用户将具有对您的配置文件的读取权限,因此有可能让黑客读取此信息。配置文件也可以在版本控制中被捕获,或者在服务器周围复制。

我们已经切换到在Apache VirtualHost中设置的环境变量中存储user / pass。此配置只能由root读取 - 希望您的Apache用户不以root用户身份运行。

与此相关的是,现在密码是全局PHP变量。

为了降低这种风险,我们采取了以下预防措施:

  • 密码已加密。我们将PDO类扩展为包含用于解密密码的逻辑。如果有人读取我们建立连接的代码,则使用加密密码而不是密码本身建立连接并不明显。
  • 加密密码从全局变量移动到私有变量应用程序立即执行此操作以减少值在全局空间中可用的窗口。
  • phpinfo()已停用。 PHPInfo是一个简单的目标,可以全面了解所有内容,包括环境变量。

答案 11 :(得分:4)

如果您正在谈论数据库密码,而不是来自浏览器的密码,那么标准做法似乎是将数据库密码放在服务器上的PHP配置文件中。

您只需要确保包含密码的php文件具有适当的权限。即它只能由Web服务器和您的用户帐户读取。

答案 12 :(得分:3)

另一个技巧是使用看起来像这样的PHP单独配置文件:

<?php exit() ?>

[...]

Plain text data including password

这并不妨碍您正确设置访问规则。但是如果您的网站被黑客攻击,“require”或“include”将只在第一行退出脚本,因此获取数据更加困难。

尽管如此,不要让配置文件放在可以通过Web访问的目录中。你应该有一个“Web”文件夹,其中包含你的控制器代码,css,图片和js。就这样。其他任何内容都在脱机文件夹中。

答案 13 :(得分:3)

将它放入某个配置文件中就像通常那样。请确保你:

  1. 禁止从网络外的任何服务器访问数据库,
  2. 注意不要意外地向用户显示密码(在错误消息中,或通过PHP文件意外地作为HTML等提供。)

答案 14 :(得分:3)

最好的方法是不要存储密码!
例如,如果您使用的是Windows系统并连接到SQL Server,则可以使用集成身份验证使用当前进程的标识在没有密码的情况下连接到数据库。

如果您确实需要连接密码,首先加密,使用强加密(例如使用AES-256,然后保护加密密钥,或使用非对称加密并让操作系统保护证书),然后使用强ACL 将其存储在配置文件(网络目录之外)中。

答案 15 :(得分:3)

我们已经用这种方式解决了它:

  1. 在服务器上使用memcache,并使用其他密码服务器的开放连接。
  2. 保存到memcache密码(甚至加密的所有password.php文件)和解密密钥。
  3. 该网站调用memcache密钥保存密码文件密码,并在内存中解密所有密码。
  4. 密码服务器每5分钟发送一个新的加密密码文件。
  5. 如果您在项目中使用加密的password.php,则进行审核,检查该文件是否在外部触摸或查看。发生这种情况时,您可以自动清理内存,并关闭服务器以进行访问。

答案 16 :(得分:0)

实际上,最佳做法是将数据库凭据存储在环境变量中,因为:

  • 这些凭据取决于环境,这意味着您在 dev/prod 中不会拥有相同的凭据。将它们存储在所有环境的同一个文件中是错误的。
  • 凭据与业务逻辑无关,这意味着登录名和密码与您的代码无关。
  • 您可以在不创建任何业务代码类文件的情况下设置环境变量,这意味着您永远不会犯在 Git 中将凭证文件添加到提交中的错误。
  • 环境变量是超级全局变量:您可以在代码中的任何地方使用它们,而无需包含任何文件。

如何使用它们?

  • 使用 $_ENV 数组:
    • 设置:$_ENV['MYVAR'] = $myvar
    • Getting : echo $_ENV["MYVAR"]
  • 使用 php 函数:
  • In vhosts files and .htaccess 但不建议这样做,因为它在另一个文件中并且通过这种方式无法解决问题。

您可以轻松地删除包含所有环境变量的 envvars.php 文件并执行它 (php envvars.php) 并删除它。这有点老派,但它仍然有效,并且您在服务器中没有任何带有凭据的文件,并且代码中没有凭据。由于它有点费力,框架做得更好。

Symfony 示例(不仅是 PHP) Symfony 等现代框架建议使用环境变量,并将它们存储在 .env 未提交文件中或直接存储在命令行中,这意味着您可以这样做:

文档: