当前位置: 首页 > news >正文

Linux内核安全模块深入剖析【2.5】

10.2.2 域间转换同 Tomoyo 一样 AppArmor 的强制访问控制机制是基于文件路径的。在 AppArmor 中的域主要是由进程所执行的文件的路径决定的。 Tomoyo 会不厌其烦地将进程以及进程的祖先所执行过的文件的路径都记录在进程的域中。 AppArmor 不同它只会将最后一次执行的文件的路径作为域。AppArmor 将域设计成一种树状结构域下可以有子域。这种设计的目的是让进程的域转换受到额外的限制。假设系统中有 A、 B、 C 三个域。系统管理员定制策略允许这三个域互相转换。域 A 下又有 a、 b、 c 三个子域。系统管理员可以定制策略允许域 A 转换到子域 a、 b、 c但无法定制出策略让域 B 和域 C 直接转换到域 A 的子域 a、 b、 c。和其他安全模块一样在 AppArmor 中域间转换的途径有两条一是执行文件二是进程运行时自我改变。同样域间转换会反映在策略上需要策略允许。1.文件执行AppArmor 中的域与进程所执行的文件相关所以在进程执行文件时就有可能引起域的变化。结果是下面几种情况之一1根据文件名找到域转换到文件所对应的域。这种情况又分为两种情况1在当前域中存在相关的子域转换到子域。2不存在子域或不允许转换到子域在当前域外存在一个以被执行的文件的文件名命名的域转换到那个外部域。2留在当前域。3转换到“不受控制”unconfined的域。10.1 节说过 AppArmor 的设计主旨是针对单个应用的安全而不致力于整个系统的安全。一般情况下 AppArmor 的策略只能覆盖一部分进程。系统中其他进程都工作在不受控制的状态这些进程的域就是“unconfined”。不仅如此 AppArmor 的策略还允许进程将域转换为“unconfined”从受控制的状态转换到不受控制的状态。2.自我改变AppArmor 的域的第二种转换方式是通过伪文件接口/proc/[pid]/attr/current。这种转换不能为所欲为需要受到几个条件的限制1只能改进程自己的域不能改别的进程的域。 2如果进程不是处在“unconfined”状态并且进程的 no_new_privs㊀ 被置位则不能修改。3如果进程不是处在“unconfined”状态并且进程的 no_new_privs 未被置位则需要策略允许改动。“自我改变”又有两种方式第一种方式是向/proc/self/attr/current 中写入“ changeprofile NewDomain”。如果策略允许那么执行后进程的域就是“NewDomain”。“changeprofile”是“单程车票”第二种方式“changehat”是“往返车票”。第二种方式是向/proc/self/attr/current 中写入“changehat token^hatdomain”如“changehat 1234^hat”如果策略允许那么执行后进程的域就是“hat”。之后进程再向/proc/self/attr/current 中写入“changehat 1234”进程的域就恢复为原先的域了。上面例子中的“1234”称为令牌token它是进程和内核之间的“小秘密”专门用来让进程返回原先的域。“changeprofile”可以用来做域间转换包括转换到外部域和转换到子域。“changehat”只能用于父域转换到子域。3. 命名空间AppArmor 也提供了命名空间namespace的概念不同命名空间中策略配置相互隔离不同的命名空间中同名的域可以有不同的策略。在实现中命名空间是一个被“:”包裹的字符串:namespace://domainname其中“//”是可选项。切换命名空间只能通过“ changeprofile”方式也就是向/proc/self/attr/current 中写入“:namespace://domainname”。10.3 策略语言AppArmor 的策略语言并不复杂但是文档太少。要想完整地描述 AppArmor 的策略语言需要阅读 AppArmor 用户态工具的源代码。下面举个例子简单描述一下{LIBVIRT}” libvirt ”/usr/sbin/libvirtd { #include abstractions/authentication capability kill, capability net_admin, /bin/* PUx,㊀ 关于 no_new_privs可以参考内核文档 prctl/no_new_privs.txt。/sbin/* PUx, audit deny /sbin/apparmor_parser rwxl, change_profile - {LIBVIRT}-[0-9a-f]*-[0-9a-f]*, rlimit data 100M, }AppArmor 的策略语言允许使用 include 语句包含一个已有的策略文件。 客体类别 capability和 rlimit 比较简单 capability 列出允许的能力 rlimit 列出限定的资源值。客体类别文件略复杂。其基本操作许可为 r读、 w写、 a添加、 l链接、 k锁、 m在 mmap 的内存中执行、 x执行。 x 又可以有若干前缀比如“PUx”。下面对前缀做个分析见表 10-1。这些前缀可以组合使用例如“pix”意思是先找有没有与被执行文件匹配的域如果没有就维持当前域不变。当然也不是所有前缀都可以组合的例如“p”和“P” “p”和“c”就不能组合。不知读者是否注意到一条策略语句的头部可以有修饰符例如下面列出的语句audit deny /sbin/apparmor_parser rwxl,audit 表示记录日志 deny 表示拒绝访问。 deny 的引入很重要有了它 AppArmor 可以基于黑名单进行访问控制。白名单是指策略只列出允许的操作没有列出的都不被允许。黑名单则相反。下面看个例子/bin/my-shell { file, capability, deny /home/zhi/my-test r, }这个策略允许处于/bin/my-shell 域的进程做任何操作除了读文件/home/zhi/my-test。下面再看一个“changehat”的例子#include tunables/global /usr/lib/apache2/mpm-prefork/apache2 { #include abstractions/base #include abstractions/nameservice capability kill, / rw, /** mrwlkix, ^DEFAULT_URL { #include abstractions/base #include abstractions/nameservice / rw, /** mrwlkix, } }hat 子域的定义需要前缀“^”。10.4 模式AppArmor 规定了四种工作模式 enforce、 complain、 unconfined、 kill。像其他安全模块一样 enforce 就是严格按照策略办事不符合策略的就拒绝访问请求 complain 是允许访问请求但会把违反策略的访问请求记录到日志中 unconfined 就是和没有 AppArmor 一样 AppArmor 不对访问请求做控制。不同的是 kill这种模式下不仅拒绝访问请求还会将违反策略的进程杀死。每个域都有自己的工作模式。不同的域可以工作在不同的工作模式之中。规定工作模式的方法是在域名后添加“flags”参数。举个例子/usr/bin/firefox flags(complain){ …}10.5 伪文件系统10.5.1 proc 文件系统/proc/[pid]/attr 目录及其下文件是 SELinux 引入内核的其他安全模块也可以用它来实现功能。 AppArmor 用到了/proc/[pid]/attr 目录下的部分文件 current、 prev、 exec。1 current此文件可读可写。读时返回进程所在的域。写时又分两种情况1 changehat写入一行changehat token[^hat name]举个例子changehat 1234^hat1意思是转到“hat1”子域同时记录“1234”作为与之对应的令牌。这个令牌是在从子域返回时用到的例如changehat 1234就会从子域“hat1”返回刚才的父域。2 changeprofile语法是changeprofile [:namespace:]profile2 prev显示前一个域的名字。“前一个域”特指在使用“changhat”机制转换域时内核中保留的父域前一个域。3 exec这个文件的操作方法和“current”文件相同。“exec”文件对应进程中专门在 execve 系统调用中使用的域名。10.5.2 sys 文件系统在/sys/modules/apparmor/parameters 目录下有很多文件通过它们可以动态调整或读取AppArmor 的运行状态。1 audit查看或设置审计日志模式。文件的内容为一个字符串 normal、 quiet_denied、 quiet、noquiet、 all。从代码注释中可以看出这 5 种模式的含义security/apparmor/include/audit.h #define AUDIT_MAX_INDEX 5 enum audit_mode { AUDIT_NORMAL, /* follow normal auditing of accesses */ AUDIT_QUIET_DENIED, /* quiet all denied access messages */ AUDIT_QUIET, /* quiet all messages */ AUDIT_NOQUIET, /* do not quiet audit messages */ AUDIT_ALL /* audit all accesses */ }2 audit_header查看或设置审计日志消息中是否出现消息头部数据。文件内容为一个字符 “y”“Y”与“1”表示出现 “n”“N”与“0”表示不出现。3 debug查看或设置 AppArmor 的调试模式。文件内容为一个字符 “y”“Y”与“1”表示处于调试模式 “n”“N”与“0”表示不处于调试模式。4 enabled这是一个只读文件用于查看 AppArmor 的状态。其内容为一个字符 “Y”表示 AppArmor处于使能状态其他表示 AppArmor 不处于使能状态。5 lock_policy查看或设置策略文件锁的状态。文件内容为一个字符 “y”“Y”与“1”表示不能修改策略 “n”“N”与“0”表示可以修改策略。6 logsyscall和前面的文件类似这个文件的内容是一个表示布尔值的字符。但是这个文件所对应的布尔值似乎在内核代码中没有用到。7 mode查看或设置 AppArmor 的整体模式。文件的内容是一个字符串值为下列之一 “enforce” “complain”“kill”与“unconfined”。8 paranoid_load决定加载策略文件时是否进行严格检查。文件内容为一个字符 “y”“Y”与“1”表示严格检查 “n”“N”与“0”表示不做严格检查。9 path_max查看或设置路径的最大长度文件内容是一个表示长度的整数。10.5.3 securityfs 文件系统同 Tomoyo 一样 AppArmor 也使用了 securityfs相关的目录通常在/sys/kernel/security/ apparmor。此目录下包含 4 个文件和两个子目录。下面描述它们的用法。1 .load这个文件用于加载策略。 AppArmor 的策略和 SELinux 类似也是二进制格式的。用户需要预先用一个工具apparmor_parser将用户友好的文本格式的策略文件编译为内核更易处理的二进制格式策略文件然后再通过.load 文件载入内核。2 .replace这个文件用于加载策略和.load 的区别是 .load 是添加 .replace 是替换。3 .remove这个文件用于删除策略。删除以域为单位。4 profiles这是一个只读文件虽然文件允许位标记可写但是内核根本没有实现此文件的写函数通过它可以读出所有策略。5 policy这是一个目录其下又有两个子目录 1 namespaces其下的文件或目录与名字空间有关。2 profiles其下的文件或目录与域有关。6 features这是一个目录其下有子目录和文件全部为只读接口通过它们可以得到当前系统支持的 AppArmor 特性㊀ 。举个例子$ cat /sys/kernel/security/apparmor/features/file/mask create read write exec append mmap_exec link lock当前系统对文件相关的操作许可控制包括 create、 read、 write、 exec、 append、 mmap_exec、link、 lock。10.6 总结AppArmor 的最大特点是“不安全”或者换一个积极正面的词汇——简单易用。 AppArmor的这个特点体现在两个方面1 AppArmor 设计的宗旨是安全加固某个应用或某几个应用。2 AppArmor 提供方法让用户可以用黑名单的方式定制策略。AppArmor 这么做有一定道理。在现实中一个系统迫切需要安全加固的往往只是一个或几个应用。例如一个 Web 服务器只有 Web 服务进程和外界交流 Web 服务安全了 90%的安全问题就解决了。抛开安全性 AppArmor 的缺陷是文档。到 2016 年 2 月 AppArmor 的文档还不能算是完善一些特性语焉不详一些文档前后矛盾。一个标榜易用性的安全模块却没有把文档做好实在是有些不应该。10.7 参考资料读者可参考 http://wiki.apparmor.net/index.php/Main_Page。习题AppArmor 设计的宗旨是安全加固某个或某几个应用。思考一下如何利用 AppArmor 来加固整个系统是否需要修改代码如果不修改代码又该如何制定策略
http://www.rkmt.cn/news/1362934.html

