问题描述

这些天最常见的安全最佳做法之一似乎是将 wp-config.php 的一个目录移动到高于 vhost 的文档根目录。我从来没有真正找到一个很好的解释,但我假设它是最小化 webroot 中的恶意或感染脚本的风险从阅读数据库密码。

但是,您仍然必须让 WordPress 访问它,因此您需要扩展 open_basedir 以将文档根目录上方的目录包括在内。这不仅仅是打败整个目的,还可能会将服务器日志,备份等暴露给攻击者?

或者是只是试图阻止 wp-config.php 将被显示为任何请求 http://example.com/wp-config.php 的任何人的情况的技术,而不是由 PHP 引擎解析?这似乎是一个非常罕见的事情,它不会超过暴露日志/备份/ etc 到 HTTP 请求的缺点。

也许可以将它移动到某些主机设置中的文档根目录外,而不会暴露其他文件,但不能在其他设置中?


结论:在这个问题上经过很多的 back-and-forth,出现了两个答案,我认为应该被认为是权威的。亚伦·亚当斯 (Aaron Adams) 表示赞成移动 wp-config,克里斯蒂安 (Joe Adams) 对此表示反感。这些是你应该阅读的两个答案,如果你是新的线程,不想阅读整个事情。其他答案是冗余或不准确的。

最佳解决方案

简答:是的

这个问题的答案是一个明确的肯定,否则说完全是不负责任的。


长答案:一个 real-world 的例子

让我提供一个非常真实的例子,从我真正的服务器,移动 wp-config.php 外面的 Web 根,专门阻止其内容被捕获。

错误:

