我正试图使用realpath()来避免目录遍历攻击,但我不太明白为什么它在一个肯定存在的文件上返回false。
这些文件托管在Apache用户可以访问的NFS共享上。除了文件本身为777之外,整个层次结构为755。
下面是一个代码片段:
$path = "/mnt/share/path/to/20160111-133552-msg0000.wav";
$path = realpath($path);
var_dump($path);
结果是:
bool(false)
文件肯定在那里。我登录到Apache用户并运行:
bash-4.2$ ls -lah /mnt/share/path/to/20160111-133552-msg0000.wav
-rwxrwxrwx. 1 1001 1001 77K Jan 11 13:35 /mnt/share/path/to/3000-20160111-133552-msg0000.wav
另一个观察结果是:当我从$path变量中删除文件名时:
$path = "/mnt/share/path/to/
它运行得很好:
string(39) "/mnt/share/path/to"
以前有人遇到过这种行为吗?
我想这是我自己想出来的!Good ol’selinux阻止httpd访问文件:
type=AVC msg=audit(1452550767.071:18495): avc: denied { read } for pid=10397 comm="httpd" name="3000-20160111-133552-msg0000.wav" dev="0:41" ino=12483 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:nfs_t:s0 tclass=file
Was caused by:
One of the following booleans was set incorrectly.
Description:
Allow httpd to use nfs
Allow access by executing:
# setsebool -P httpd_use_nfs 1
我是在尝试对有问题的.wav文件执行readfile()操作时才发现这一点的,但遇到了拒绝权限的错误,这在777文件上没有意义。检查了/var/log/audit/audit.log,这是显而易见的。
运行setsebool -P httpd_use_nfs 1
为我修复了它。
不要认为以下是真的:这个答案是基于对访问权限的详细组合的记错而写的:755已经允许所有人执行了
你说:
除了文件本身是777之外,整个层次结构是755。
而PHP手册页面上写着:
运行的脚本必须对层次结构中的所有目录具有可执行权限,否则realpath()将返回FALSE。
因此,您需要将整个层次结构设置为777,以使realpath()
工作。