相关文章:

  • 对比直接使用原厂API体验Taotoken在路由容灾与稳定性上的差异
  • 用Python和xarray处理ERSST数据:一步步重现PDO指数计算(附完整代码)
  • 别再傻等下载了!手把手教你用wget离线部署sentence-transformers模型(以all-MiniLM-L6-v2为例)
  • 量子计算中的ZZ串扰问题与周期感知优化方法
  • 基于RTK-GPS与ResNet50的自主草坪清扫机器人系统设计与实践
  • 从PSCI到ATF:手把手带你拆解Linux ARM64平台CPU休眠唤醒的完整调用链
  • 别再花钱买网盘了!手把手教你在Windows服务器上免费搭建个人版Filebrowser(附端口映射与防火墙配置)
  • 麒麟V10 SP2服务器mate-indicators内存泄漏?别慌,手把手教你打补丁和降级auditd
  • 从/dev/snd文件看起:手把手教你理解Linux ALSA声卡驱动的设备命名规则
  • 告别Excel表格!手把手教你用OCSInventory-NG在Rocky Linux 9.3上搭建企业IT资产库
  • 安卓7+ HTTPS抓包失效原因与Fiddler实战绕过方案
  • 云环境负载均衡与虚拟机安全分配:核心挑战与实战解析
  • 别再只会`dnf makecache`了!深入理解CentOS 8 DNF源配置文件的那些关键参数
  • Claude如何让慢SQL提速8倍?揭秘向量嵌入+RAG协同优化的5个关键阈值
  • Godot移动端触觉反馈实战:从振动到交互语言
  • AI依赖如何引发金融市场系统性风险:从认知退化到同质化共振
  • 二、Socket 编程 TCP
  • Godot 4地形性能修复:图层混合、LOD切换与法线生成三大断点解决方案
  • VeriLoC:基于LLM的硬件设计质量预测技术解析
  • 十年未更新的开源激光计算器LaserCalc,在2024年还能怎么用?我的实战踩坑与配置指南
  • 从傅里叶定律到散热盘:手把手推导不良导体热导率测量公式(附Python数据处理代码)
  • 89、CAN FD硬件实现要点:控制器、收发器与MCU选型指南
  • 单尾检验 vs 双尾检验:选错一步,你的A/B测试结果可能全错了(附Python模拟代码)
  • 四足机器人视觉循线:从阈值分割到HSV跟踪的嵌入式实现
  • AI洗白:识别企业虚假AI宣传与构建真实技术能力
  • UE5 GPU崩溃真相:Windows TCC超时机制与注册表调优指南
  • 量子互联网:原理、挑战与未来应用
  • Unity实现CS级FPS手感的四大底层契约与枪械物理精调
  • 从手动部署到GitOps:AI工程化部署流水线的演进与实践
  • LLM多智能体系统在微服务自治运维中的架构设计与工程实践