看看这个描述在 Plesk 的一个错误 (固定在 11.0.9 MU#27):

Plesk resets subdomain forwarding after syncing subscription with hosting plan (117199)

听起来无害,对吧?

嗯,这是我做了什么来触发这个错误:

  1. 设置子域以重定向到另一个 URL(例如 site.staging.server.comsite-staging.ssl.server.com) 。
  2. 更改订阅的服务计划 (例如其 PHP 配置) 。

当我这样做时,Plesk 将子域重置为默认值:为~/httpdocs/的内容提供服务,没有口译员 (例如 PHP) 的活动。

我没有注意到。数周。

结果:

  • 在 Web 根目录中使用 wp-config.php,对/wp-config.php 的请求将下载 WordPress 配置文件。
  • 使用 wp-config.php 在 Web 根外部,对/wp-config.php 的请求下载完全无害的文件。真正的 wp-config.php 文件无法下载。

因此,显而易见的是,在网页外移动 wp-config.php 在现实世界中具有真正的安全优势。


如何将 wp-config.php 移动到服务器上的任何位置

WordPress 将自动在您的 wp-config.php 文件的 WordPress 安装上方看到一个目录,所以如果你已经移动了它,那么你就完成了!

但是如果你把它移到别的地方呢?简单。在 WordPress 目录中使用以下代码创建一个新的 wp-config.php

<?php

/** Absolute path to the WordPress directory. */
if ( !defined('ABSPATH') )
    define('ABSPATH', dirname(__FILE__) . '/');

/** Location of your WordPress configuration. */
require_once(ABSPATH . '../phpdocs/wp-config.php');

(请务必将上述路径更改为重定位的 wp-config.php 文件的实际路径。)

如果遇到 open_basedir 的问题,只需在 PHP 配置中添加 open_basedir 指令的新路径:

open_basedir = "/var/www/vhosts/example.com/httpdocs/;/var/www/vhosts/example.com/phpdocs/;/tmp/"

而已!


提出相反的论据

在网页外移动 wp-config.php 的所有争论都取决于假设。

参数 1:如果禁用 PHP,它们已经存在

The only way someone is going to see that contents of
[wp-config.php] is if they circumvent your servers PHP interpreter…
If that happens, you’re already in trouble: they have direct access to
your server.

FALSE:我上面描述的场景是错误配置的结果,而不是入侵。

参数 2:意外的禁用 PHP 是罕见的,因此是微不足道的

If an attacker has enough access to change the PHP handler, you’re
already screwed. Accidental changes are very rare in my experience,
and in that case it’d be easy to change the password.

FALSE:我上面描述的场景是一个常见的服务器软件中的错误的结果,影响了一个常见的服务器配置。这几乎不是”rare”(此外,安全意味着担心罕见的情况) 。

WTF:如果在入侵期间收到敏感信息,入侵后更改密码几乎不会有帮助。真的,我们仍然认为 WordPress 仅用于休闲博客,而攻击者只对污名感兴趣吗?我们担心保护我们的服务器,而不仅仅是在有人进入后恢复。

参数 3:拒绝访问 wp-config.php 是足够好的

You can restrict access to the file via your virtual host config or
.htaccess – effectively limiting outside access to the file in the
same way that moving outside the document root would.

FALSE:想象一下虚拟主机的服务器默认值是:没有 PHP,没有.htaccessallow from all(在生产环境中几乎不常见) 。如果您的配置在例行操作中以某种方式重置 (例如,面板更新),则所有操作都将恢复为默认状态,并显示出来。

如果您的安全模型在设置意外重置为默认设置时失败,则需要更多的安全性。

WTF:为什么有人特意推荐更少的安全层?昂贵的汽车不只是有锁; 他们还有闹钟,固定装置和 GPS 追踪器。如果有什么值得保护的话,做对吧。

参数 4:未经授权访问 wp-config.php 是没有什么大不了的

The database information is really the only sensitive stuff in
[wp-config.php].

FALSE:认证密钥和盐可用于任何数量的潜在劫持攻击。

WTF:即使数据库凭据是 wp-config.php 中的唯一的事情,您也应该害怕攻击者手中。

参数 5:在 Web 根外部移动 wp-config.php 实际上使服务器不太安全

You still have to let WordPress access [wp-config.php], so you need
to expand open_basedir to include the directory above the document
root.

FALSE:假设 wp-config.phphttpdocs/中,只需将其移动到../phpdocs/,并将 open_basedir 设置为仅包含 httpdocs/phpdocs/。例如:

open_basedir = "/var/www/vhosts/example.com/httpdocs/;/var/www/vhosts/example.com/phpdocs/;/tmp/"

(记住要始终包括/tmp/或您的用户 tmp/目录,如果您有) 。


结论:配置文件应始终始终位于 Web 根外部

如果你关心安全性,你将把 wp-config.php 移到你的网页之外。

次佳解决方案

最重要的是 wp-config.php 包含一些敏感信息:您的数据库用户名/密码等。

所以这个想法:把它移到文档根目录之外,你不必担心任何事情。攻击者永远无法从外部来源访问该文件。

然而,这是擦除:wp-config.php 从来没有实际打印任何东西到屏幕。它只定义了在整个 WP 安装过程中使用的各种常量。因此,有人会看到该文件的内容是唯一的方法是如果他们绕过您的服务器 PHP 解释器 – 他们将.php 文件渲染为纯文本。如果发生这种情况,您已经遇到了麻烦:他们可以直接访问您的服务器 (也可能是 root 权限),并可以做任何他们喜欢的操作。

我将继续说,从安全角度来看,将 wp-config 移到文档根目录之外没有任何好处 – 由于上述原因和这些原因:

  1. 您可以通过虚拟主机配置或.htaccess 限制对该文件的访问 – 有效地限制对文件的访问权限与文档根目录外的相同方式
  2. 您可以确保 wp-config 上的文件权限严格,以防止任何没有足够权限的用户读取文件,即使他们通过 SSH 获取 (限制) 访问服务器。
  3. 您的敏感信息,数据库设置仅在单个站点上使用。所以即使攻击者获得访问该信息,唯一会影响的站点是 wp-config.php 文件所属的 WordPress 安装。更重要的是,该数据库用户只具有读取和写入该 WP 安装数据库的权限,也没有其他的权限 – 无权限授予其他用户权限。换句话说,如果攻击者可以访问您的数据库,这只是一个从备份恢复的问题 (请参阅第 4 点) 并更改数据库用户
  4. 你经常备份。通常是一个相对的术语:如果你每天发布 20 篇文章,你最好每天或每隔几天备份。如果您每周发布一次,每周备份一次可能就足够了。
  5. 您的站点受版本控制 (like this),这意味着即使攻击者获得访问权限,也可以轻松地检测代码更改并将其回滚。如果攻击者可以访问 wp-config,那么他们可能会搞砸别的东西。
  6. 数据库信息真的是 wp-config 中唯一敏感的东西,因为你很小心 (参见第 3 点和第 4 点),这不算什么。任何时候都可以改变盐等。发生的唯一事情是使用户的 Cookie 无效。

对我来说,将 wp-config 从文件中移除,这是一个非常棒的人。

第三种解决方案

我认为马克斯是一个知识渊博的答案,而这是故事的一面。 WordPress Codex has more advise

Also, make sure that only you (and the web server) can read this file
(it generally means a 400 or 440 permission).

If you use a server with .htaccess, you can put this in that file (at
the very top) to deny access to anyone surfing for it:

<files wp-config.php>
order allow,deny
deny from all
</files>

请注意,在 wp-config.php 上设置 400 或 440 的权限可能会阻止插件写入或修改它。例如,一个真正的例子是缓存插件 (W3 Total Cache,WP Super Cache 等) 在这种情况下,我将使用 600(/home/user 目录中的文件的默认权限) 。

第四种方案

肯定是

当您将 wp-config.php 移动到公共目录之外时,当 php 处理程序恶意 (或意外!) 更改时,您可以使用浏览器保护它免受阅读。

当服务器几乎不受跛脚管理员的错误感染时,可以读取您的 DB 登录名/密码。给管理员一个罚款,并获得一个 better-tended 和更可靠的服务器主机。虽然这可能会更贵。

第五种方案

有人要我们照看,我会在这里回答。

是的,从您的站点的根目录隔离您的 wp-config.php 有安全的好处。

1-如果您的 PHP 处理程序以某种方式被破坏或修改,您的数据库信息将不会被公开。是的,我在服务器更新期间看到这种情况在共享主机上发生了几次。是的,该网站将在此期间被破坏,但您的密码将是完整的。

2-最佳做法总是建议从数据文件中隔离配置文件。是的,这是很难用 WordPress(或任何网络应用程序),但移动它做一点隔离。

3-记住 PHP-CGI 漏洞,其中任何人都可以将。-s 传递给文件并查看源。 http://www.kb.cert.org/vuls/id/520827

最后,这些都是细节细节,但它们有助于最大限度地降低风险。特别是如果您处于共享环境中,任何人都可以访问您的数据库 (所有他们需要的是用户/通行证) 。

但是请不要让小心的分心 (过早的优化) 得到真正需要使网站正确安全的前提:

1-始终保持更新

2-使用强密码

3-限制访问 (通过权限) 。我们在这里有一个帖子:

 http://blog.sucuri.net/2012/08/wordpress-security-cutting-through-the-bs.html

谢谢,

第六种方案

我只是想澄清一下,为了争论,移动你的 wp_config.php 文件并不一定意味着你必须把它移动到父目录。假设你有一个结构,如/ root / html,其中 html 包含 WP 安装和所有的 HTML 内容。而不是将 wp_config.php 移动到/ root,您可以将其移动到/ root / secure … 之外,这两者都在 html 目录之外,也不在服务器根目录中。当然,您需要确保 php 可以在此安全文件夹中运行。

由于 WP 无法配置为在同级文件夹 (如/ root / secure) 中查找 wp_config.php,因此您必须采取额外的步骤。我将 wp_config.php 放在/ root / html 中,并删除敏感部分 (数据库登录名,salt,表前缀),并将它们移动到一个名为 config.php 的单独文件中。然后,您将 PHP include 命令添加到您的 wp_config.php,如下所示:include('/home/content/path/to/root/secure/config.php');

这本质上是我在我的设置中所做的。现在,基于上述讨论,我还在评估是否有必要甚至是一个好主意。但我只是想补充说,上述配置是可能的。它不会暴露您的备份和其他根文件,只要安全文件夹没有设置自己的公共 URL,它是不可浏览的。

此外,您可以通过在其中创建.htaccess 文件来限制对安全文件夹的访问:

order deny,allow
deny from all
allow from 127.0.0.1

第七种方案

有很多不好的书面主题和插件,允许 atatckers 注入代码 (记住与 Timthumb 的安全问题) 。如果我是攻击者,为什么要搜索 wp-config.php?只需注入这段代码:

var_dump( DB_NAME, DB_USER, DB_PASSWORD );

您可以尝试隐藏您的 wp-config.php 。只要 WordPress 将所有敏感信息全局访问,隐藏 wp-config.php 就没有任何好处。

wp-config.php 的不好的部分不是它保存敏感数据。不好的部分是将敏感数据定义为全局可访问常数。

更新

我想澄清 define()的问题,为什么将敏感数据定义为全局常量是一个坏主意。

有很多方法来攻击网站。脚注注入只是打破网站的一种方式。

假设服务器有一个漏洞,让攻击者访问内存转储。攻击者会在内存中找到所有变量的所有值。如果你定义一个全局可访问的常量,它必须保持在内存中,直到脚本结束。创建一个变量而不是一个常量,在不再需要该变量的情况下,很可能垃圾回收器会覆盖 (或释放) 内存。

保护敏感数据的更好方法是在使用它们后立即删除它们:

$db_con = new stdClass();
$db_con->db_user = 'username';
$db_con->password = 'password';
$db_con->host = 'localhost';

$db_handler = new Database_Handler( $db_con );

$db_con = null;

使用敏感数据后,分配给 null 会覆盖内存中的数据。攻击者必须在 $db_con 包含敏感数据的时刻获取内存转储。这在上面的例子中是非常短的时间 (如果 Database_Handler 类不保存它的副本) 。

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。