一、概述
1.1 背景介绍
Linux 的安全模型建立在文件权限之上。每个文件和目录都有三组权限(属主、属组、其他),每组权限包含读(r)、写(w)、执行(x)三个位。这套看似简单的机制,加上 SUID/SGID/Sticky 特殊权限位、ACL 扩展权限和 SELinux 强制访问控制,构成了 Linux 完整的权限体系。
DAC 与 MAC
Linux 采用两层权限模型:
DAC(自主访问控制,Discretionary Access Control):
MAC(强制访问控制,Mandatory Access Control):
- 通过安全上下文(Security Context)控制
访问请求 → DAC 检查(文件权限) → MAC 检查(SELinux) → 允许/拒绝 | | 权限位 + ACL 安全上下文
权限三元组
# ls -la 输出示例-rwxr-xr-- 1 nginx www-data 4096 Mar 13 10:00 index.html│├─┤├─┤├─┤│ │ │ └── 其他用户权限(Other): r-- (读)│ │ └───── 属组权限(Group): r-x (读+执行)│ └───────── 属主权限(Owner): rwx (读+写+执行)└──────────── 文件类型: - (普通文件)
权限的数字表示:
常用权限组合:
特殊权限位
# SUID 示例:passwd 命令需要以 root 身份修改 /etc/shadowls -la /usr/bin/passwd# -rwsr-xr-x 1 root root 68208 ... /usr/bin/passwd# 注意 's' 替代了属主的 'x'# Sticky 示例:/tmp 目录ls -ld /tmp# drwxrwxrwt 15 root root 4096 ... /tmp# 注意末尾的 't'
1.2 权限混乱的常见成因
| | |
|---|
| chmod -R 777 / | |
| chown -R www-data:www-data / | |
| | |
| | |
| Docker volume 的 uid/gid 不匹配 | |
| | |
1.3 适用场景
1.4 环境要求
| | |
|---|
| Ubuntu 24.04 LTS / Rocky Linux 9.5 | |
| | |
| | |
| | |
| | |
| | |
# Ubuntu 24.04 安装必要工具sudo apt install -y acl attr policycoreutils aide auditd# Rocky Linux 9.5 安装sudo dnf install -y acl attr policycoreutils-python-utils aide audit
二、详细步骤
2.1 权限查看与分析
基本权限查看
# ls -la 查看权限ls -la /etc/ssh/# total 620# drwxr-xr-x 4 root root 4096 Mar 13 10:00 .# drwxr-xr-x 133 root root 12288 Mar 13 09:30 ..# -rw-r--r-- 1 root root 577388 Feb 15 08:00 moduli# -rw-r--r-- 1 root root 1649 Feb 15 08:00 ssh_config# -rw------- 1 root root 3667 Mar 10 15:00 sshd_config# -rw------- 1 root root 505 Mar 10 15:00 ssh_host_ecdsa_key# -rw-r--r-- 1 root root 176 Mar 10 15:00 ssh_host_ecdsa_key.pub# stat 命令查看详细信息stat /etc/ssh/sshd_config# File: /etc/ssh/sshd_config# Size: 3667 Blocks: 8 IO Block: 4096 regular file# Access: (0600/-rw-------) Uid: ( 0/ root) Gid: ( 0/ root)# Access: 2026-03-13 10:00:00.000000000 +0800# Modify: 2026-03-10 15:00:00.000000000 +0800# Change: 2026-03-10 15:00:00.000000000 +0800
ACL 权限查看
# 查看 ACLgetfacl /var/www/html/# # file: var/www/html/# # owner: www-data# # group: www-data# user::rwx# user:deploy:rwx# group::r-x# mask::rwx# other::r-x# 查看目录下所有文件的 ACLgetfacl -R /var/www/html/
SELinux 上下文查看
# 查看 SELinux 上下文ls -laZ /var/www/html/# -rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 index.html# 查看进程的安全上下文ps auxZ | grep nginx
2.2 系统目录标准权限参照表
系统关键目录的标准权限。误操作后按照此表修复:
| | | |
|---|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| /etc/ssh/ssh_host_*_key.pub | | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
2.3 批量权限修复
RPM 系统(Rocky Linux)
# 验证所有 RPM 包的文件权限rpm -Va --nofiledigest --nosize --nomtime 2>/dev/null | grep "^....."# 输出示例:# .M....... c /etc/ssh/sshd_config# SM5....T. c /etc/sysconfig/authselect# .M 表示权限(Mode)不一致# 修复所有 RPM 包管理的文件权限sudo rpm -Va --setperms 2>/dev/null# 修复特定包的权限sudo rpm --setperms openssh-serversudo rpm --setperms nginxsudo rpm --setperms mysql-server# 同时修复属主和属组sudo rpm --setugids openssh-server
DEB 系统(Ubuntu)
# Ubuntu 没有 rpm 的 --setperms 功能,使用 debsums 和 dpkg# 安装 debsumssudo apt install -y debsums# 检查文件完整性sudo debsums -c 2>/dev/null# 重新安装包以恢复权限(针对特定包)sudo apt install --reinstall openssh-serversudo apt install --reinstall nginx# 手动修复关键系统文件权限的脚本sudo chmod 644 /etc/passwd /etc/group /etc/shells /etc/hostnamesudo chmod 640 /etc/shadow /etc/gshadowsudo chmod 600 /etc/ssh/sshd_configsudo chmod 600 /etc/ssh/ssh_host_*_keysudo chmod 644 /etc/ssh/ssh_host_*_key.pubsudo chmod 440 /etc/sudoerssudo chmod 1777 /tmp /var/tmp
2.4 常见服务权限修复
SSH 权限修复
SSH 对权限要求非常严格。权限不对会直接拒绝认证。
# SSH 服务端sudo chmod 755 /etc/sshsudo chmod 600 /etc/ssh/sshd_configsudo chmod 600 /etc/ssh/ssh_host_*_keysudo chmod 644 /etc/ssh/ssh_host_*_key.pubsudo chown -R root:root /etc/ssh# SSH 客户端(用户目录)chmod 700 ~/.sshchmod 600 ~/.ssh/id_rsa # 私钥chmod 644 ~/.ssh/id_rsa.pub # 公钥chmod 600 ~/.ssh/authorized_keys # 授权密钥chmod 600 ~/.ssh/config # SSH 客户端配置chmod 644 ~/.ssh/known_hosts # 已知主机# 用户主目录权限(SSH 也会检查)chmod 700 ~# 或者至少chmod 755 ~# 绝对不能是 777 或组/其他可写
SSH 权限检查的严格规则:
Nginx 权限修复
# Nginx 配置文件sudo chown -R root:root /etc/nginxsudo chmod 755 /etc/nginxsudo chmod 644 /etc/nginx/nginx.confsudo chmod 755 /etc/nginx/conf.dsudo chmod 644 /etc/nginx/conf.d/*.conf# SSL 证书(私钥需要严格限制)sudo chown root:root /etc/nginx/ssl/sudo chmod 700 /etc/nginx/ssl/sudo chmod 600 /etc/nginx/ssl/*.key # 私钥sudo chmod 644 /etc/nginx/ssl/*.crt # 证书# Web 根目录sudo chown -R www-data:www-data /var/www/htmlsudo find /var/www/html -type d -exec chmod 755 {} \;sudo find /var/www/html -type f -exec chmod 644 {} \;# Nginx 临时目录sudo chown -R www-data:www-data /var/cache/nginxsudo chmod 700 /var/cache/nginx# 日志目录sudo chown -R www-data:adm /var/log/nginxsudo chmod 755 /var/log/nginxsudo chmod 640 /var/log/nginx/*.log
MySQL 权限修复
# MySQL 数据目录sudo chown -R mysql:mysql /var/lib/mysqlsudo chmod 750 /var/lib/mysqlsudo find /var/lib/mysql -type d -exec chmod 750 {} \;sudo find /var/lib/mysql -type f -exec chmod 640 {} \;# MySQL 配置文件sudo chown root:root /etc/mysql/mysql.conf.d/mysqld.cnfsudo chmod 644 /etc/mysql/mysql.conf.d/mysqld.cnf# MySQL 日志sudo chown mysql:adm /var/log/mysqlsudo chmod 750 /var/log/mysql# MySQL socket 目录sudo chown mysql:mysql /var/run/mysqldsudo chmod 755 /var/run/mysqld
Docker 权限修复
# Docker 数据目录sudo chown -R root:root /var/lib/dockersudo chmod 710 /var/lib/docker# Docker socket(允许 docker 组访问)sudo chown root:docker /var/run/docker.socksudo chmod 660 /var/run/docker.sock# Docker 配置sudo chown root:root /etc/dockersudo chmod 755 /etc/dockersudo chmod 600 /etc/docker/daemon.json 2>/dev/null
2.5 ACL 权限修复
# 查看 ACLgetfacl /var/www/html# 删除所有 ACL(恢复到基本权限)sudo setfacl -b /var/www/htmlsudo setfacl -Rb /var/www/html # 递归# 设置 ACL(允许 deploy 用户读写)sudo setfacl -m u:deploy:rwx /var/www/htmlsudo setfacl -m u:deploy:rw /var/www/html/index.html# 设置默认 ACL(新建文件继承)sudo setfacl -d -m u:deploy:rwx /var/www/html# 从文件恢复 ACLsudo getfacl -R /var/www > /tmp/acl_backup.txt # 备份sudo setfacl --restore=/tmp/acl_backup.txt # 恢复
2.6 SELinux 上下文修复
# 查看默认上下文matchpathcon /var/www/html# /var/www/html system_u:object_r:httpd_sys_content_t:s0# 恢复默认上下文(单个文件)sudo restorecon -v /var/www/html/index.html# 递归恢复(整个目录)sudo restorecon -Rv /var/www/html/# 查看当前上下文与默认上下文的差异sudo restorecon -Rnv /var/www/html/# 修改文件的上下文类型sudo chcon -t httpd_sys_content_t /var/www/html/custom_file# 永久修改上下文映射规则sudo semanage fcontext -a -t httpd_sys_content_t "/srv/myapp(/.*)?"sudo restorecon -Rv /srv/myapp/
2.7 验证修复结果
#!/bin/bash# verify_permissions.sh - 关键文件权限验证脚本RED='\033[0;31m'GREEN='\033[0;32m'NC='\033[0m'check_perm() {local file="$1"local expected_perm="$2"local expected_owner="$3"local expected_group="$4"if [ ! -e "$file" ]; thenecho -e "${RED}[MISS]${NC}$file 不存在"returnfi actual_perm=$(stat -c "%a""$file") actual_owner=$(stat -c "%U""$file") actual_group=$(stat -c "%G""$file")if [ "$actual_perm" = "$expected_perm" ] && \ [ "$actual_owner" = "$expected_owner" ] && \ [ "$actual_group" = "$expected_group" ]; thenecho -e "${GREEN}[OK]${NC}$file ($actual_perm$actual_owner:$actual_group)"elseecho -e "${RED}[BAD]${NC}$file 期望: $expected_perm$expected_owner:$expected_group, 实际: $actual_perm$actual_owner:$actual_group"fi}echo"===== 关键文件权限检查 ====="# 系统文件check_perm "/etc/passwd""644""root""root"check_perm "/etc/shadow""640""root""shadow"check_perm "/etc/group""644""root""root"check_perm "/etc/sudoers""440""root""root"check_perm "/tmp""1777""root""root"# SSHcheck_perm "/etc/ssh""755""root""root"check_perm "/etc/ssh/sshd_config""600""root""root"# 用户 SSHif [ -d "$HOME/.ssh" ]; then check_perm "$HOME/.ssh""700""$(whoami)""$(id -gn)" [ -f "$HOME/.ssh/authorized_keys" ] && \ check_perm "$HOME/.ssh/authorized_keys""600""$(whoami)""$(id -gn)"fiecho"===== 检查完成 ====="
三、示例代码和配置
3.1 完整的权限修复脚本
#!/bin/bash# fix_permissions.sh - Linux 系统权限修复脚本# 用法: sudo ./fix_permissions.sh [--check|--fix|--fix-service <service>]set -euo pipefailRED='\033[0;31m'GREEN='\033[0;32m'YELLOW='\033[1;33m'NC='\033[0m'log_info() { echo -e "[INFO] $1"; }log_pass() { echo -e "${GREEN}[PASS]${NC}$1"; }log_fail() { echo -e "${RED}[FAIL]${NC}$1"; }log_fix() { echo -e "${YELLOW}[FIX]${NC}$1"; }# 检查 root 权限if [ "$EUID" -ne 0 ]; thenecho"需要 root 权限运行"exit 1fifix_system_permissions() { log_info "修复系统关键文件权限..."# /etc 基础文件 chmod 644 /etc/passwd /etc/group /etc/shells chmod 640 /etc/shadow /etc/gshadow chown root:root /etc/passwd /etc/group /etc/shells chown root:shadow /etc/shadow /etc/gshadow log_fix "/etc/{passwd,group,shadow,gshadow}"# sudoers chmod 440 /etc/sudoers chown root:root /etc/sudoers chmod 750 /etc/sudoers.d find /etc/sudoers.d -type f -exec chmod 440 {} \; log_fix "/etc/sudoers"# /tmp 和 /var/tmp chmod 1777 /tmp /var/tmp chown root:root /tmp /var/tmp log_fix "/tmp, /var/tmp (sticky bit)"# /root chmod 700 /root chown root:root /root log_fix "/root"}fix_ssh_permissions() { log_info "修复 SSH 权限..."# 服务端 chmod 755 /etc/ssh chmod 600 /etc/ssh/sshd_config find /etc/ssh -name "ssh_host_*_key" -exec chmod 600 {} \; find /etc/ssh -name "ssh_host_*_key.pub" -exec chmod 644 {} \; chown -R root:root /etc/ssh log_fix "SSH 服务端配置"# 所有用户的 .ssh 目录for home_dir in /home/*/; do user=$(basename "$home_dir") ssh_dir="${home_dir}.ssh"if [ -d "$ssh_dir" ]; then chmod 700 "$ssh_dir" [ -f "${ssh_dir}/authorized_keys" ] && chmod 600 "${ssh_dir}/authorized_keys" [ -f "${ssh_dir}/id_rsa" ] && chmod 600 "${ssh_dir}/id_rsa" [ -f "${ssh_dir}/id_ed25519" ] && chmod 600 "${ssh_dir}/id_ed25519" [ -f "${ssh_dir}/config" ] && chmod 600 "${ssh_dir}/config" chown -R "${user}:${user}""$ssh_dir" log_fix "用户 ${user} 的 .ssh 目录"fidone# root 的 .sshif [ -d /root/.ssh ]; then chmod 700 /root/.ssh [ -f /root/.ssh/authorized_keys ] && chmod 600 /root/.ssh/authorized_keys chown -R root:root /root/.ssh log_fix "root 的 .ssh 目录"fi}fix_nginx_permissions() { log_info "修复 Nginx 权限..."if [ -d /etc/nginx ]; then chown -R root:root /etc/nginx chmod 755 /etc/nginx chmod 644 /etc/nginx/nginx.conf find /etc/nginx/conf.d -type f -exec chmod 644 {} \; 2>/dev/null log_fix "Nginx 配置文件"fiif [ -d /var/www/html ]; then chown -R www-data:www-data /var/www/html find /var/www/html -type d -exec chmod 755 {} \; find /var/www/html -type f -exec chmod 644 {} \; log_fix "Web 根目录"fi}fix_mysql_permissions() { log_info "修复 MySQL 权限..."if [ -d /var/lib/mysql ]; then chown -R mysql:mysql /var/lib/mysql chmod 750 /var/lib/mysql log_fix "MySQL 数据目录"fi}case"${1:---check}"in --check) log_info "检查模式(不修改)" bash "$(dirname "$0")/verify_permissions.sh" 2>/dev/null || \ log_info "运行权限验证脚本查看详情" ;; --fix) log_info "开始修复系统权限..." fix_system_permissions fix_ssh_permissionsecho"" log_pass "系统权限修复完成" ;; --fix-service) SERVICE="${2:?用法: $0 --fix-service <ssh|nginx|mysql>}"case"$SERVICE"in ssh) fix_ssh_permissions ;; nginx) fix_nginx_permissions ;; mysql) fix_mysql_permissions ;; *) echo"支持的服务: ssh, nginx, mysql"; exit 1 ;;esac log_pass "${SERVICE} 权限修复完成" ;; *)echo"用法: $0 [--check|--fix|--fix-service <service>]"exit 1 ;;esac
3.2 案例 1:chmod -R 777 误操作后的修复
场景:管理员为了"解决权限问题"执行了 chmod -R 777 /etc,导致 SSH 无法登录、sudo 报错。
# 症状# 1. SSH 密码认证可以登录,但公钥认证失败# 2. sudo 报错:/etc/sudoers is world writable# 诊断ls -la /etc/sudoers# -rwxrwxrwx 1 root root 1671 ... /etc/sudoers# 权限全部变成 777,这是灾难性的# 修复步骤# 1. 先用密码登录(公钥认证已经失效)# 2. 修复 sudoers(否则 sudo 无法使用)pkexec chmod 440 /etc/sudoers# 或者如果能用 root 直接登录chmod 440 /etc/sudoers# 3. 修复 shadow(否则密码认证可能出问题)chmod 640 /etc/shadowchown root:shadow /etc/shadow# 4. 修复 SSH 相关文件chmod 600 /etc/ssh/sshd_configchmod 600 /etc/ssh/ssh_host_*_keychmod 644 /etc/ssh/ssh_host_*_key.pub# 5. 使用 rpm/dpkg 批量修复# Rocky Linuxsudo rpm -Va --setperms 2>/dev/nullsudo rpm -Va --setugids 2>/dev/null# Ubuntusudo apt install --reinstall $(dpkg -S /etc/ 2>/dev/null | cut -d: -f1 | sort -u | tr '\n'' ')# 6. 重启 SSH 服务sudo systemctl restart sshd# 7. 验证sudo -l # 测试 sudossh -T user@localhost # 测试 SSH 公钥认证
3.3 案例 2:SSH 密钥权限错误导致登录失败
场景:新建用户后配置了 SSH 公钥认证,但登录时仍然要求输入密码。
# 使用 ssh -vvv 查看详细信息ssh -vvv user@192.168.1.100# ...# debug1: Offering public key: /home/user/.ssh/id_ed25519# debug3: send packet: type 50# debug2: we sent a publickey packet, wait for reply# debug3: receive packet: type 51# debug1: Authentications that can continue: publickey,password# debug1: Trying private key: /home/user/.ssh/id_rsa# ...# 如果看到 "Authentication refused: bad ownership or modes" 在服务端日志中sudo journalctl -u sshd | grep "Authentication refused"# Authentication refused: bad ownership or modes for directory /home/user# 排查权限ls -la /home/user/# drwxrwxrwx 5 user user 4096 ... . <-- 主目录 777,SSH 拒绝ls -la /home/user/.ssh/# drwxrwxrwx 2 user user 4096 ... . <-- .ssh 目录 777# 修复chmod 755 /home/userchmod 700 /home/user/.sshchmod 600 /home/user/.ssh/authorized_keyschown -R user:user /home/user/.ssh# 重试 SSH 连接ssh user@192.168.1.100# 成功使用公钥认证登录
3.4 案例 3:Web 目录权限导致 403
场景:部署 Web 应用后,Nginx 返回 403 Forbidden。
# 1. 确认 Nginx 错误日志sudo tail -5 /var/log/nginx/error.log# open() "/var/www/myapp/index.html" failed (13: Permission denied)# 2. 检查文件权限ls -la /var/www/myapp/# -rw------- 1 root root 1024 ... index.html <-- 只有 root 可读# Nginx 以 www-data 用户运行,无法读取# 3. 检查 Nginx 运行用户grep "user" /etc/nginx/nginx.conf# user www-data;# 4. 修复权限sudo chown -R www-data:www-data /var/www/myappsudo find /var/www/myapp -type d -exec chmod 755 {} \;sudo find /var/www/myapp -type f -exec chmod 644 {} \;# 5. 如果使用 SELinux,还需要检查上下文ls -laZ /var/www/myapp/# 如果上下文不是 httpd_sys_content_t,则需要修复sudo restorecon -Rv /var/www/myapp/# 6. 验证curl -I http://localhost/# HTTP/1.1 200 OK
3.5 权限审计脚本
#!/bin/bash# permission_audit.sh - 系统权限审计脚本echo"=========================================="echo" Linux 权限安全审计报告"echo" 时间: $(date '+%Y-%m-%d %H:%M:%S')"echo" 主机: $(hostname)"echo"=========================================="echo -e "\n--- 1. 全局可写文件(排除 /tmp /proc /sys) ---"find / -xdev -type f -perm -0002 \ -not -path "/tmp/*" \ -not -path "/var/tmp/*" \ -not -path "/proc/*" \ -not -path "/sys/*" \ 2>/dev/null | head -20echo -e "\n--- 2. SUID 文件 ---"find / -xdev -type f -perm -4000 2>/dev/null | sortecho -e "\n--- 3. SGID 文件 ---"find / -xdev -type f -perm -2000 2>/dev/null | sortecho -e "\n--- 4. 无属主文件 ---"find / -xdev \( -nouser -o -nogroup \) 2>/dev/null | head -20echo -e "\n--- 5. 关键文件权限检查 ---"for f in /etc/passwd /etc/shadow /etc/group /etc/sudoers /etc/ssh/sshd_config; doif [ -e "$f" ]; thenstat -c "%a %U:%G %n""$f"fidoneecho -e "\n--- 6. 用户主目录权限 ---"for dir in /home/*/; dostat -c "%a %U:%G %n""$dir" 2>/dev/nulldoneecho -e "\n=========================================="echo" 审计完成"echo"=========================================="
四、最佳实践和注意事项
4.1 最佳实践
最小权限原则落地
# 1. 服务使用专用用户,不用 root 运行# 检查以 root 运行的非系统服务ps aux | awk '$1=="root" && $11!~/^\[/ {print $0}' | grep -v -E "sshd|systemd|agetty|cron"# 2. 目录权限分离# Web 根目录: 文件属于 www-data,配置属于 root# 日志目录: 服务用户可写,其他用户不可读# 3. 使用 umask 控制默认权限# 在 /etc/profile 或用户的 .bashrc 中设置umask 027 # 新建文件默认 640,目录默认 750# 4. 敏感文件使用 600 或 640chmod 600 /path/to/database.confchmod 600 /path/to/api_keys.yml
权限变更审计
# 1. 使用 auditd 监控关键文件权限变更# 添加审计规则sudo auditctl -w /etc/passwd -p wa -k passwd_changessudo auditctl -w /etc/shadow -p wa -k shadow_changessudo auditctl -w /etc/ssh/sshd_config -p wa -k sshd_configsudo auditctl -a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -k perm_changes# 持久化规则sudo cat >> /etc/audit/rules.d/permissions.rules << 'EOF'-w /etc/passwd -p wa -k passwd_changes-w /etc/shadow -p wa -k shadow_changes-w /etc/ssh/sshd_config -p wa -k sshd_config-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -k perm_changesEOF# 查看审计日志sudo ausearch -k perm_changes -ts recent
4.2 注意事项
常见错误
| | |
|---|
| sudo 报 "is world writable" | | chmod 440 /etc/sudoers |
| | |
| | |
| | chown -R mysql:mysql /var/lib/mysql |
| | chmod 600 /var/spool/cron/crontabs/* |
| | rpm --setperms |
| | 使用 --user 参数或 userns-remap |
兼容性注意
chmod -R 会同时作用于文件和目录。目录需要 x 权限才能进入,文件通常不需要 x。正确做法是分开设置:
# 分别设置目录和文件权限find /path -type d -exec chmod 755 {} \;find /path -type f -exec chmod 644 {} \;
ACL 需要文件系统支持。ext4 和 xfs 默认支持 ACL。挂载时需要 acl 选项(大部分发行版默认启用)。
SELinux 上下文在跨文件系统复制时可能丢失。使用 cp --preserve=context 或复制后执行 restorecon。
五、故障排查和监控
5.1 故障排查
日志查看
# 系统审计日志(auditd)sudo ausearch -m AVC -ts recent # SELinux 拒绝sudo ausearch -k perm_changes -ts recent # 权限变更sudo aureport --summary # 审计摘要# 系统日志sudo journalctl -p err -t sshd # SSH 错误sudo journalctl -p err -t sudo # sudo 错误sudo journalctl -p err -t kernel | grep "avc:"# SELinux 内核日志
常见问题排查
问题 1:恢复备份后权限全乱
# tar 解压时保留权限sudo tar xzf backup.tar.gz -p # -p 保留权限# 如果已经解压但权限丢失# 使用 rpm/apt 修复系统文件sudo rpm -Va --setperms 2>/dev/null # Rocky Linux# Ubuntu 重新安装相关包# 对于应用数据,从权限备份文件恢复sudo setfacl --restore=/path/to/acl_backup.txt
问题 2:容器内文件权限不对
# 查看容器内运行用户docker exec mycontainer id# uid=1000(app) gid=1000(app) groups=1000(app)# 宿主机上该 UID 对应的用户可能不同id 1000# uid=1000(developer) gid=1000(developer)# 解决方案 1:在 Dockerfile 中使用与宿主机一致的 UID# RUN useradd -u 1000 app# 解决方案 2:使用 Docker userns-remap# /etc/docker/daemon.json# { "userns-remap": "default" }
5.2 性能监控
AIDE 文件完整性监控
# 初始化 AIDE 数据库sudo aideinit# 运行检查sudo aide --check# 更新数据库(确认变更后)sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db# 定时检查(crontab)# 0 3 * * * /usr/bin/aide --check | mail -s "AIDE Report $(hostname)" admin@example.com
Prometheus 权限监控
#!/bin/bash# perm_exporter.sh - 关键文件权限指标导出METRICS_FILE="/var/lib/prometheus/node-exporter/permissions.prom"check_file_perm() {local file="$1"local expected="$2"if [ -e "$file" ]; then actual=$(stat -c "%a""$file")if [ "$actual" = "$expected" ]; thenecho"file_permission_correct{file=\"${file}\",expected=\"${expected}\"} 1"elseecho"file_permission_correct{file=\"${file}\",expected=\"${expected}\"} 0"fifi}{ check_file_perm "/etc/passwd""644" check_file_perm "/etc/shadow""640" check_file_perm "/etc/sudoers""440" check_file_perm "/etc/ssh/sshd_config""600"# SUID 文件数量 suid_count=$(find / -xdev -type f -perm -4000 2>/dev/null | wc -l)echo"system_suid_file_count $suid_count"# 全局可写文件数量(排除 /tmp) world_writable=$(find / -xdev -type f -perm -0002 -not -path "/tmp/*" -not -path "/var/tmp/*" 2>/dev/null | wc -l)echo"system_world_writable_file_count $world_writable"} > "$METRICS_FILE"
# Prometheus 告警规则groups:-name:file_permissionsrules:-alert:CriticalFilePermissionWrongexpr:file_permission_correct==0for:5mlabels:severity:criticalannotations:summary:"关键文件权限异常: {{ $labels.file }}"description:"文件 {{ $labels.file }} 的权限与预期 {{ $labels.expected }} 不一致"-alert:TooManySUIDFilesexpr:system_suid_file_count>30for:1hlabels:severity:warningannotations:summary:"SUID 文件数量异常: {{ $value }}"
auditd 权限变更监控
使用 auditd 实时监控关键文件和目录的权限变更:
# 安装 auditdsudo apt install -y auditd audispd-plugins # Ubuntusudo dnf install -y audit # Rocky# 监控 /etc/passwd 和 /etc/shadow 的权限变更sudo auditctl -w /etc/passwd -p wa -k passwd_changessudo auditctl -w /etc/shadow -p wa -k shadow_changes# 监控 SSH 配置文件的变更sudo auditctl -w /etc/ssh/ -p wa -k ssh_config_changes# 监控 sudoers 文件sudo auditctl -w /etc/sudoers -p wa -k sudoers_changes# 监控所有 chmod/chown 操作sudo auditctl -a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -k permission_changessudo auditctl -a always,exit -F arch=b64 -S chown,fchown,fchownat -k ownership_changes# 将规则持久化到 /etc/audit/rules.d/cat > /etc/audit/rules.d/90-permissions.rules << 'EOF'-w /etc/passwd -p wa -k passwd_changes-w /etc/shadow -p wa -k shadow_changes-w /etc/ssh/ -p wa -k ssh_config_changes-w /etc/sudoers -p wa -k sudoers_changes-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -k permission_changes-a always,exit -F arch=b64 -S chown,fchown,fchownat -k ownership_changesEOF# 查看权限变更审计记录sudo ausearch -k permission_changes -ts today# time->Thu Mar 13 14:30:45 2026# type=SYSCALL msg=audit(1710337845.123:456): arch=c000003e syscall=268# success=yes exit=0 a0=ffffff9c a1=55a12345 a2=1ed a3=0# uid=0 gid=0 euid=0 comm="chmod" exe="/usr/bin/chmod"# type=PATH msg=audit(1710337845.123:456): item=0 name="/etc/myapp/config.yml"# inode=12345 dev=fd:00 mode=0100755 ouid=0 ogid=0# 生成审计报告sudo aureport --file --summarysudo aureport -x --summary | head -20
Grafana 面板关键查询
# 关键文件权限偏离数量count(file_permission_correct == 0)# SUID 文件数量趋势system_suid_file_count# 全局可写文件数量趋势system_world_writable_file_count# 权限变更事件率(需要配合 auditd exporter)rate(audit_permission_changes_total[5m])
5.3 备份与恢复
#!/bin/bash# 权限备份脚本BACKUP_DIR="/opt/backup/permissions"DATE=$(date +%Y%m%d)mkdir -p "$BACKUP_DIR"# 备份关键目录的权限信息getfacl -R /etc > "${BACKUP_DIR}/etc_acl_${DATE}.txt"getfacl -R /var/www > "${BACKUP_DIR}/www_acl_${DATE}.txt" 2>/dev/nullgetfacl -R /home > "${BACKUP_DIR}/home_acl_${DATE}.txt"# 备份文件权限列表find /etc -printf"%m %u %g %p\n" > "${BACKUP_DIR}/etc_perms_${DATE}.txt"# 保留 30 天find "$BACKUP_DIR" -mtime +30 -deleteecho"权限信息已备份到 ${BACKUP_DIR}"
恢复:
# 从 ACL 备份恢复sudo setfacl --restore="${BACKUP_DIR}/etc_acl_20260313.txt"# 从权限列表恢复(手动脚本)while IFS=' 'read -r perm owner group path; do [ -e "$path" ] && chmod "$perm""$path" && chown "${owner}:${group}""$path"done < "${BACKUP_DIR}/etc_perms_20260313.txt"
六、总结
6.1 技术要点回顾
- Linux 权限体系包含 DAC(权限位+ACL)和 MAC(SELinux)两层,排查权限问题需要两层都检查
- SSH 对权限有严格要求:主目录不能 group/other 可写,.ssh 目录必须 700,私钥必须 600
chmod -R 777 是最常见的权限灾难,修复需要区分文件和目录分别设置权限- RPM 系统可用
rpm -Va --setperms 批量修复,DEB 系统需要 apt install --reinstall - ACL 权限使用
getfacl -R 备份、setfacl --restore 恢复 - SELinux 上下文使用
restorecon -Rv 恢复默认设置 - 使用 auditd 监控关键文件的权限变更是安全最佳实践
- SUID/SGID 文件是安全审计重点,定期扫描确认没有非预期的特权文件
- 容器环境中的权限问题通常由 UID 映射不一致导致,需要关注 Dockerfile 中的 USER 设置
6.2 权限修复流程图
权限问题 │ ├── 文件不可读/写/执行 │ └── ls -la 检查权限位 │ ├── 权限位正确 → 检查 ACL(getfacl) │ ├── ACL 正确 → 检查 SELinux(ls -laZ) │ └── SELinux 正确 → 检查进程运行身份 │ ├── SSH 登录失败 │ └── 检查 ~/.ssh 目录权限(700) │ └── 检查密钥文件权限(600) │ └── 检查 authorized_keys 权限(600) │ └── 检查用户主目录权限(不超过 755) │ ├── Web 服务 403 │ └── 检查文件属主(www-data/nginx) │ └── 检查目录是否有 x 权限 │ └── 检查 SELinux 类型(httpd_sys_content_t) │ └── chmod 777 误操作 └── 停止所有服务 └── rpm -Va --setperms 修复系统文件 └── 手动修复 SSH 权限 └── 恢复应用目录权限 └── restorecon -Rv 修复 SELinux
6.2 进阶学习方向
- Linux Capabilities:比 SUID 更精细的权限控制,允许进程获得特定的 root 能力而非全部权限
- AppArmor:Ubuntu 默认的 MAC 框架,基于路径的访问控制,配置比 SELinux 简单
- 命名空间与 cgroups:容器环境下的权限隔离机制
- eBPF LSM:基于 eBPF 的安全模块,下一代 Linux 安全框架
6.3 参考资料
- Linux man pages: chmod(1), chown(1), setfacl(1), getfacl(1), restorecon(8)
- Red Hat SELinux 用户指南: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/using_selinux
- AIDE 官方文档: https://aide.github.io/
- Linux auditd 系统: https://linux-audit.com/
- POSIX ACL 规范: IEEE Std 1003.1e
附录
A. 命令速查表
# 权限查看ls -la <path> # 基本权限stat <file> # 详细信息getfacl <path> # ACL 权限ls -laZ <path> # SELinux 上下文# 权限修改chmod 755 <path> # 设置权限chown user:group <path> # 设置属主属组setfacl -m u:user:rwx <path> # 设置 ACLchcon -t <type> <path> # 设置 SELinux 上下文# 批量操作find <path> -type d -exec chmod 755 {} \; # 目录权限find <path> -type f -exec chmod 644 {} \; # 文件权限restorecon -Rv <path> # 恢复 SELinux 上下文# 审计find / -perm -4000 -type f # 查找 SUID 文件find / -perm -0002 -type f # 查找全局可写文件find / -nouser -o -nogroup # 查找无属主文件rpm -Va --setperms # RPM 修复权限
B. 配置参数详解
umask 值对照表
SELinux 常用文件类型