SELinux在CentOS服务器上被大量管理员直接禁用的原因,往往不是策略本身复杂,而是默认策略在业务场景中频繁拦截正常请求后,管理员为了快速恢复服务选择了关闭。但权限泄露导致的入侵事件中,很大一部分本可以通过SELinux的强制访问控制避免。问题不在于SELinux没用,而在于没有针对实际业务做精确配置。下面直接讲清楚如何在不牺牲业务连续性的前提下,利用SELinux规避权限泄露。
先确认SELinux当前状态与工作模式登录服务器后执行getenforce和sestatus,确认当前是Enforcing、Permissive还是Disabled。Permissive模式下SELinux只记录不拦截,适合调试但无法防止权限泄露。如果服务器已经处于Disabled状态,需要修改/etc/selinux/config中的SELINUX=enforcing,并重启系统。注意从Disabled切到Enforcing会触发全盘重新标记,重启时间可能较长。生产环境建议先在测试机验证业务兼容性,再操作生产机。
理解SELinux类型强制与权限泄露的关系SELinux的核心是类型强制,每个进程和文件都有安全上下文。即使某个服务被攻击者拿到shell,只要该进程的域没有权限读取或写入其他类型的文件,攻击者就无法横向移动。例如httpd进程默认运行在httpd_t域,它只能访问httpd_sys_content_t类型的网页文件。如果攻击者通过Web漏洞上传了webshell,这个webshell继承httpd_t域,依然无法读取/etc/shadow或/root下的文件。这就是SELinux在权限泄露后的最后一道防线。
针对Web服务配置SELinux避免权限泄露CentOS上最常见的权限泄露场景是Web目录权限设置过宽,比如chmod -R 777 /var/www/html。即使不用SELinux,这种权限本身就很危险。但如果配合SELinux,即使目录权限是777,httpd_t域外的进程也无法随意写入。关键是要正确设置文件上下文。执行semanage fcontext -a -t httpd_sys_content_t "/var/www/html(/.*)?",然后restorecon -Rv /var/www/html。如果Web应用需要写入上传目录,单独给上传目录设置httpd_sys_rw_content_t类型,不要整个站点都开放写权限。
处理动态内容与CGI脚本的SELinux布尔值很多PHP或Python应用在启用SELinux后出现权限拒绝,是因为默认布尔值禁止httpd执行网络连接或读写用户目录。通过getsebool -a | grep httpd查看相关布尔值。常见的需要开启的包括httpd_can_network_connect、httpd_can_sendmail、httpd_unified。例如WordPress需要连接数据库,如果数据库在远程主机,必须开启httpd_can_network_connect_db。执行setsebool -P httpd_can_network_connect_db on使其永久生效。不要一次性开启所有布尔值,只开业务必需的,否则等于削弱了SELinux的隔离能力。
自定义策略模块解决特殊权限需求标准策略无法覆盖所有业务场景。当出现denied日志且没有现成布尔值可用时,需要创建自定义策略模块。先用ausearch -m avc -ts recent查看最近的拒绝记录,或者用grep denied /var/log/audit/audit.log。确认拒绝的源域和目标域后,使用audit2allow生成策略。例如:
grep httpd_t /var/log/audit/audit.log | audit2allow -M myhttpdpolicy semodule -i myhttpdpolicy.pp
生成前务必人工审查audit2allow给出的规则,确认不是过度授权。攻击者可能利用自定义策略中过于宽泛的allow规则扩大权限。策略模块应尽量细化到具体类型和操作,避免使用通配符。
数据库与文件服务的SELinux隔离配置MySQL或MariaDB的数据目录默认在/var/lib/mysql,类型为mysqld_db_t。如果管理员将数据目录迁移到其他路径,比如/data/mysql,必须重新标记上下文,否则mysqld进程无法访问。执行semanage fcontext -a -t mysqld_db_t "/data/mysql(/.*)?",然后restorecon -Rv /data/mysql。同样,NFS或Samba共享目录如果被多个服务访问,要明确每个服务对应的类型,不要为了方便把所有共享目录都设成public_content_rw_t,这样会破坏SELinux的域隔离。
利用SELinux限制管理员误操作与内部威胁权限泄露不仅来自外部攻击,内部用户误操作或恶意行为同样危险。SELinux可以限制特定用户角色。例如普通运维人员通过sudo执行命令时,进程仍然受到SELinux域约束。可以配置staff_u或user_u角色,限制其访问系统关键目录。对于需要执行系统管理任务的用户,分配sysadm_u角色,但仍然无法绕过SELinux策略直接读取某些敏感文件。这种强制访问控制与传统的DAC权限叠加,能有效降低内部权限滥用风险。
监控与审计SELinux拒绝日志配置完成后必须持续监控SELinux日志,及时发现异常访问尝试。/var/log/audit/audit.log中记录所有denied事件。可以安装setroubleshoot-server,它会将SELinux拒绝转换成可读的提示信息,并给出解决建议。但不要盲目按照提示执行,有些提示建议开启的布尔值可能过于宽松。定期分析日志中重复出现的拒绝记录,判断是业务需求还是攻击行为。如果某个域频繁尝试访问不属于它的文件类型,很可能说明该服务已经被入侵。
常见SELinux配置错误与规避方法第一个错误是直接复制网上教程执行setenforce 0,这会让之前的配置全部失效。第二个错误是使用chcon命令临时修改上下文,重启或重新标记后失效,应该用semanage fcontext持久化。第三个错误是遇到拒绝就开启所有httpd相关布尔值,导致SELinux形同虚设。第四个错误是自定义策略模块中允许了过宽的范围,比如allow httpd_t etc_t:file read,这会让httpd进程读取/etc下所有文件。正确做法是只允许读取特定文件,例如allow httpd_t etc_t:file { read open getattr },并且限制在特定文件名。
验证SELinux配置有效性的具体方法配置完成后不要只依赖getenforce确认状态。可以模拟攻击场景测试。例如在Web目录放置一个测试文件,尝试通过Webshell读取/etc/passwd,确认被SELinux拦截。或者以普通用户身份尝试访问其他用户home目录下的文件,观察audit日志是否记录denied。定期使用sealert -a /var/log/audit/audit.log生成报告,检查是否有新的策略缺口。在业务更新或部署新应用后,重新运行restorecon并检查日志,确保新文件的上下文正确。
针对容器与虚拟化环境的SELinux注意事项如果CentOS上运行Docker或KVM,SELinux的策略配置更加复杂。容器进程默认运行在container_t域,与宿主机其他进程隔离。不要为了容器方便而禁用SELinux,否则容器逃逸漏洞一旦被利用,攻击者可以直接控制宿主机。对于需要挂载宿主机目录的容器,使用docker run -v /host/path:/container/path:z或:Z参数自动重新标记挂载目录,避免手动chcon导致上下文错误。KVM虚拟机磁盘文件需要标记为svirt_image_t,否则虚拟机无法启动。
总结SELinux规避权限泄露的核心原则权限泄露的本质是进程获得了超出其职责范围的访问能力。SELinux通过强制类型隔离,将每个服务限制在最小权限域内。配置时要遵循最小授权原则,只开放业务必需的布尔值和策略规则。遇到拒绝日志先分析再处理,不要直接关闭SELinux。定期审计策略和日志,确保配置与实际业务同步。SELinux不是负担,而是CentOS服务器安全体系中最有效的权限泄露防护手段之一。
