引言
AppArmor 通过路径为基础的强制访问控制策略,对进程行为进行精细限制。在受限 shell 场景中,常将用户登录 shell 强制设置为轻量级解释器(如 BusyBox ash),并为其加载专用 profile,以阻止切换至功能更强的 shell 或访问敏感目录。
在打 HMV 靶机 Publisher 时,我遇到了一个 AppArmor 限制 ,并找到了一种有效的绕过方法:当 profile 对常规可执行路径(如 /bin/、/usr/bin/)施加权限继承约束时,可通过动态链接器所在路径(通常为 /lib/ 或 /lib64/)的规则差异,手动加载目标 shell,实现 profile 逃逸。
受限 Profile 剖析
目标 profile 针对 /usr/sbin/ash 制定,内容如下:
apparmor
#include <tunables/global>
/usr/sbin/ash flags=(complain) {
#include <abstractions/base>
#include <abstractions/bash>
#include <abstractions/consoles>
#include <abstractions/nameservice>
#include <abstractions/user-tmp>
deny /opt/ r,
deny /opt/** rwx,
/usr/bin/** mrix,
/usr/sbin/** mrix,
owner /home/** rwix,
}
关键约束分析:
-
明确拒绝敏感路径
deny /opt/ r,和deny /opt/** rwx,两条规则无条件禁止对/opt及其下所有路径的读、写、执行操作。即使 profile 整体处于 complain 模式(*在此模式下,违反 allow 规则的访问仅会被记录日志,但不会被阻塞),deny 规则仍强制生效,导致进程即使进入该目录也无法读取内容。 -
子进程权限继承
对
/usr/bin/**和/usr/sbin/**使用mrix规则,其中x无修饰符,等价于ix(inherit execute)。这意味着从当前受限 ash 直接执行这些路径下的任何程序时,子进程将完全继承父进程的 AppArmor profile,继续受到相同 deny 规则约束。注意:该 profile 虽未对
/bin/路径显式定义规则,但/bin是指向usr/bin的软链接,这意味着直接执行/bin/bash仍受到上述限制。
绕过原理:动态链接器路径规则差异
现代 Linux 系统中,几乎所有用户态动态链接二进制文件的 ELF 头部均包含 INTERP 段,指定动态链接器路径(如 /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2)。
当直接执行一个动态链接二进制文件时,内核实际执行流程为:
动态链接器路径 + 目标二进制路径
即内核会调用 /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /bin/bash。
AppArmor 在判断执行过渡时,以被执行文件的路径规则为准。在本 profile 中:
/bin/、/usr/bin/、/usr/sbin/等常规可执行路径被显式设置为mrix(继承执行)。- 但动态链接器所在路径
/lib/x86_64-linux-gnu/通常仅受 abstractions/base 等基础规则覆盖,未被施加同样的继承约束。 - 因此,当手动以动态链接器作为入口执行目标程序时:
sh
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /bin/bash
AppArmor 将根据动态链接器自身的执行规则进行 profile 过渡。由于该路径未被强制设置为继承模式,新启动的 bash 进程获得的是其自身默认 profile(通常为宽松标准 profile 或 unconfined),而非原 ash 的严格 profile。
结果:
- 新 bash 进程不再受
deny /opt/** rwx约束。 - 可正常读取并操作此前被禁止的
/opt目录内容。
绕过成功的关键条件
该技术成立的前提包括:
- profile 对常规可执行目录施加继承模式 (如
/usr/bin/** mrix),导致直接启动受限。 - 动态链接器路径未被同等约束 (常见于手工或模板生成的受限 profile,未显式添加
/lib/**/{ld-*} mrix)。 - 目标二进制为动态链接(静态编译的 bash 极少见,几乎所有发行版默认均为动态链接)。
加固建议
为阻断该绕过向量,profile 需补充以下规则:
apparmor
# 强制动态链接器继承当前 profile
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 mrix,
/lib64/ld-linux-x86-64.so.2 mrix,
# 更全面覆盖可能路径
/{,usr/}lib{,32,64}/**/{ld*,ld-linux*} mrix,
同时建议为常用 shell(如 /bin/bash、/usr/bin/bash)单独编写严格子 profile,避免默认过渡至宽松上下文。
结论
当 AppArmor profile 对常规可执行路径(如 /bin/、/usr/bin/)实施权限继承约束时,通过动态链接器所在的不受同等限制的路径(如 /lib/)手动加载目标 shell,可成功实现 profile 逃逸。该技术本质上利用了规则覆盖范围的差异:常规路径被严格继承控制,而动态链接器路径往往遗漏相应约束。
此绕过方式简洁高效,在安全策略配置不完备的环境中普遍有效,凸显了 AppArmor profile 设计中路径规则完整性和一致性的重要性。在实际加固实践中,必须对所有可能的执行入口(包括解释器和链接器)进行统一约束,方能构建坚固的防御边界。