在 htaccess 中而不是在 PHP 文件中声明 DB 参数是一种安全的方法吗?

信息安全 php 硬化 mysql
2021-09-10 22:34:20

保护 PHP 文章中建议,在 htaccess 中使用如下指令比将其硬编码到您的应用程序中更安全:

<VirtualHost ilia.ws>
Include /home/ilia/sql.cnf
</VirtualHost>

然后在 sql.cnf 中声明您的参数,如下所示:

SetEnv DB_LOGIN “login”
SetEnv DB_PASSWD “password”
SetEnv DB_DB “my_database”
SetEnv DB_HOST “127.0.0.1”

最后通过以下方式访问它们:

echo $_SERVER[‘DB_LOGIN’]; // login
echo getenv(“DB_LOGIN”); // login 
4个回答

这是一种合理的做法。这种方法的好处是它避免了将密码存储在源代码中。这是一件好事:您不应该在源代码中硬编码密码

(当然,在这个建议下,数据库密码不存储在.htaccess文件中,而是存储在单独的配置文件中。但差别不大。)

重要提示:确保它sql.cnf没有存储在您的 Web 根目录中。如果它存储在您的 Web 根目录中,那么任何知道正确路径的人都可以通过发送 GET 请求来请求它。

  • 将密码存储在 webroot 内的文件中还有一个额外的风险sql.cnf,这有点晦涩难懂,但可以通过将文件放在 web root 之外轻松避免。考虑:如果您正在sql.cnf使用文本编辑器进行编辑,并且在您编辑时连接断开,您的编辑器会自动将sql.cnf文件的副本保存在某个备份文件中:例如sql.cnf~(在同一目录中)。现在备份文件有一个不同的扩展名,所以如果有人试图获取该文件,Apache 服务器会很高兴地以明文形式提供该文件的副本,从而显示您的数据库密码。有关详细信息,请参阅1% 的 CMS 支持的站点公开其数据库密码

有关一般原则的更多信息:

该建议基于这样一个事实,即 PHP 文件将是世界可读的,但 .htaccess 文件/httpd.conf 不会。作者正确地指出,使用加密来隐藏这些值并没有帮助——因为这意味着 PHP 代码需要可以访问加密密钥。但是将值存储在环境中只会避免一些问题,这些问题也可以通过其他方式避免。服务器上运行的任何 PHP 代码都可以读取 httpd.conf 文件中的值。将它们移动到 vhost defn 会缩小可见性。您可以将它们作为 PHP 代码保存在文档根目录中,只需在文件名前加上“.ht”即可。

当然,独立于大部分代码维护令牌是一种很好的做法。自从

  • 它们将具有与代码不同的生命周期(即可能需要独立于代码进行更改,反之亦然)
  • 不应通过代码管理工具(例如版本控制系统)公开
  • 应根据代码的部署位置而有所不同(即用于测试/阶段/实时的不同令牌)

然而,使用网络服务器配置只是实现这一目标的一种方法——还有其他有效的方法。

无论您采用哪种方式,解决方案的安全性都来自考虑所有方面 - 文件权限/文件可访问性、数据库连接限制、数据库访问控制

对此有一些警告,第一个希望路径:/home/ilia/sql.cnf 不在您网站的 webroot 中,或者攻击者可以简单地访问 url http://ilia.ws/sql .cnf查看您的数据库凭据。

此外,希望您的网站不包含各种信息泄露错误或 phpinfo 页面,因为 phpinfo 将转储 $_SERVER 数组,从而向该页面的任何访问者披露您的数据库凭据。

此外,如果信息存储在 PHP 文件中而不是环境变量,攻击者将更难获取信息的假设是垃圾。您的示例为每个页面请求设置环境变量。这意味着可能无权读取您的 sql.conf 文件的目录遍历攻击仍可能具有读取 /prof/self/environ 并以这种方式获取凭据的权限。

我会确保您的数据库服务器绑定到环回接口,确保您的数据库凭据具有尽可能低的权限,并确保您的 Web 应用程序和服务器软件及时修补,并将凭据存储在 php 文件中。

如果您想将密码存储在环境变量中,但不希望其他用户能够读取密码或密钥,您可以按照以下步骤操作(在 Ubuntu 18.04 上测试):

  • 创建文件 /etc/apache2/conf-available/mysql_credentials.conf
  • 将所有权更改为 root sudo chown root:root /etc/apache2/conf-available/mysql_credentials.conf
  • 更改文件权限,使其仅对root可读 sudo chmod 600 /etc/apache2/conf-available/mysql_credentials.conf
  • 将密码或密钥放入文件中,例如 SetEnv DB_PASSWD abcdefg12345+-987654321
  • 启用配置文件 sudo a2enconf mysql_credentials
  • 重启阿帕奇 sudo service apache2 restart

在 PHP 中可以通过$_SERVER['DB_PASSWD'].