十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Linux安全模型全解析:从DAC权限到LSM强制访问控制

Linux安全模型全解析:从DAC权限到LSM强制访问控制 简介《基于Linux的操作系统安全模型》是一篇面向Linux系统开发、安全领域研究者及高校相关专业学生的学术文献聚焦传统自主访问控制DAC存在的权限滥用、setuid提权与越权读取等隐患在RBAC、Bell-LaPadula模型和格模型基础上提出改进的角色安全模型。资料包内收录1个PDF文档约165KB包含论文全文与核心模型说明适合系统安全课程研读、课题立项参考或安全功能设计时的资料比对。已有181人学习属于该方向上篇幅精简但体系完整的技术论文。文中详细讨论了S-LINUX中的三权分立角色管理包括超级用户、安全管理员、审计员的职责划分与互相制约关系并结合用户-角色多对一映射、安全标签设置、系统调用改造等实现细节说明如何在Linux中同时启用DAC与MAC来保证数据机密性和完整性。该模型还可推广至其他UNIX系列操作系统对实现B1级安全操作环境及权限-信息流协同管理具有较强的工程指导价值。1. 安全模型在Linux下的真实坐标从权限位到强制访问控制在Linux上谈“安全模型”很多人第一反应是chmod 700但真正决定一个进程能读什么、能写什么、能不能跨界的那套判断逻辑是由好几层机制叠出来的以UID/GID为基础的DAC权限以capability位拆分root特权的能力模型再往上由LSM钩子承载的强制访问控制SELinux、AppArmor最后是审计子系统把每次允许和拒绝记录下来。日常看到的Permission denied大多来自第一层而真正扛住提权、堵住横向渗透的往往是后面几层。这篇内容把“用户-文件权限-内核钩子-强制访问控制-审计”串成一条可复现链路适合运维、容器安全和做安全基线的工程师。文中命令在RHEL系和Debian系发行版上都能直接验证涉及内核参数的地方会标注适用场景。理解这一整套模型不只能解释“为什么root也会被拒绝”更能回答“加了一台服务器后安全基线应该从哪里开始”这个问题。2. 从DAC到CapabilitiesLinux权限模型的基座与边界2.1 UID/GID与九个权限位一切DAC判断的起点DAC自主访问控制是Linux权限模型的第一层文件属主可以自主决定谁能访问自己拥有的对象。一个进程完成每次文件访问前内核要做的判断是当前进程的有效UID和有效GID是什么目标文件的属主、属组、权限位是什么然后决定进程落在owner、group、other三段里的哪一段。这个模型优点是可预期、开销小缺点是粒度粗——没有“中间态”要么属于属主那侧要么属于组那侧要么算“其他人”。九个权限位对文件和目录的含义不同落实到安全判断时尤其容易混淆。下表是我在分析故障时经常贴在边上的对照权限位对普通文件对目录r读取文件内容列出目录项ls可见w修改文件内容、截断增/删/改名目录下的项x作为程序执行进入目录、参与路径检索带上执行位还有个特殊形态setuid。chmod us会让进程执行时把有效UID临时切换成文件属主这是早期系统提权最常见入口也是安全基线里需要重点排查的对象。find / -perm -4000 -type f这把命令能扫出所有带setuid位的文件结果里出现非系统包自带的二进制就要警惕了。内核具体做第一轮检查的函数是generic_permission()进程是文件属主就看owner位属于属组但非属主就看group位其余看other位这轮不过再尝试ACL再不过返回-EACCES。这里有个高频错误排查“某用户读不到文件”只看文件权限位而忽略了整个路径中每一层目录的x位。访问/home/alice/report.log如果/home/alice没有x权限即使文件自身是644路径解析也会失败。我一般用namei -l把路径逐层摊开确认[rootlocalhost ~]# namei -l /var/lib/mysql/ibdata1 f: /var/lib/mysql/ibdata1 dr-xr-xr-x root root / drwxr-xr-x root root var drwxr-xr-x root root lib drwxr-xr-x mysql mysql mysql -rw-r----- mysql mysql ibdata1namei按“路径组件 → 属主/属组 → 权限位”逐行输出任何一层权限异常都会直接暴露。很多服务起不来的“诡异”权限问题最终都出在中间目录缺x位这类问题用strace看openat返回EACCES往往定位不到具体层级先跑namei是最快路径。2.2 Capabilities机制把root的一篮子特权拆成位掩码root的问题在于特权都绑在一个UID上chown、mount、启动raw socket、修改路由表、ptrace其他进程这些操作本来互不相干却都因为“是root”而一次性放行。内核从2.2开始引入capability机制把root特权拆成一组细粒度能力位每次特权操作单独检查对应的CAP_*位。从安全模型角度理解capability两条主线最关键。第一特权判断从“对象是不是root”变为“进程能力集合里有没有CAP_SYS_ADMIN”第二可执行文件可以携带filesystem capability普通用户执行该文件时获得指定能力替代早年必须依赖setuid二进制的做法。这两条改变了威胁模型边界攻击者拿下一个服务进程后如果进程能力集已被裁剪就无法继续mknod、chroot或加载内核模块。查看和设置能力位的常用命令是getcap与setcap。给抓包程序单独授权是最常见操作# 仅授予抓包所需的能力位而非整个root [rootlocalhost ~]# setcap cap_net_raw,cap_net_admineip /usr/bin/dumpcap [rootlocalhost ~]# getcap /usr/bin/dumpcap /usr/bin/dumpcap cap_net_admin,cap_net_raweipeip里的e、i、p分别对应effective、inheritable、permitted三张能力集合effective是进程当前生效的能力permitted是允许临时提升的上限inheritable是exec子进程时能往下传的位。生产环境一般只给e和pi如果不需要继承就不该放开否则子进程会带着用不到的能力扩大攻击面。容器是这套机制最贴切的应用场景。Docker默认丢弃进程大部分能力位只保留CHOWN、DAC_OVERRIDE、FOWNER、FSETID、KILL、SETGID、SETUID、SETPCAP、NET_BIND_SERVICE、NET_RAW、SYS_CHROOT等少数位在Kubernetes的securityContext里还能继续用drop: [ALL]再按需加回。到这里能力模型解决的正是“root如何安全降级”的问题它让一个程序拥有权限却不拥有全部权限。2.3 POSIX ACL与默认ACL突破九个权限位的授权边界当“属主、属组、其他人”三段不够用时POSIX ACL提供第二套授权入口可以为任意指定用户或指定组单独授权也可以对目录设置default ACL让新建文件和子目录自动带上同样规则。setfacl与getfacl是对应的两个操作命令。ACL最典型的生产用法是给共享目录做细粒度授权。下面命令给/srv/shared增加用户alice的读写执行权限并把该规则设为default目录里新建的文件会自动继承用户条目对应的mask限制[rootlocalhost ~]# setfacl -R -m u:alice:rwx,d:u:alice:rwx /srv/shared [rootlocalhost ~]# getfacl /srv/shared # file: srv/shared # owner: root # group: root user::rwx user:alice:rwx group::r-x mask::rwx other::--- default:user::rwx default:user:alice:rwx default:group::r-x default:mask::rwx default:other::----m表示修改ACLd:前缀表示default ACL-R递归应用到当前已存在的子对象。有两个ACL使用中的常见坑第一ls -l输出权限位末尾出现只代表该文件有ACL内容仍需通过getfacl查看第二cp不带-p不会保留ACL备份共享目录要用tar --acls或cp -p。另外注意mask字段会限定用户和组条目的实际最大权限只改u:alice:rwx而mask是r-xalice最终拿到的仍是只读加执行。ACL还有一个容易被忽略的运维特性设置ACL后chmod组权限位会被同步到mask。也就是说命令行里执行chmod 750后ACL的named user权限可能被mask盖住表现为“getfacl里权限是对的但实际访问还是被拒”。这类问题在给NFS或Samba共享目录配权限时反复出现判断依据永远是getfacl里的mask行不是ls -l那组符号位。3. LSM钩子与强制访问控制SELinux和AppArmor的拦截逻辑3.1 LSM钩子列表与注册流程安全模块怎么“挂”进内核DAC和capability解决的是“对象属主说了算”和“root特权拆分”但两者都回答不了一个问题如果属主进程被攻击者控制系统能否依据另一套全局策略阻止它越界操作这就是强制访问控制MAC存在的意义。Linux上承载MAC的机制是LSMLinux Security Module框架。LSM在内核关键对象操作的必经路径上放置钩子SELinux和AppArmor通过注册钩子函数接入访问决策。一次open()文件调用的完整判定路径是VFS层先做DAC检查再调用security_inode_permission钩子由当前加载的LSM模块给出最终决策。钩子返回0放行、返回负errno拒绝比如-EACCES或-EPERM。这个“DAC之后、对象操作生效之前”的插入点让安全模型不修改对象语义只负责拦与放。查看当前内核挂载了哪些LSM模块读sysfs即可[rootlocalhost ~]# cat /sys/kernel/security/lsm capability,selinux输出顺序即模块注册顺序capability永远排第一个因为基础能力检查本身就是通过LSM框架实现的——这是一个容易被误解的点capability既是上一章讲的能力模型的内核实现也占据一个LSM槽位。SELinux源码中最常看的部分在security/selinux/hooks.c里面按钩子生命周期排布了所有回调函数。想深入学习LSM直接grep钩子名然后沿回调看决策分支比通读架构文档更高效。实践上已经有通过hook住security_file_open实现的透明加密方案被多家国产操作系统厂商内置文件落盘时加密被允许的进程读取时自动解密。这类方案绕不开LSM钩子底层逻辑就是安全模块在DAC之后、进程拿到数据之前有机会做拦截或转换。看到“linux 内核 动态加载 file_operations 拦截 read write”这类描述本质也在同一套钩子框架里做文章。3.2 SELinux类型强制标签、TE规则与三种运行模式SELinux为系统里的每个主体进程和客体文件、端口、socket、甚至内存对象打上安全上下文标签标签格式是system_u:system_r:httpd_t:s0四个字段分别代表用户、角色、类型、灵敏度。绝大多数访问控制决策只由类型字段决定所以这套机制叫类型强制Type EnforcementTE。当httpd_t类型的进程试图读取var_t类型的文件时SELinux查询TE规则表里有没有allow httpd_t var_t:file read这条没有就拒绝并在审计日志写一条AVC denied。SELinux运行模式在/etc/selinux/config的SELINUX行配置三种模式用一张表就能对比清楚模式行为适用场景enforcing拒绝并记录所有违规生产环境合规目标permissive只记录违规、不拒绝策略调试、灰度验证disabled不做标签与决策确认不需要SELinux生产环境遇到服务被SELinux拦截最常见的错误是直接setenforce 0关掉。正确的流程是先切到permissive跑一轮业务流量把违规AVC记录导出来再判断是打错标签还是缺策略。对文件标签修正优先使用semanage fcontext写入持久化规则而不是chcon——chcon只改文件系统里的标签被restorecon重新标记后会被恢复。semanage属于policycoreutils-python-utils包最小化安装的RHEL系主机需要单独装。在RHEL系环境里还有一个经常碰到的点SELinux布尔值。getsebool -a可以列出所有开关典型如httpd_can_network_connect、samba_export_all_rw。这些开关把高频策略组合预置成可调项避免每个操作都去写一条TE规则。调整后要用setsebool -P持久化-P会写入策略存储否则重启后回到默认值。3.3 AppArmor路径约束与profile编写Debian/Ubuntu系默认的MAC是AppArmor。它与SELinux最直观的区别是一个按路径和程序对象描述策略不给整个系统铺标签一个基于标签和类型规则需要全局策略基座。AppArmor把策略粒度落在每个可执行程序上每个受限程序对应一个profile对应用开发者更友好。用nginx写一个最简profile示范# /etc/apparmor.d/usr.sbin.nginx #include tunables/global /usr/sbin/nginx { #include abstractions/base /etc/nginx/** r, /var/log/nginx/*.log w, /var/run/nginx.pid w, /usr/sbin/nginx mr, /usr/lib/nginx/** mr, network inet tcp, }每行末尾的字母是权限位r读、w写、m内存映射执行/etc/nginx/**递归匹配下级目录network inet tcp限定仅允许TCP网络。profile写完后用apparmor_parser -r重新加载并通过aa-status观察进程约束情况。AppArmor也有complain模式对profile执行aa-complain后只记录违规不拦截适合上线前观察程序实际需要访问哪些路径。对麒麟、统信UOS、凝思等国产发行版安全模型的默认形态并不统一有的基于Debian默认启用AppArmor有的参照RHEL启用SELinux但策略未调优还有的构建时直接关闭了LSM注册入口。做安全基线时照搬通用加固脚本会出现“明明执行了setenforce 1实际LSM列表里连selinux都没有”的情况。判断依据就是第一节的/sys/kernel/security/lsm这一点在下一章串成完整流程。4. 把安全模型落到发行版加固配置与参数调优4.1 三条命令确认当前LSM模型与运行模式任何加固动作开始前都要先确认这台机器上真正生效的是什么模型。三条命令组成完整状态快照# 1. 查看LSM加载列表 cat /sys/kernel/security/lsm # 2. SELinux当前模式与配置文件 getenforce grep ^SELINUX /etc/selinux/config # 3. AppArmor是否加载以及进程约束统计 aa-status --enabled aa-status这三条命令应该出现在任何系统初始化脚本的前置阶段。如果第一行输出只有capability说明发行版构建时虽有SELinux/AppArmor源码但未被启用。SELinux场景下修改GRUB参数编辑/etc/default/grub在GRUB_CMDLINE_LINUX里加securityselinux selinux1然后执行grub2-mkconfig -o /boot/grub2/grub.cfg或update-grub重启生效。AppArmor场景同理启动参数写apparmor1 securityapparmor。这里要特别提一句SELinux和AppArmor不建议同时开启LSM框架虽然允许多模块共存但两套MAC策略同时决策会带来排查复杂度实际生产环境几乎没人这么做。4.2 用户、sudo与最小命令集授权的基线配置落实安全模型的第一道执行者是账户系统。禁止root直接登录、以普通用户加sudo执行管理操作是多数合规检查的硬指标。sudo规则里最小权限原则要求只放行该岗位确实需要的命令且必须写绝对路径# 新建nginx运维账号仅允许查看systemctl状态和检查nginx配置 useradd -m -s /bin/bash ops-nginx cat /etc/sudoers.d/ops-nginx EOF ops-nginx ALL(root) NOPASSWD: /usr/bin/systemctl status *, /usr/sbin/nginx -t EOF chmod 440 /etc/sudoers.d/ops-nginx/etc/sudoers.d下的文件要求属主root、权限440权限不正确sudo会直接拒绝加载。NOPASSWD后面跟的命令越少越好涉及敏感操作的命令建议去掉NOPASSWD让执行时再次验证身份。如果后续需要调整用visudo -f /etc/sudoers.d/ops-nginx打开语法校验通过再保存。账户侧还有两个容易被忽略的点一是为每个服务创建独立运行用户例如nginx直接用nginx用户跑而不是用www-data大锅饭二是给这类服务账号设置nologinshell避免被用来登录。服务账号不该出现在/etc/passwd的可交互shell列表里。4.3 systemd沙箱参数与进程能力裁剪的实战组合systemd单元文件里有一组直接映射到内核安全能力的参数不用改程序代码只在service定义里声明就能完成大半沙箱化。最常用的是四个ProtectSystemstrict把整个文件系统改为只读挂载只在显式声明路径保留写PrivateTmpyes给进程独立私有/tmp规避/tmp下的符号链接竞争NoNewPrivilegesyes禁止进程及其子进程通过setuid、setcap等方式获取新特权CapabilityBoundingSet直接裁剪进程能持有的能力位。这四个参数组合后能起到类似容器只读层的写保护效果在很多风险控制要求里被视为容器隔离的替代项。参数含义推荐值ProtectSystem全盘只读可选strictstrictPrivateTmp独立临时目录yesNoNewPrivileges禁止setuid提权yesCapabilityBoundingSet能力边界集合按需给最少位下面是一个nginx加固片段放到/etc/systemd/system/nginx.service.d/hardening.conf[Service] ProtectSystemstrict ProtectHomeyes PrivateTmpyes NoNewPrivilegesyes RestrictAddressFamiliesAF_INET AF_INET6 AF_UNIX CapabilityBoundingSetCAP_NET_BIND_SERVICE CAP_SETUID CAP_SETGID ReadOnlyPaths/etc/nginx参数含义RestrictAddressFamilies只允许IPv4、IPv6与UNIX socket三种协议族CapabilityBoundingSet把nginx可能获得的能力收拢到三个位。配置后执行systemctl daemon-reload重启服务通过以下命令查看暴露面systemd-analyze security nginx输出会把每项安全特性标成exposed或enabled最后给一个0到10的整体暴露分数越接近0越安全。常见服务默认分数在8以上加上上面的配置后通常能压进2以内。提示改完sandbox配置服务起不来时不要急着删配置先看journalctl -u nginx。沙箱参数要逐步收紧一次加太多会掩盖真实的工作路径依赖。4.4 容器场景下安全模型如何映射容器与主机共享内核也共享LSM钩子。Docker默认丢弃容器进程的大部分能力位Kubernetes又通过Pod的securityContext进一步裁剪。一个常见的Pod安全模型声明securityContext: runAsNonRoot: true runAsUser: 10001 capabilities: drop: [ALL] add: [NET_BIND_SERVICE] seccompProfile: type: RuntimeDefaultrunAsNonRoot拒绝root容器drop: [ALL]清掉所有能力位再只加回web服务必须的绑定端口权限seccompProfile交给运行时默认的系统调用过滤策略。这是云原生环境下把Linux安全模型从主机层映射到容器层最常见的落地方法。容器里的--privileged要尽量避免它等价于把所有cap全部还给进程。这里需要补一个定位安全模型解决的是访问授权不是恶意代码查杀。真正的主机防护还需要叠加杀毒软件或HIDS主机入侵检测安全模型负责把权限边界画清楚HIDS负责在边界内发现异常行为两者不能互相替代。5. 用审计日志验证安全模型从允许/拒绝事件反推配置缺口5.1 从AVC拒绝记录定位SELinux的拦截现场“安全模型是否生效”不能靠猜。SELinux的每次拒绝决策都会记录在/var/log/audit/audit.log对应事件类型是AVC。用ausearch按时间窗口把最近的拒绝取出来ausearch -m avc -ts recent一条典型拒绝事件的要素是scontext发起进程的安全上下文、tcontext目标对象的安全上下文、tclass对象类型。看到permissive0说明决策发生在enforcing模式拒绝是真实生效的调试期间会看到permissive1。拿到拒绝事件后修正文件标签优先semanage fcontext添加持久化映射目录级标签写法如下semanage fcontext -a -t httpd_sys_content_t /var/www/html(/.*)? restorecon -Rv /var/www/html如果服务确实需要访问某些被拒对象又写不好TE规则可以用audit2allow -w -a生成策略草案人工审一遍再加载。生成前先确认评审别把拒绝规则直接合入。5.2 主动验证给关键路径添加自定义审计跟踪除了被动看日志基线验证更常需要主动证明“不该有的访问进不来”。auditctl可以针对路径和系统调用设规则无论结果如何都留下记录。验证某个私钥文件是否被异常读取auditctl -w /etc/ssh/ssh_host_rsa_key -p rwa -k ssh_key_watch ausearch -k ssh_key_watch-w添加路径监视-p指定读、写、属性变更-k是过滤关键词。生产环境临时规则重启即失需要写入/etc/audit/rules.d/持久化。调试完用auditctl -l列出当前规则并及时撤销避免无效审计日志刷盘。最后给一个实战中很受用的验证技巧用setpriv启动一个剥离了大量能力位的子进程尝试执行chroot或mount这类高权限操作观察它是否在内核层被拦截。这套做法既能检验CapabilityBoundingSet是否被systemd正确施加也能直观理解“能登录root账号”和“能调用特权操作”之间的差距。在Linux面试题里它经常被拿来考察对安全模型的理解深度在生产里它是快速区分“主机被攻破”和“服务配置故障”的有效手段。本文还有配套的精品资源点击获取
返回列表