web根目录权限最小化要求www-data仅拥有运行服务必需的读写权限:静态资源只读、上传目录可写、代码不可执行、配置文件严格隔离;典型结构中public/为750/640,uploads/单独可写并禁用php解析,app/和config/由deploy管理且www-data无权访问。

Web根目录权限最小化不是简单地把文件夹所有者设为www-data,而是让www-data仅拥有运行服务所必需的读写权限,其他一概不给。核心原则是:静态资源只读、上传目录可写、代码文件不可执行、配置文件严格隔离。
明确www-data的最小权限边界
www-data用户应仅在必要时具备以下权限:
- 读取:HTML、CSS、JS、图片等静态资源;PHP/Python等脚本文件(但不直接执行)
-
写入:仅限明确设计为动态写入的目录(如
uploads/、cache/、logs/) - 不执行:禁止www-data对上传目录或缓存目录中的文件拥有执行权限(防止webshell利用)
- 不拥有:源码、配置文件、数据库凭证等敏感内容不应由www-data拥有,而应归属部署用户(如deploy)
典型目录结构与权限分配示例
以标准LAMP环境为例(Web根目录为/var/www/example.com):
-
/var/www/example.com/public/—— Web可访问入口,属主deploy:www-data,权限750(目录),640(文件) -
/var/www/example.com/public/uploads/—— 仅此目录可写,属主www-data:www-data,权限750(目录),640(文件),并禁用PHP解析(Nginx/Apache中配置location ~* \.php$ { deny all; }) -
/var/www/example.com/app/、/var/www/example.com/config/—— 不在Web路径下,属主deploy:deploy,权限700或600,www-data无任何访问权限 -
/var/www/example.com/logs/—— 属主www-data:adm,权限750,允许日志轮转工具(如logrotate)读取
关键加固操作步骤
执行前确保已备份,并在维护窗口操作:
- 重设属组:将public目录及子目录统一加入
www-data组:chgrp -R www-data /var/www/example.com/public - 收紧权限:
find /var/www/example.com/public -type d -exec chmod 750 {} \;,find /var/www/example.com/public -type f -exec chmod 640 {} \; - 单独放开上传目录:
chmod 750 /var/www/example.com/public/uploads,再限制其内部文件不可执行:find /var/www/example.com/public/uploads -type f -name "*.php" -delete(上线前清理)+ Nginx中显式拒绝执行 - 验证www-data实际能力:切换用户测试
sudo -u www-data ls -l /var/www/example.com/public和sudo -u www-data touch /var/www/example.com/public/test.txt(应失败,除非在uploads内)
配合Web服务器与应用层进一步收口
权限只是基础,需与运行时控制联动:
- Nginx中使用
user www-data;,并设置secure_link或limit_except限制HTTP方法 - PHP-FPM池配置中启用
php_admin_value[disable_functions]禁用exec,system,passthru,shell_exec,proc_open - 应用层上传逻辑必须校验文件MIME类型、扩展名、内容头,并重命名存储(避免原文件名被执行)
- 定期扫描Web目录下异常可执行文件:
find /var/www/example.com/public -type f \( -name "*.php" -o -name "*.sh" \) -not -path "*/uploads/*" -ls










