如何在非自有文件夹中运行来自apache用户的脚本


How to run a script from apache user in non owned folder?

我发现了许多问题,这些问题是通过在权限上打开巨大的漏洞或更改文件的用户所有权来实现的。对于我目前的申请来说,这两种都不是一种选择。我想做的是,当点击网页上的按钮时,使用shell_exec或类似的php函数在系统上一个完全不同的文件夹中运行.sh脚本。脚本必须从它所在的文件夹中运行。我在debian上,已经安装了sudo,允许apache用户通过添加以下行来运行命令:

www-data ALL=(ALL) NOPASSWD:/opt/folder/run.sh start
www-data ALL=(ALL) NOPASSWD:/opt/folder/run.sh stop
www-data ALL=(ALL) NOPASSWD:/opt/folder/run.sh status

run.sh不允许我编辑,所以如果可能的话,我必须在apache端管理它。我不允许更改run.sh的权限或所有权。所以你可以看到我的困境。我使用的php调用如下所示:

$test=shell_exec('cd /opt/folder/  && ./run.sh start&& cd -');

我正在使用$test来回显命令的输出。这就是它变得奇怪的地方。该命令输出良好。run.sh脚本用于启动和停止其他程序的列表,并显示它们的状态。我可以运行./run.sh status,并在$test变量中获得良好的结果。如果我尝试./run.sh stop,它会说它有效(我很确定run.sh脚本没有内置太多检查),但系统上实际上什么都没有发生。我可以运行ps -ef | grep作为健全性检查,并查看所有应该停止的进程。如果我运行./run.sh start也是一样的,但它会返回没有启动任何程序。

尽管如此,我只是想弄清楚我做错了什么。我确信php正在运行bash脚本,但由于某种原因,它无法实际运行脚本中的任何启动或停止命令。我也可以从操作系统以root身份完全运行run.sh。在这件事上,我真的是走投无路了,所以我们非常感谢任何帮助。如果这是不可能的,那么有没有一个不需要额外安装程序的替代方案。

因此,经过几次尝试后,我决定将其保存以备以后使用。我意识到,虽然我允许apache用户以root身份运行脚本,但我并没有真正告诉它

$test=shell_exec('cd /opt/folder/  && sudo ./run.sh start&& cd -');

添加的sudo现在告诉脚本以root身份运行,并且visudo中的条目允许它在不要求密码的情况下这样做。我确实更改了我的visodu文件,使其更加精简,所以现在它只有一行。

www-data ALL=(ALL) NOPASSWD:/opt/folder/run.sh

这既符合安全要求又符合用户约束。几乎没有像chmod 777或类似程序那样打开的攻击向量,apache用户只能访问带有硬编码参数的run.sh脚本。

我最近发布了一个项目,该项目允许PHP获得真正的Bash shell并与之交互(如果请求,可以作为root,但我认为您不需要它),它解决了exec()和shell_exec()的限制。在这里获取:https://github.com/merlinthemagic/MTS

下载后,您只需使用以下代码:

$shell    = 'MTS'Factories::getDevices()->getLocalHost()->getShell('bash', false);
$return1  = $shell->exeCmd('cd /opt/folder/');
$return2  = $shell->exeCmd('./run.sh start');
$return3  = $shell->exeCmd('cd -');
//the return will be a string containing the return of the command
echo $return1;
echo $return2;
echo $return3;

由于您不需要root,因此实际上没有任何安全问题。安装软件包时,只需跳过有关设置sudo的部分。

此外,如果你的"run.sh"需要很长时间才能完成,你将需要更改一个命令的超时,如下所示:

//is one hour enough?
$timeout = 3600000;
$return2 = $shell->exeCmd('./run.sh start', null, $timeout);