网站上传目录禁止脚本执行,Nginx配置代码
网站被上传木马,多数情况是上传目录里的PHP文件被直接访问执行了。
用Nginx把上传目录限制为只能读取静态文件、不能执行脚本,是成本最低、见效最快的一层防护。
下面从判断目录、写配置、验证结果三个环节讲清楚,配置可直接复制后按自己的路径修改。
先确认哪些目录需要禁止执行
不是所有目录都要限制,通常只处理用户能写入的目录。
常见的有:
uploads、upload、attachment:用户上传的图片、附件images、img、avatar:头像、商品图data、cache:程序生成的缓存或数据目录- 后台编辑器、富文本上传目录,如
ueditor/php/upload
判断方法:登录服务器,进入网站根目录,用 ls 看目录结构,凡是程序允许用户提交文件的位置,都列入清单。
这一步不要凭感觉,建议对照程序官方文档确认上传路径。
这里有一个容易忽略的判断条件:如果目录里本身就有需要执行的PHP文件,
比如某些老程序的 data 目录存放配置文件,
就不能整目录禁止执行,
否则网站会报500或白屏。 先确认目录里没有业务脚本,
再动手配置。
核心Nginx配置代码
在网站对应的 server {} 块内,添加一个 location 匹配规则。
以下以禁止 uploads 目录执行PHP为例:
location ~* ^/uploads/.*\.(php|php5|php7|phtml|jsp|asp|aspx|sh)$ {
deny all;
return 403;
}
这段配置的含义:匹配 /uploads/ 路径下所有以 php、phtml、jsp 等脚本后缀结尾的请求,直接返回403。~* 表示不区分大小写,避免攻击者用 .PHP 绕过。
如果希望更彻底,连执行入口都不给,可以把整个上传目录的脚本请求交给静态处理:
location ^~ /uploads/ {
location ~* \.(php|php5|php7|phtml|jsp|asp|aspx|sh)$ {
deny all;
return 403;
}
}
^~ 表示前缀匹配且优先于正则,这样 /uploads/ 下的脚本请求会被内层规则拦截,普通图片请求正常返回。
宝塔面板用户操作路径:网站 → 设置 → 配置文件,把上面的 location 粘贴到 server {} 内部,保存后重载Nginx。
手动编译环境则编辑 /etc/nginx/conf.d/你的站点.conf 或 /usr/local/nginx/conf/vhost/站点.conf,改完执行:
nginx -t && nginx -s reload
nginx -t 用于检查语法,显示 syntax is ok 和 test is successful 再重载,避免配置错误导致网站无法访问。
多目录批量禁止的写法
如果上传目录不止一个,可以用正则一次匹配多个目录名,减少重复配置:
location ~* ^/(uploads|images|avatar|attachment|data)/.*\.(php|php5|php7|phtml|jsp|asp|aspx|sh)$ {
deny all;
return 403;
}
这里有一个关键判断:如果你使用的是ThinkPHP、Laravel等框架,入口文件在public目录,上传目录路径要按实际URL路径写,不能照抄示例。 比如URL访问是 https://域名/uploads/a.php,规则里就写 ^/uploads/;
如果URL里带二级路径,要相应调整正则。
配置写完后,务必用 nginx -t 验证语法,再重载。
配置后如何验证是否生效
验证不能只看配置文件,要在浏览器或命令行实际请求一个测试文件。
方法一:在服务器上传目录放一个测试文件:
echo '' > /www/wwwroot/你的站点/uploads/test.php
然后访问 https://你的域名/uploads/test.php。
预期结果是返回403页面,而不是输出 test。
确认后删除测试文件。
方法二:用 curl 在服务器本机请求:
curl -I https://你的域名/uploads/test.php
返回头里出现 HTTP/1.1 403 Forbidden 即为生效。
同时要确认正常图片仍可访问,访问 https://你的域名/uploads/正常图片.jpg 应返回200,避免规则误伤静态资源。
避坑与常见问题
规则位置放错:location 必须放在对应站点的 server {} 块内,放到 http {} 全局块会影响所有站点,容易误伤其他业务。
deny all 和 return 403 同时写:两者取其一即可,同时写虽然不报错,但没必要。
推荐用 return 403,语义更直接。
忽略了大小写:必须用 ~* 而不是 ~,否则攻击者用 .PHP 后缀可能绕过。
只禁PHP没禁其他脚本:如果服务器装了其他解析器,建议把 jsp、asp、sh 一并写入后缀列表;
不确定装了哪些解析器,可以查看 nginx -V 输出和 conf 目录下的解析配置。
配置后网站白屏:先执行 nginx -t 看是否语法错误,再检查是否误伤了业务目录。
回滚方法就是删除新增的 location 块并重载。
上传目录仍有旧木马:Nginx限制的是执行,不负责删除文件。
配置生效后,建议用 find /www/wwwroot/你的站点/uploads -name "*.php" 排查残留脚本文件,确认后清理。
还需要配合哪些措施
Nginx禁止执行只是其中一层。
更完整的做法包括:上传目录设置不可执行权限、程序层校验文件类型和内容、定期扫描异常文件。
如果使用的是云服务器,还可以在安全组限制不必要的端口,降低整体暴露面。
如果同一台服务器跑了多个站点,建议每个站点单独配置上传目录规则,不要图省事用一个全局规则覆盖,避免某个站点路径特殊导致误拦截。
常见疑问
问:配置后图片能打开,但PHP文件返回404而不是403,正常吗?
答:如果规则写成了 location 内部 try_files 或路径不匹配,可能落到其他规则返回404。
只要能阻止执行,404和403效果相同,但建议统一为403,便于排查和日志统计。
问:宝塔面板保存配置时提示语法错误怎么办?
答:先检查大括号是否成对、location 是否写在 server {} 内。
宝塔保存前会做语法校验,错误提示通常会指出行号,按行号定位即可。
问:规则会不会影响伪静态?
答:只要正则只匹配上传目录下的脚本后缀,不会影响其他路径的伪静态规则。
如果发现影响,检查正则里的路径是否写得太宽泛。
问:CDN回源时403会不会被缓存?
答:部分CDN会缓存403响应。
如果使用CDN,建议在CDN侧配置不缓存403,或对上传目录的脚本请求直接拒绝回源,具体以所用CDN的官方文档为准。
到这里,上传目录禁止脚本执行的Nginx配置就完成了。
建议先在测试环境验证,确认图片正常、脚本返回403,再同步到生产服务器,避免上线后才发现误伤。