最直接有效的做法是linux文件权限与用户组隔离。应将配置文件属主设为root、属组为专用管理组(如confadm),权限严格设为640,禁止world读;避免使用setfacl或sudoers;启用systemd的dynamicuser=yes增强进程级隔离;禁用应用层权限判断,杜绝配置接口暴露;确保备份文件权限一致且受selinux/apparmor管控。
linux 文件权限 + 用户组隔离是最直接有效的做法
普通用户不能读取服务器配置文件,本质是操作系统层面的访问控制问题。靠应用层逻辑判断(比如代码里 if (user.role === 'admin'))既不可靠又容易绕过,必须依赖 /etc/ssh/sshd_config、/etc/nginx/nginx.conf 这类文件自身的权限机制。
常见错误现象:cat: /etc/nginx/nginx.conf: Permission denied 看似正常,但其实是因为该用户被加进了 nginx 组,而文件误设为 640 且组可读——结果非预期泄露。
- 把配置文件属主设为
root,属组设为一个专用管理组(如confadm),而非服务运行组(如www-data) - 权限严格设为
640(root:confadm),禁止 world 读;用chmod 640 /etc/nginx/nginx.conf确认 - 仅将真正需要查看的运维人员加入
confadm组,普通用户不在任何相关组中 - 避免使用
setfacl或sudoers做细粒度授权——它会掩盖权限模型,排查时反而更难定位谁到底能读
systemd 服务配置中的 DynamicUser=yes 能防止配置文件被进程意外暴露
有些服务(如 nginx、redis)启动后,其 worker 进程若以低权限用户运行,仍可能通过 /proc/PID/fd/ 或内存 dump 暴露已加载的配置内容。启用 DynamicUser=yes 可让 systemd 在启动时动态创建无家目录、无 shell、无登录能力的临时用户,大幅压缩攻击面。
使用场景:你部署了一个自定义的 myapp.service,它读取 /etc/myapp/config.yaml 后长期运行,但你不希望该进程有任意文件读取能力。
- 在 service 文件中添加:
DynamicUser=yes和NoNewPrivileges=yes - 确保配置文件路径对这个动态用户不可写(否则它可能覆盖自身配置)
- 注意兼容性:glibc 2.31+、systemd 245+ 才完整支持;旧系统会静默降级为普通用户,起不到隔离效果
- 该设置不影响 root 用户对配置文件的读取权,只约束服务进程自身权限边界
不要在 Web 后端代码里做“if user.is_normal then hide_config”这类判断
这种逻辑看似可控,实则等于把权限决策从内核推到应用层,一旦接口被绕过(比如直接调用内部 API、利用日志注入、或反序列化漏洞),配置内容立刻裸奔。真实生产环境里,90% 的配置泄漏事故都源于这类“信任应用层”的设计。
典型错误示例:if current_user.role != 'admin': return {'error': 'no access'} —— 这个判断本身就在响应体里暴露了“存在配置接口”,还可能被爆破角色字段。
- 删除所有返回原始配置内容的 HTTP 接口,哪怕加了鉴权也不行
- 如需提供配置状态,只返回结构化摘要(如
{"nginx_status": "running", "ssl_enabled": true}),不包含路径、密钥、监听地址等原始值 - Web 服务运行用户(如
www-data)对/etc/下任何配置文件必须无读权限,用sudo -u www-data cat /etc/nginx/nginx.conf实测验证 - CI/CD 流水线中禁止将配置文件 copy 到 webroot 或 public 目录下——哪怕加了
.htaccess或location ^~ /etc/阻断,也是徒劳
SELinux 或 AppArmor 是最后防线,但别指望它替代基础权限
当 Linux 标准权限和 systemd 隔离都到位后,SELinux(RHEL/CentOS)或 AppArmor(Ubuntu/Debian)可以封住“本不该发生但发生了”的越权行为,比如某个被提权的 nginx worker 尝试 open() 其他服务的配置。但它不是银弹:策略写错会导致服务起不来,且默认策略通常不覆盖自定义配置路径。
容易踩的坑:sestatus 显示 enforcing,但你的 /etc/myapp/ 目录没打标签,SELinux 完全不干预对该目录的访问。
- 用
ls -Z /etc/nginx/nginx.conf确认上下文是否为system_u:object_r:nginx_conf_t:s0类型;不是就用semanage fcontext -a -t nginx_conf_t "/etc/myapp(/.*)?"加规则,再restorecon -Rv /etc/myapp - AppArmor 用户请检查
/etc/apparmor.d/usr.sbin.nginx是否包含/etc/myapp/** r,—— 如果没有,即使文件权限宽松,AA 也会拦截 - 开发阶段建议先用
permissive模式收集 avc 日志,再生成策略,而不是一上来就 enforce
最常被忽略的一点:配置文件的备份副本(如 /etc/nginx/nginx.conf.bak、/etc/myapp/config.yaml~)往往权限松散,且不在 SELinux/AppArmor 策略覆盖范围内——它们才是真正的突破口。










