设置555/444权限后PHP touch()仍可执行?PHP7.2下是否为预期行为?
关于PHP 7.2中touch()不受文件/目录权限限制的问题
首先明确:这个现象不是PHP 7.2的预期行为,核心原因和Unix系统的权限模型、PHP运行的用户身份密切相关,咱们一步步拆解:
先搞清楚touch()的两种操作场景及权限要求
PHP的touch()函数有两种核心行为,对应的权限要求完全不同:
- 创建新文件:这时候依赖的是目标目录的写入权限。如果目录权限是555(只有读、执行权限,无写入),正常情况下
touch()创建文件会直接失败——除非你的PHP进程是以root身份运行,或者目录通过POSIX ACL给PHP运行用户额外开了写入权限。 - 修改已有文件的时间戳:这时候依赖的是目标文件的写入权限。如果文件是444(仅读权限),正常情况下
touch()无法修改时间戳,但有两种例外:- PHP运行用户是该文件的所有者(Unix系统中,文件所有者拥有特殊权限,即使文件设为444,部分系统下所有者仍能修改时间戳,不过这不是普遍情况,更多取决于系统配置);
- 文件或目录通过ACL给PHP运行用户额外赋予了写入权限。
你需要先排查这几个点
- 确认touch()到底在做什么:是创建新文件,还是修改已有文件的时间?可以对比操作前后目录里的文件数量,或者直接查看文件的创建/修改时间变化。
- 检查PHP运行的用户身份:在PHP脚本里执行
echo exec('whoami');或者var_dump(posix_getpwuid(posix_geteuid()));,看看PHP是以哪个用户运行的(通常是www-data、apache之类的)。 - 核实目录和文件的实际权限:用终端执行
ls -ld /你的目录路径和ls -l /你的文件路径,确认权限确实是555/444,同时看所有者是不是和PHP运行用户一致。 - 检查ACL权限:执行
getfacl /你的目录路径和getfacl /你的文件路径,看看有没有额外的权限规则给PHP用户开了后门。
如何彻底阻止touch()执行
根据你的需求,这里有几个可行方案:
- 针对创建新文件:确保目录权限是555,且PHP运行用户不是root,同时清理目录的ACL额外权限。
- 针对修改已有文件时间戳:如果PHP是文件所有者,你可以把文件的所有者改成其他用户(比如root),这样即使PHP用户有读权限,也没法修改时间戳;或者直接在php.ini里添加
disable_functions = touch,彻底禁用这个函数。 - 额外安全层:可以配置PHP的
open_basedir限制文件操作范围,或者用SELinux、AppArmor这类系统安全模块进一步锁定文件权限。
内容的提问来源于stack exchange,提问作者suncat100
相关产品推荐
相关产品推荐

