PHP 8.3.7 本身无官方认定的 php-cgi 漏洞,所谓“php-cgi 漏洞”实为 Nginx + PHP-FPM 配置不当引发的 FastCGI 路径解析缺陷,核心在于 location 正则不严谨、未用 try_files 校验文件存在性、fastcgi_split_path_info 规则宽松,导致如 /index.php/xxx.jpg 类请求被错误解析执行。

PHP 8.3.7 本身没有官方认定的 php-cgi 漏洞,所谓“php-cgi 漏洞”通常指 CGI 路径解析缺陷(如 CVE-2012-1823)或 FastCGI 协议误配置导致的任意代码执行,这类问题与 PHP 版本无关,而是 Nginx + PHP-FPM 配置不当引发的。防护重点不在升级 PHP,而在堵住 Nginx 的 FastCGI 请求转发逻辑漏洞。
为什么 Nginx 会把非 PHP 文件当 php-cgi 执行
根本原因是 Nginx 的 fastcgi_split_path_info 和 try_files 配置不严谨,导致攻击者构造类似 /index.php/xxx.jpg 的 URI,让 Nginx 错误地将 .jpg 后缀文件交给 PHP-FPM 解析执行。
- 典型错误配置:
location ~ \.php$ { ... fastcgi_pass 127.0.0.1:9000; }—— 这种正则只匹配结尾为.php的路径,但没校验中间是否夹带恶意路径 - 更危险的是用了
location ~ \.php(缺少$),会导致/xxx.php.jpg也被匹配 - 若同时启用了
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;且未用try_files $fastcgi_script_name =404;校验文件存在性,攻击者就能绕过文件后缀限制
必须加上的三行关键防护配置
在 Nginx 的 PHP location 块中,必须显式加入以下三行,缺一不可:
-
try_files $fastcgi_script_name =404;—— 强制要求$fastcgi_script_name对应的真实文件必须存在,否则返回 404;这能直接拦截/index.php/xxx.jpg类攻击 -
fastcgi_split_path_info ^(.+?\.php)(/.*)$;—— 严格定义路径拆分规则,只允许.php后紧跟/开头的路径信息,拒绝.php.jpg等畸形组合 -
include fastcgi_params;(且确认其中fastcgi_param SCRIPT_FILENAME使用的是$document_root$fastcgi_script_name,不是$document_root$fastcgi_path_info)—— 避免把用户可控的$fastcgi_path_info拼进执行路径
验证是否已修复:用 curl 测试边界请求
部署配置后,立刻用以下命令验证是否仍可被利用:
立即学习“PHP免费学习笔记(深入)”;
-
curl -I http://yoursite.com/index.php/xxx.jpg—— 正常应返回404 Not Found或403 Forbidden,若返回200 OK或502 Bad Gateway,说明仍存在风险 -
curl -I http://yoursite.com/test.jpg/phpinfo.php—— 若 Nginx 错误地把test.jpg当作脚本目录处理,可能触发异常响应 - 检查 Nginx error log 中是否有
FastCGI sent in stderr: "Primary script unknown"—— 这是try_files生效的标志;若日志里大量出现Permission denied或空响应,则可能是SCRIPT_FILENAME拼接出错,需回查路径变量
额外注意:PHP-FPM 自身的权限隔离不能省
即使 Nginx 配置正确,若 PHP-FPM 进程以高权限运行(如 root 或网站目录可写用户),一旦其他漏洞被利用,后果依然严重:
- 确保
www.conf中user和group是独立低权用户(如www-data),而非nobody或root - 设置
php_admin_value[open_basedir]限制 PHP 只能访问指定目录,例如:php_admin_value[open_basedir] = /var/www/site/:/tmp/ - 禁用高危函数(虽不能替代配置防护):
php_admin_value[disable_functions] = system,exec,passthru,shell_exec,proc_open,popen,pcntl_exec
真正起作用的从来不是某一行代码,而是 Nginx 的路径解析逻辑、PHP-FPM 的执行上下文、文件系统权限这三层之间严丝合缝的配合;少一层,攻击链就可能重新闭合。



















