必须关闭 cgi.fix_pathinfo=1,否则 nginx+php-cgi 存在路径解析绕过漏洞,攻击者可通过 /1.jpg/xxx.php 执行任意 php 文件;该问题源于 php-cgi 对 script_filename 的错误截断逻辑,导致真实文件存在时仍按畸形路径执行 php,需在 php.ini 中显式设为 0 并重启服务验证。

必须关闭 cgi.fix_pathinfo,否则 Nginx + PHP-CGI 组合存在路径解析绕过风险,攻击者可通过 /1.jpg/xxx.php 这类畸形 URL 触发任意 PHP 文件执行。
为什么 php-cgi 默认开启 cgi.fix_pathinfo=1 会出问题
PHP-CGI 在处理请求时,若 cgi.fix_pathinfo=1(默认值),会对 SCRIPT_FILENAME 做“智能截断”:当请求路径含多个点或斜杠(如 /upload/1.jpg/xxx.php),它会从右往左找第一个 .php,再往前匹配真实文件是否存在。如果 /upload/1.jpg 存在,就认定 /upload/1.jpg/xxx.php 的脚本路径是 /upload/1.jpg,但依然用 xxx.php 去解析执行——这就绕过了后缀白名单检查。
这个行为在 PHP 5.3.11 及更早版本中尤其危险,且无法通过 Nginx 的 try_files 完全拦截,因为 FastCGI 请求已由 PHP-CGI 接收并错误解析。
关闭方式:优先改 php.ini,不是 nginx 配置
很多教程建议在 Nginx 中加正则判断(如 if ($fastcgi_script_name ~ \..*\/.*php) { ... }),但这只是补丁,治标不治本,且容易被绕过。真正可靠的修复必须落在 PHP 层。
- 找到 PHP-CGI 实际加载的
php.ini:运行php-cgi -i | grep "Loaded Configuration File",注意是php-cgi而非php,二者配置文件可能不同 - 在该
php.ini中添加或修改这一行:cgi.fix_pathinfo=0(即使原文件没这行,也必须显式写上) - 重启 PHP-CGI 进程(如
killall php-cgi或重启 spawn-fcgi / systemd service) - 验证是否生效:创建一个
info.php,内容为<?php echo ini_get('cgi.fix_pathinfo'); ?>,访问后输出应为0
验证是否还存在漏洞的简单方法
部署一个仅含 <?php phpinfo(); ?> 的 test.jpg 文件到 Web 目录,然后用 curl 测试:
curl http://your-site/test.jpg/xxx.php
如果页面返回了 PHP 信息,则漏洞仍在;如果返回 404 或直接下载 test.jpg,说明 cgi.fix_pathinfo=0 已生效。
注意:某些旧版 PHP-CGI(如 5.3.11)即使设为 0,仍可能因内部路径拼接逻辑残留风险,因此升级 PHP 版本仍是根本解法——5.3 系列早已停止维护,CVE-2026-109618 等新漏洞也不再修复。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











