上传目录权限不应设为777,正确做法是所有者为web服务用户(如www-data)、权限755;上传文件应为644且禁用执行;临时目录和open_basedir需配置正确;最佳实践是将上传目录移出web根目录并禁用脚本执行。

上传目录不能设为 777,这是最常见也最危险的错误
很多 PHP 上传功能出问题时,第一反应是“ chmod 777 一下”,结果直接把整个上传目录暴露给 Web 服务器进程(如 www-data、apache、nginx 用户),攻击者一旦利用任意文件上传漏洞,就能写入 Webshell 并执行命令。777 权限在绝大多数生产环境中完全不可接受。
正确权限设置:目录 755 + 所有者为 web 用户,而非 root
关键不是“权限数字”,而是“谁拥有它”和“谁需要写入”。PHP 上传操作由 Web 服务器进程执行,所以上传目录必须:
- 所有者(owner)设为 Web 服务运行用户,例如
www-data(Debian/Ubuntu)、apache(CentOS/RHEL)或nginx(某些 Nginx 配置) - 所属组(group)可设为同名或自定义组,但通常保持默认即可
- 目录权限设为
755(即 rwxr-xr-x)——Web 进程可读写,其他用户仅可读、不可写 - 上传后的文件默认权限应为
644(rw-r--r--),禁止执行;若需临时处理,也应在后续脚本中显式chmod,而非开放目录执行权
执行示例(以 Ubuntu + Apache 为例):
发卡宝是一个专业的软件卡密等虚拟商品在线交易平台,拥有多种兑换方式,费率低,结算快,正规企业平台一直稳定运营,24小时不间断提供自动发卡服务。【模板说明】试用版自带一套模板(响应式)【环境支持】PHP环境 / 200M或以上空间大小 / 开启父路径 / 设置index.php为默认首页 / 目录写入权限需要开启【数据库】MySQL【安装步骤】将文件上传至空间目录,运行“http://域名/inst
sudo chown www-data:www-data /var/www/myapp/uploads sudo chmod 755 /var/www/myapp/uploads
PHP 自身配置影响上传行为,upload_tmp_dir 和 open_basedir 必须检查
上传流程实际分两步:先写入临时目录(upload_tmp_dir),再由 PHP move_uploaded_file() 移到目标目录。如果临时目录权限不对,或被 open_basedir 限制,会报 move_uploaded_file(): Unable to move 或 failed to open stream: Permission denied 等错误。
- 确认
upload_tmp_dir指向的路径存在,且属主为www-data,权限为700或755(不建议 777) - 检查
open_basedir是否包含上传目标目录和临时目录,否则move_uploaded_file()会静默失败 - 用
phpinfo()或ini_get('upload_tmp_dir')查看当前值
更安全的做法:上传目录不放在 Web 根目录下,且禁用脚本执行
即使权限设对了,只要上传目录在 Web 可访问路径(如 /var/www/html/uploads/),攻击者上传 .php 文件后仍可能直接请求执行。真正安全的方案是:
- 把上传目录移到 Web 根目录之外,例如
/var/www/uploads/(与/var/www/html/同级) - 通过 PHP 脚本控制文件访问(如用
readfile()+header()输出),避免直接 URL 访问 - 若必须放 Web 目录内,务必在 Web 服务器层禁用脚本执行:
– Apache:在上传目录的.htaccess中加php_flag engine off或RemoveHandler .php
– Nginx:在 location 块中加deny all;或fastcgi_intercept_errors on;配合location ~ \.php$ { deny all; }
权限只是基础,路径隔离和执行拦截才是防住上传漏洞的关键。很多人调通了 move_uploaded_file() 就以为万事大吉,其实刚跨过第一道门槛。










