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

当PHP应用程序进行数据库连接时,通常需要传递login名和密码。 如果我为我的应用程序使用了一个最小权限login,那么PHP需要知道login名和密码。 什么是保护密码的最佳方式? 这似乎只是写在PHP代码是不是一个好主意。

有几个人误解这是一个关于如何密码存储在数据库中的问题。 那是错的。 这是关于如何存储让你数据库的密码。

通常的解决scheme是将密码从源代码移出到configuration文件中。 然后离开pipe理和保护该configuration文件到您的系统pipe理员。 这样开发人员不需要知道任何有关生产密码的信息,并且在源代码pipe理中没有密码logging。

如果您在别人的服务器上托pipe,并且没有访问webroot的权限,则可以始终将密码和/或数据库连接置于文件中,然后使用.htaccesslocking该文件:

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

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

对于非常安全的系统,我们在configuration文件(它本身由系统pipe理员保护)中encryption数据库密码。 在应用程序/服务器启动时,应用程序会提示系统pipe理员input解密密钥。 然后从configuration文件中读取数据库密码,解密并存储在内存中以供将来使用。 仍然不是100%安全的,因为它被存储在内存中解密,但你必须在某个时候称它为'安全'!

最安全的方法是根本没有在您的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")); 

这个解决scheme是通用的,因为它对于开源和闭源应用程序都是有用的。

  1. 为您的应用程序创build一个OS用户。 请参阅http://en.wikipedia.org/wiki/Principle_of_least_privilege
  2. 使用密码为该用户创build(非会话)OS环境variables
  3. 以该用户身份运行该应用程序

优点:

  1. 您不会无意中将您的密码检入源代码pipe理,因为您不能
  2. 你不会不小心搞砸了文件权限。 那么,你可以,但不会影响到这一点。
  3. 只能由root或该用户读取。 Root可以读取所有文件和encryption密钥。
  4. 如果你使用encryption,你如何安全地存储密钥?
  5. 作品x平台
  6. 一定不要将envvar传递给不可信的subprocess

Herokubuild议这个方法非常成功。

如果可以在存储凭据的相同文件中创build数据库连接。 在连接语句中内联凭证。

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

否则,最好在连接语句之后取消设置凭证,因为不在内存中的凭证不能从内存读取 ;)

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

你的select是有限的,因为你说你需要密码来访问数据库。 一种通用的方法是将用户名和密码存储在单独的configuration文件中而不是主脚本中。 那么一定要把它存储在主Web树的外面。 这是如果有一个Webconfiguration问题,让您的PHP文件只是简单地显示为文本而不是执行,你没有暴露的密码。

除此之外,您正在使用正确的线路,只需最小的访问权限。 除此之外

  • 不要使用用户名/密码的组合
  • 将数据库服务器configuration为只接受来自该用户的Web主机的连接(如果数据库在同一台计算机上,则本地主机甚至更好)这样,即使凭据被公开,对任何人都是无用的,除非他们有其他访问机。
  • 混淆密码(即使是ROT13也会这样做),如果有人能够访问这个文件,它不会提供很多的防御措施,但是至less会阻止它的随意查看。

彼得

如果您使用的是PostgreSQL,那么它会自动查找~/.pgpass中的密码。 有关更多信息,请参阅手册 。

将数据库密码放在一个文件中,使其成为只读文件的用户。

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

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

你只需要确保包含密码的php文件具有适当的权限就可以了。 也就是说,只能通过Web服务器和用户帐户来阅读。

我认为OP意味着数据库密码。

除非有人通过FTP或SSH访问您的服务器(在这种情况下,您已经错过了),我不会担心在PHP文件中以明文存储密码。 我见过的大多数PHP应用程序都是这样做的,例如phpbb。

最好的方法是根本不存储密码!
例如,如果您在Windows系统上并连接到SQL Server,那么可以使用集成身份validation来使用当前进程的身份而不用密码连接到数据库。

如果您确实需要使用密码进行连接,请先使用高度encryption(例如,使用AES-256,然后保护encryption密钥或使用非对称encryption并使操作系统保护证书)对其进行encryption,然后将其存储在configuration文件(在Web目录之外),使用强大的ACL

另一个技巧是使用一个PHP单独的configuration文件,如下所示:

 <?php exit() ?> [...] Plain text data including password 

这并不妨碍您正确设置访问规则。 但是如果你的网站被黑客攻击,那么“require”或者“include”就会在第一行退出脚本,所以更难获取数据。

不过,不要让configuration文件放在可以通过networking访问的目录中。 你应该有一个包含你的控制器代码,CSS,图片和JS的“Web”文件夹。 就这样。 其他任何事情都在脱机文件夹中。

把它放在一个configuration文件的地方是通常的做法。 只要确保你:

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

我们用这种方式解决了这个问题:

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

以前我们在configuration文件中存储了数据库用户/密码,但是之后又出现了偏执模式 – 采用深度防御策略。

如果您的应用程序遭到破坏,用户将拥有对您configuration文件的读取访问权限,所以攻击者有可能读取这些信息。 configuration文件也可能受到版本控制,或者在服务器周围复制。

我们已经切换到在Apache VirtualHost中设置的环境variables中存储用户/密码。 这个configuration只能由root读取 – 希望你的Apache用户不能以root身份运行。

与此同时,现在密码是全局PHPvariables。

为了减轻这种风险,我们有以下的预防措施:

  • 密码被encryption。 我们扩展PDO类以包含解密密码的逻辑。 如果有人在我们build立连接的地方读取代码,那么使用encryption的密码而不是密码本身build立连接并不明显。
  • encryption的密码从全局variables移动到私有variables中应用程序会立即执行此操作,以减less全局空间中可用值的窗口。
  • phpinfo()被禁用。 PHPInfo是一个简单的目标,可以概括一切,包括环境variables。