核心原则是nginx与php-fpm进程用户必须分离且不能为网站文件所有者,须遵循最小权限原则;网站根目录属部署账户,仅上传等特定目录对php-fpm可写,并通过open_basedir、disable_functions、socket权限限制及nginx访问控制等多层加固。

核心原则是:Nginx 工作进程与 PHP-FPM 子进程不能以网站文件所有者身份运行,且二者用户需分离、权限需最小化。越权访问往往不是来自网络攻击,而是权限配置失当导致 WebShell 或漏洞利用后获得远超预期的文件操作能力。
分离 Nginx 与 PHP-FPM 的运行用户
这是最根本的安全动作。若两者都用 www-data(或 nobody)且网站文件也属该用户,一旦 PHP 被植入一句话木马,它就能直接改写源码、删除日志、读取 .env 文件——因为权限完全一致。
- Nginx 配置中设置 user www-data;(Ubuntu/Debian)或 user nginx;(CentOS/RHEL)
- PHP-FPM 的 pool 配置(如 /etc/php/*/fpm/pool.d/www.conf)中明确指定:
user = www-data<br>group = www-data<br>listen.owner = www-data<br>listen.group = www-data
- 网站根目录(如 /var/www/html)的所有者设为部署账户(如 deploy),而非 www-data:
sudo chown -R deploy:www-data /var/www/html - 关键目录(如 uploads、cache)才赋予 PHP-FPM 用户可写权限:
sudo chmod 755 /var/www/html && sudo chmod 775 /var/www/html/uploads
限制 PHP-FPM 进程的文件系统视野
即使 PHP 脚本被攻陷,也要阻止其读取系统敏感文件或跨站读取其他项目。
- 在 PHP-FPM 的 pool 配置中启用 open_basedir:
php_admin_value[open_basedir] = /var/www/html:/tmp - 禁用高危函数(在同 pool 配置中添加):
php_admin_value[disable_functions] = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source - 关闭 PHP 版本暴露:
expose_php = Off(在 /etc/php/*/apache2/php.ini 或 fpm/php.ini 中)
加固 Unix socket 权限与通信路径
PHP-FPM 默认使用 Unix socket(如 /run/php/php8.2-fpm.sock),但若 socket 文件权限过宽(如 srwxrwxrwx),本地任意用户都可向其发 FastCGI 请求——相当于绕过 Nginx 直连后端。
- 确保 listen.mode 设为 0660(仅 owner/group 可读写)
- 确认 listen.owner 和 listen.group 与 Nginx worker 用户一致(如 www-data)
- 检查 socket 文件实际权限:
ls -l /run/php/php8.2-fpm.sock 应显示 srw-rw----,属主属组均为 www-data - 避免使用 TCP 监听(如 127.0.0.1:9000),除非容器等特殊场景;若必须用,防火墙须严格限制仅本机访问
配合 Nginx 层做访问控制兜底
权限隔离是基础,Nginx 配置是第二道防线,能拦截常见越权尝试。
- 禁止访问敏感后缀:
location ~* \.(env|ini|log|sh|bak|swp|git|htaccess|php\.bak)$ { deny all; } - 防御路径遍历:
location ~ (\.\.\/|\/\.) { return 403; } - 限制上传目录执行 PHP:
location ^~ /uploads/ { location ~ \.php$ { deny all; } } - 确保 SCRIPT_FILENAME 使用 $document_root 动态拼接,不写死路径,防止因 root 配置错误导致脚本被当作静态文件下载
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











