我正在运行 LEMP 堆栈,并希望为其编写一个简单的控制面板。
所以,我希望能够php-fpm
从 php 脚本重新启动。为了实现这一目标,这就是我所做的。
c
像这样创建了一个二进制包装器php-shell.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CMN_LEN 100
int main(int argc, char *argv[])
{
char cmd[MAX_CMN_LEN] = "", **p;
if (argc < 2)
{
fprintf(stderr, "Usage: ./php_shell terminal_command ...");
exit(EXIT_FAILURE);
}
else
{
strcat(cmd, argv[1]);
for (p = &argv[2]; *p; p++)
{
strcat(cmd, " ");
strcat(cmd, *p);
}
system(cmd);
}
return 0;
}
这个程序是这样编译的:
gcc php_shell.c -o php_shell
然后我添加了 nginx 用户,如下所示sudo visudo
:
Defaults:nginx !requiretty
nginx ALL=(ALL) NOPASSWD:/path/to/php_shell
然后我在 php 脚本中执行命令,如下所示:
var_dump(shell_exec('sudo /path/to/php_shell "service nginx restart" 2>&1'));
一旦我运行这个脚本 php 脚本,我就会502 Gateway Error
发现所有php-fpm
进程都已被终止并且不会启动备份。
有任何想法吗?我这样做错了吗?我希望能够通过执行从 php 脚本重新启动 nginx 服务器service nginx restart
。我怎样才能实现这个目标?
答案1
恭喜!您正在向任何可以让您的 nginx 服务器运行任意代码的人授予不受限制的 root 访问权限。您最好确保每个 CGI 脚本和 php 页面以及任何其他可能用于执行任意代码的内容都是安全的。
您的 C 包装器相当于配置 sudo 以允许 nginx 以 root 身份运行任何命令。
不就那样做。
为特定命令编写单独的 shell 脚本(或其他)包装器,然后仅向这些包装器脚本授予 sudo 访问权限。例如,/usr/local/sbin/restart-nginx.sh
这确实是没有什么但是service nginx restart
并给予 nginx sudo 访问该脚本的权限。
然后编写另一个完全独立的脚本来运行,例如,dmidecode -s system-uuid
如上一个问题所示。并授予 nginx sudo 访问该脚本的权限。
每个单独的脚本越简单、越简单越好。最安全的是根本不接受任何用户输入,不从命令行或环境变量中进行输入。
如果某些包装器脚本必须接受用户输入,请在使用之前进行完整性检查并清理所有用户提供的输入。并引用你的变量 - 例如总是使用"$variable"
而不是不带$variable
引号。
如果您的包装器脚本变得过长且复杂,则尝试仅识别需要以 root 身份运行的最小命令或命令集,并将它们编写为单独的脚本(或多个脚本),这些脚本由sudo
主脚本调用。即尽可能少地以 root 身份运行。