为什么 PHP fopen() 函数不适用于 755 和 775 文件夹权限?
Why the PHP fopen() function is not working with 755 and 775 folder permissions?
我正在使用 ACRA (https://github.com/ACRA/acra) 自动将我的 Android 崩溃报告发布到报告服务器。我有一个 PHP 脚本,它使用以下行将日志文件写入测试服务器上的 https://example.com/logs/
文件夹:
$FileLog = $_SERVER['DOCUMENT_ROOT'] . "/logs/" . $fname;
$HandleLog = fopen($FileLog, 'a');
只有当我服务器上的 logs/
文件夹具有这些权限时,PHP fopen()
功能才能正常工作:
drwxrwxrwx (777)
我已经尝试了 drwxrwxr-x (775)
和 drwxr-xr-x (755)
,但 fopen()
功能不起作用。它仅在我使用 drwxrwxrwx (777)
作为 logs/
文件夹权限时有效。
这对我来说很奇怪,因为我 运行 的 PHP 脚本在我的服务器上,所以当我从我的 PHP 文件执行 fopen($FileLog, 'a')
时服务器,如果 https://example.com/logs/
是具有 drwxrwxr-x (775)
权限的文件夹,它应该可以正常工作,因为使用 fopen($FileLog, 'a')
的 PHP 脚本也在同一个 https://example.com
服务器上。你有什么关于为什么只有 777 权限有效的提示吗?我知道 Web 服务器的 drwxrwxrwx (777)
权限是禁忌。谢谢。
更新 1:
使用 fopen($FileLog, 'a')
的 PHP 脚本托管在 https://example.com/loggingscript.php
并由我的 Android 应用程序的 ACRA 库 (https://github.com/ACRA/acra) 调用当它崩溃时。
该目录应归运行网络服务器的用户所有。否则,它需要世界写入权限,以便其他用户可以写入它。
这可能类似于 www-data
或 apache
。如果您不确定这是什么,请参阅
Barmar 的回答就是解决方案。但为了准确记录我所做的,我在下面写下了我的详细步骤。
运行 # ps aux | egrep '(apache|httpd)'
显示用户 运行 网络服务器是 www-data
:
# ps aux | egrep '(apache|httpd)'
www-data 3735 0.0 2.6 273160 12996 ? S 06:25 0:00 /usr/sbin/apache2 -k start
www-data 3736 0.0 2.6 273148 12892 ? S 06:25 0:00 /usr/sbin/apache2 -k start
www-data 3738 0.0 2.6 273216 13092 ? S 06:25 0:00 /usr/sbin/apache2 -k start
www-data 7163 0.0 2.6 273180 12888 ? S 12:56 0:00 /usr/sbin/apache2 -k start
www-data 7165 0.0 2.6 273176 13000 ? S 12:56 0:00 /usr/sbin/apache2 -k start
www-data 8209 0.0 2.6 273200 13032 ? S 14:26 0:00 /usr/sbin/apache2 -k start
www-data 8211 0.0 2.6 273128 12904 ? S 14:26 0:00 /usr/sbin/apache2 -k start
www-data 8219 0.0 2.6 273128 12896 ? S 14:26 0:00 /usr/sbin/apache2 -k start
www-data 8221 0.0 3.3 273192 16412 ? S 14:26 0:00 /usr/sbin/apache2 -k start
www-data 8235 0.0 2.6 273196 13008 ? S 14:26 0:00 /usr/sbin/apache2 -k start
root 12976 0.0 0.2 13136 1048 pts/0 S+ 22:09 0:00 grep -E --color=auto (apache|httpd)
root 29850 0.0 4.7 268240 23488 ? Ss Aug07 0:10 /usr/sbin/apache2 -k start
我将该文件夹的所有权从 root
更改为 www-data
:
# chown www-data logs/
# chgrp www-data logs/
现在,当我拥有 755
作为我的 logs
文件夹的权限时,一切正常。
虽然通常 Barmar 在这里给出了很好的建议,但在这个场合,我不同意 "The directory should be owned by the user that runs the webserver"。
八进制权限中的每个数字,以及权限字符串中的每个"rwx"都与用户、组和任何其他uid相关联(其中用户和组是文件上的属性)。如果您的 PHP 脚本应该写入日志,那么它需要以任何用户、组或其他身份执行和写入目录的权限。虽然通常网络服务器 uid 应该是专用网络服务器主机上权限最低的帐户(因此通过 "other" 授予访问权限),但情况并非总是如此。例如,如果主机上还有一个电子邮件 MTA,那么更好的解决方案可能是 770,并通过组所有权向网络服务器授予访问权限。将网络服务器 uid 设置为目录的所有者应该始终是一个自动危险信号。
您设置的权限模型应反映对文件的所有访问权限,使所有相关方都能访问文件(网络开发人员、备份软件、日志轮换服务帐户) ...)它还应该限制任何未明确打算访问的人的访问。 OP 没有告诉我们与目录关联的 user/group/这是否可变/谁需要什么访问权限)。
I know drwxrwxrwx (777) permissions for a web server is a no-no
不一定 - 这应该 never 是默认设置,但有时它是网络服务器 uid 可写内容的正确配置。人们对此感到兴奋的原因是,对于权限有问题的人来说,它通常被视为一种快速修复,他们不应提供 PHP 对内容的写入访问权限。
这里还暴露了一个 大规模 安全漏洞(在没有未提及的其他缓解措施的情况下)。限制 PHP 可以写的地方的主要原因是为了防止最终用户注入代码。为了实现攻击,攻击者还必须有一种调用他们放置在您服务器上的代码的方法。通常日志包含用户提供的数据 - 因此允许 PHP 写入数据可以启动攻击的第一阶段。如果数据写在文档根目录中,那么它可以通过浏览器 URL 直接寻址。
OP 将权限更改为 755 并没有减轻这种攻击,并且造成了只有 PHP 代码和 root 用户才能在日志文件创建后删除它们的情况。
我正在使用 ACRA (https://github.com/ACRA/acra) 自动将我的 Android 崩溃报告发布到报告服务器。我有一个 PHP 脚本,它使用以下行将日志文件写入测试服务器上的 https://example.com/logs/
文件夹:
$FileLog = $_SERVER['DOCUMENT_ROOT'] . "/logs/" . $fname;
$HandleLog = fopen($FileLog, 'a');
只有当我服务器上的 logs/
文件夹具有这些权限时,PHP fopen()
功能才能正常工作:
drwxrwxrwx (777)
我已经尝试了 drwxrwxr-x (775)
和 drwxr-xr-x (755)
,但 fopen()
功能不起作用。它仅在我使用 drwxrwxrwx (777)
作为 logs/
文件夹权限时有效。
这对我来说很奇怪,因为我 运行 的 PHP 脚本在我的服务器上,所以当我从我的 PHP 文件执行 fopen($FileLog, 'a')
时服务器,如果 https://example.com/logs/
是具有 drwxrwxr-x (775)
权限的文件夹,它应该可以正常工作,因为使用 fopen($FileLog, 'a')
的 PHP 脚本也在同一个 https://example.com
服务器上。你有什么关于为什么只有 777 权限有效的提示吗?我知道 Web 服务器的 drwxrwxrwx (777)
权限是禁忌。谢谢。
更新 1:
使用 fopen($FileLog, 'a')
的 PHP 脚本托管在 https://example.com/loggingscript.php
并由我的 Android 应用程序的 ACRA 库 (https://github.com/ACRA/acra) 调用当它崩溃时。
该目录应归运行网络服务器的用户所有。否则,它需要世界写入权限,以便其他用户可以写入它。
这可能类似于 www-data
或 apache
。如果您不确定这是什么,请参阅
Barmar 的回答就是解决方案。但为了准确记录我所做的,我在下面写下了我的详细步骤。
运行 # ps aux | egrep '(apache|httpd)'
显示用户 运行 网络服务器是 www-data
:
# ps aux | egrep '(apache|httpd)'
www-data 3735 0.0 2.6 273160 12996 ? S 06:25 0:00 /usr/sbin/apache2 -k start
www-data 3736 0.0 2.6 273148 12892 ? S 06:25 0:00 /usr/sbin/apache2 -k start
www-data 3738 0.0 2.6 273216 13092 ? S 06:25 0:00 /usr/sbin/apache2 -k start
www-data 7163 0.0 2.6 273180 12888 ? S 12:56 0:00 /usr/sbin/apache2 -k start
www-data 7165 0.0 2.6 273176 13000 ? S 12:56 0:00 /usr/sbin/apache2 -k start
www-data 8209 0.0 2.6 273200 13032 ? S 14:26 0:00 /usr/sbin/apache2 -k start
www-data 8211 0.0 2.6 273128 12904 ? S 14:26 0:00 /usr/sbin/apache2 -k start
www-data 8219 0.0 2.6 273128 12896 ? S 14:26 0:00 /usr/sbin/apache2 -k start
www-data 8221 0.0 3.3 273192 16412 ? S 14:26 0:00 /usr/sbin/apache2 -k start
www-data 8235 0.0 2.6 273196 13008 ? S 14:26 0:00 /usr/sbin/apache2 -k start
root 12976 0.0 0.2 13136 1048 pts/0 S+ 22:09 0:00 grep -E --color=auto (apache|httpd)
root 29850 0.0 4.7 268240 23488 ? Ss Aug07 0:10 /usr/sbin/apache2 -k start
我将该文件夹的所有权从 root
更改为 www-data
:
# chown www-data logs/
# chgrp www-data logs/
现在,当我拥有 755
作为我的 logs
文件夹的权限时,一切正常。
虽然通常 Barmar 在这里给出了很好的建议,但在这个场合,我不同意 "The directory should be owned by the user that runs the webserver"。
八进制权限中的每个数字,以及权限字符串中的每个"rwx"都与用户、组和任何其他uid相关联(其中用户和组是文件上的属性)。如果您的 PHP 脚本应该写入日志,那么它需要以任何用户、组或其他身份执行和写入目录的权限。虽然通常网络服务器 uid 应该是专用网络服务器主机上权限最低的帐户(因此通过 "other" 授予访问权限),但情况并非总是如此。例如,如果主机上还有一个电子邮件 MTA,那么更好的解决方案可能是 770,并通过组所有权向网络服务器授予访问权限。将网络服务器 uid 设置为目录的所有者应该始终是一个自动危险信号。
您设置的权限模型应反映对文件的所有访问权限,使所有相关方都能访问文件(网络开发人员、备份软件、日志轮换服务帐户) ...)它还应该限制任何未明确打算访问的人的访问。 OP 没有告诉我们与目录关联的 user/group/这是否可变/谁需要什么访问权限)。
I know drwxrwxrwx (777) permissions for a web server is a no-no
不一定 - 这应该 never 是默认设置,但有时它是网络服务器 uid 可写内容的正确配置。人们对此感到兴奋的原因是,对于权限有问题的人来说,它通常被视为一种快速修复,他们不应提供 PHP 对内容的写入访问权限。
这里还暴露了一个 大规模 安全漏洞(在没有未提及的其他缓解措施的情况下)。限制 PHP 可以写的地方的主要原因是为了防止最终用户注入代码。为了实现攻击,攻击者还必须有一种调用他们放置在您服务器上的代码的方法。通常日志包含用户提供的数据 - 因此允许 PHP 写入数据可以启动攻击的第一阶段。如果数据写在文档根目录中,那么它可以通过浏览器 URL 直接寻址。
OP 将权限更改为 755 并没有减轻这种攻击,并且造成了只有 PHP 代码和 root 用户才能在日志文件创建后删除它们的情况。