在Ubuntu 16.04.3 LTS服务器上,网页调用运行可执行文件的PHP脚本。即使属于root的可执行文件(这些可执行文件具有访问模式0755),这也可以正常工作。
但是,当网页调用PHP脚本运行可执行文件,并且该可执行文件尝试打开文件进行读取时,程序会运行但无法打开该文件。
需要更改什么以便Apache(www-data)可以运行可执行文件(我用C编写)打开文件进行阅读?
让我们调用可执行文件ExecutableFile。要打开以供读取的文件可以称为FileToRead,它位于名为DirectoryContainingFileToRead的目录中。该目录与ExecutableFile位于同一目录中。
在命令行中给出了ExecutableFile FileToRead。它知道在DirectoryContainingFileToRead中查找。如果找到它,它将参考此文件计算结果。如果找不到,程序将计算默认结果。
PHP使用其exec()函数调用可执行文件,如下所示:
$data = exec('./ExecutableFile FileToRead OtherArgument 2>&1');
这是我已经尝试过的,无济于事:
更改所涉及文件的所有权。 ExecutableFile具有模式755。 DirectoryContainingFileToRead具有模式755。 FileToRead具有模式644。
chown www-data.www-data ExecutableFile
chown www-data.www-data DirectoryContainingFileToRead
chown www-data.www-data DirectoryContainingFileToRead/FileToRead
这不会产生任何变化。 (如上所述,其他不尝试打开文件的可执行文件仍会在被www-data调用时运行,即使它们属于root.root。这些可执行文件具有读取和执行权限。)
与上述相同,但将该组保留为root:
chown www-data.root ExecutableFile
chown www-data.root DirectoryContainingFileToRead
chown www-data.root DirectoryContainingFileToRead/FileToRead
这不会产生任何变化。返回默认结果。
将所有文件保留为root的属性并仅更改ExecutableFile上的粘滞位:
chown root.root ExecutableFile
chown root.root DirectoryContainingFileToRead
chown root.root DirectoryContainingFileToRead/FileToRead
chmod +s ExecutableFile
这不会产生任何变化:可执行文件仍会运行,但它不会打开文件。
更改所有涉及的文件的粘滞位:
chown root.root ExecutableFile
chown root.root DirectoryContainingFileToRead
chown root.root DirectoryContainingFileToRead/FileToRead
chmod +s ExecutableFileName
chmod +s DirectoryContainingFileToRead
chmod +s DirectoryContainingFileToRead/FileToRead
这不会产生任何变化:程序运行但不会打开文件。返回默认结果。
将所有文件的所有者更改为www-data并仅为ExecutableFile设置粘滞位:
chown www-data.root ExecutableFile
chown www-data.root DirectoryContainingFileToRead
chown www-data.root DirectoryContainingFileToRead/FileToRead
chmod +s ExecutableFileName
相同的默认结果。
重新编译程序以使用setuid(0);在尝试打开文件之前:
FILE* fp;
char fpath[64];
int currentUID = getuid(); // Save given UID
sprintf(fpath, "./DirectoryContainingFileToRead/%s", FileToRead);
if(setuid(0) < 0) // Briefly become root
{
printf("Unable to become root\n");
exit(1);
}
fp = fopen(fpath, "rb");
if(fp == NULL)
{
// Proceed without use of the file
}
else
{
// Make use of the file
fclose(fp);
}
if(setuid(currentUID) < 0) // Resume being yourself
{
printf("Unable to resume given identity\n");
exit(1);
}
尝试成为root时退出。 ExecutableFile有755. DirectoryContainingFileToRead有755.FileToRead有644。
与尝试6相同,但也在可执行文件中设置粘滞位。
chmod +s ExecutableFile
这至少会在不退出的情况下运行,但结果表明它不会打开文件。
与尝试6相同,但在所有涉及的文件上设置粘滞位:
chmod +s ExecutableFileName
chmod +s DirectoryContainingFileToRead
chmod +s DirectoryContainingFileToRead/FileToRead
同样,这至少会运行,但结果表明该程序不允许访问该文件。
我正在为此撕开我的头发。我整天都在研究这个问题。我已经就StackOverflow,Wikipedia,Tanenbaum&amp; amp; Bos'现代操作系统。所有这些来源都表明权限受到威胁,但我尝试的解决方案都没有在实践中发挥作用。任何见解都将受到赞赏。
答案 0 :(得分:0)
哦,伙计。这背后是一个愚蠢的疏忽:
如果我使用要读取的文件的绝对路径,一切正常:
sprintf(fpath, "/var/long/path/DirectoryContainingFileToRead/%s", FileToRead);
不需要粘性位。我甚至不需要chown
任何东西:ExecutableFile,DirectoryContainingFileToRead和FileToRead都属于root。只需确保可执行文件和目录已由任何已启用的读取和执行。要阅读的文件应该是任何人都可读的。
要明确,PHP会这样调用:
$data = exec('../../ExecutableFile FileToRead OtherArgument 2>&1');
我在原帖中省略了PHP使用的相对路径,认为它不相关。事实上,有必要彻底了解这个问题。
PHP命令中的相对路径。 C代码中的绝对路径。
这么多浪费了加重......