phpEnv 的 Nginx 默认允许任意目录执行 PHP,因其仅配置宽泛的 location ~ \.php$ 规则,未按目录精细化限制,导致上传目录如 /upload/ 下的 shell.php 可被直接访问执行。

phpEnv 是一个 Windows 下的 PHP 集成环境(类似 XAMPP),自带 Nginx + PHP-FPM,但它的默认配置**不禁止上传目录执行 PHP**,一旦用户上传了 shell.php 到 /upload/ 或 /images/,就能直接访问执行——这是真实发生过的入侵入口。
为什么 phpEnv 的 Nginx 默认允许任意目录执行 PHP
phpEnv 的 nginx.conf 通常只有一条宽泛的 location ~ \.php$ 匹配规则,没有按目录做精细化控制。它会把所有以 .php 结尾的请求,不管路径是 /index.php 还是 /upload/test.php,全都转发给 PHP-FPM 执行。
- 它没区分“入口文件”和“上传文件”,
/upload/目录下本不该有可执行脚本 - 它没加
^~ /upload/这类前缀匹配块来提前拦截 - 它的
root路径常设为网站根目录(如C:/phpEnv/www),导致子目录天然可被解析
在 phpEnv 中禁用指定目录的 PHP 执行(实操步骤)
打开 phpEnv 安装目录下的 nginx/conf/vhost/xxx.conf(或主配置 nginx/conf/nginx.conf 中的 server 块),在 location ~ \.php$ { ... } 之前 插入以下任一配置:
- 禁止单个上传目录:
location ~* ^/upload/.*\.(php|php5|phtml)$ { deny all; } - 禁止多个敏感目录:
location ~* ^/(upload|images|static|data|cache)/.*\.(php|php5|phtml)$ { deny all; } - 更彻底:禁止所有非入口路径的 PHP(推荐):
location ~* ^/(?!index\.php|api/).*\.(php|php5|phtml)$ { deny all; }
⚠️ 注意:必须放在 location ~ \.php$ 上方,否则会被后者的正则先命中、直接转发,前面的 deny all 形同虚设。
立即学习“PHP免费学习笔记(深入)”;
绕过检测的常见构造及防御补丁
攻击者会尝试 /upload/x.jpg/.php、/upload/.php、/upload/xxx.PHP 等方式绕过简单后缀过滤。仅靠 ~ \.php$ 不够。
- 加
^~ /upload/前缀匹配,优先级高于正则,能覆盖/upload/.php这类无后缀的请求:location ^~ /upload/ { deny all; } - 关闭大小写敏感:
location ~* \.(php|phtml|php5)$中的*已启用,但确保没漏掉.phP或.PHP3,可扩展为\.(php|phtml|php[3-7]|phar|inc)$ - 配合系统层权限:进到
C:/phpEnv/www/upload,右键 → 属性 → 安全 → 编辑 → 拒绝IIS_IUSRS或Everyone的“执行”权限(Windows 下等效于chmod -x)
验证是否真正生效的三个必测点
改完配置后,nginx -t && nginx -s reload,然后手动验证:
- 上传一个
test.php到/upload/,访问http://localhost/upload/test.php→ 必须返回403 Forbidden或404 Not Found,不能显示源码、也不能执行 - 访问
http://localhost/upload/.php→ 同样应 403/404(测试前缀匹配是否生效) - 访问
http://localhost/index.php→ 必须正常加载(确保没误杀合法入口)
容易被忽略的是:phpEnv 的 Nginx 进程默认以当前登录用户身份运行,没有降权机制;如果该用户有管理员权限,即使 Nginx 配置正确,恶意脚本仍可能通过系统调用逃逸。所以,上传目录的 Windows ACL 权限控制不是可选项,而是最后一道防线。



















