AppArmor
AppArmor 是一种强制访问控制(Mandatory Access Control, MAC)系统,基于 Linux 安全模块(Linux Security Modules, LSM)实现。
就像其他大多数的 Linux 安全模块一样,AppArmor 是对默认的的自主访问控制(Discretionary Access Control, DAC)的补充,而非替代。因此,程序通过 AppArmor 获取到的权限不可能大于原本在 DAC 下拥有的权限。
Ubuntu,SUSE 和许多其他的发行版默认使用 AppArmor,而 RHEL(及其衍生发行版)所使用的 SELinux 需要特定的用户空间工具才能正常使用。SELinux 通过附加标签的方式管理所有的文件、进程和对象,因而十分灵活。不过,普遍认为 SELinux 难以配置,且需要支持扩展属性的的文件系统才能运作。相反,AppArmor 基于文件路径,配置文件也相对简单易懂。
AppArmor 通过对特定应用执定专用的规则集,主动保护操作系统和应用程序免受来自内外部的威胁,包括部分零日漏洞攻击。安全策略决定了每个应用所能够访问的系统资源及其权限。没有在安全配置文件中允许的访问,将被默认拦截。AppArmor 随附了一些默认策略,再结合使用高级静态分析与基于学习的工具,即使是极其复杂的应用程序,用户也可以在数小时内完成其 AppArmor 策略的编写。
任何违反策略的访问都将在系统日志中报告。也可以通过配置 AppArmor,令其在越权访问发生时,在用户桌面实时弹出警告通知。
安装[编辑 | 编辑源代码]
AppArmor 可以在所有的官方支持的内核中使用。
安装 apparmor包 以获取管理 AppArmor 的用户空间工具与库。要在启动时加载所有 AppArmor 安全配置文件,启用 apparmor.service
。
要在每次引导时将 AppArmor 作为默认的安全模型启用,设置以下的内核参数:
lsm=landlock,lockdown,yama,integrity,apparmor,bpf
lsm=
内核参数决定了 Linux 安全模块的初始化顺序。内核已配置的 lsm=
值可以通过 zgrep CONFIG_LSM= /proc/config.gz
查看,当前值可以通过 cat /sys/kernel/security/lsm
查看。
- 确保
apparmor
是参数列表中的第一个“主要”模块。[1]合法的值和顺序的样例可以在 security/Kconfig 查看。 lsm=
中不应包含capability
,因为它始终会被自动隐式包含。
自定义内核[编辑 | 编辑源代码]
自行编译内核时,需要启用以下选项:
CONFIG_SECURITY_APPARMOR=y CONFIG_AUDIT=y
要让内核在无需设置内核参数的前提下默认启用 AppArmor Linux 安全模型,需要额外添加 CONFIG_LSM
选项,并将 apparmor
设定为列表中的第一个“主要”模块。
CONFIG_LSM="landlock,lockdown,yama,integrity,apparmor,bpf"
使用方法[编辑 | 编辑源代码]
显示当前状态[编辑 | 编辑源代码]
检测 AppArmor 是否成功启动:
$ aa-enabled
Yes
显示当前运行状态,执行 aa-status(8):
# aa-status
apparmor module is loaded. 44 profiles are loaded. 44 profiles are in enforce mode. ... 0 profiles are in complain mode. 0 processes have profiles defined. 0 processes are in enforce mode. 0 processes are in complain mode. 0 processes are unconfined but have a profile defined.
在 complain 模式下,违反策略的访问将被允许,但该行为会被记录在日志中。complain 模式常用于了解程序正常运行所需要的权限,或是测试新撰写的配置文件是否合适。但是,需要注意的是,在配置文件中被设定为 deny 的规则在 complain 模式下仍然会强制执行。
在 enforce 模式下,违反策略的访问将被拒绝,并记录到日志中。
解析配置文件[编辑 | 编辑源代码]
使用 apparmor_parser
以加载、卸载、重启、缓存或是统计配置文件。默认行为(-a
)是以 enforce 模式加载配置文件。要以 complain 模式加载,请使用 -C
参数。要覆盖已有配置文件,使用 -r
参数。要删除配置文件,使用 -R
参数。每次操作也可能应用到多个配置文件上。参见 apparmor_parser(8) 手册页面以了解详情。
停用[编辑 | 编辑源代码]
要在当前会话临时停用 AppArmor,执行以下命令以停用所有配置文件:
# aa-teardown
要永久停用 AppArmor 配置文件,请停用 apparmor.service
。要阻止内核加载 AppArmor,删除在安装 AppArmor 时添加的 lsm=
内核参数。
配置[编辑 | 编辑源代码]
审计与生成配置文件[编辑 | 编辑源代码]
要创建新的配置文件,确保 Audit 框架正在运行,因为 Arch Linux 使用 systemd,内核日志默认不会保存到文件中。AppArmor 可以从用户空间的 auditd 进程抓取内核日志,从而协助编写配置文件。
可以使用 aa-genprof(8) 或 aa-autodep(8) 创建新的 AppArmor 配置文件。新创建的配置文件默认处于 complain 模式:此模式下,违反规则的行为仅会被记录,不会被拒绝。要交互式地创建配置文件,可以使用 apparmor包 包中的 aa-logprof(8)。配置完成后,请使用 aa-enforce(8) 将配置文件设置为 enforce 模式。此模式下,配置文件中的规则将被严格执行。此外,可以重复执行 aa-logprof(8) 以添加额外的规则,也可以使用 aa-complain(8) 将配置文件重新设置为 complain 模式。可以在此找到更为详细的教程:AppArmor wiki - Profiling with tools。
需要注意的是,aa-logprof(8) 也提供 deny 规则。不过根据 AppArmor 的设计逻辑,除非规则明确允许,否则任何行为都将被拒绝,因此严格来说没有必要使用 deny 规则。不过,deny 规则有以下两个用途:
- deny 规则的优先级比 allow 规则更高,在
/etc/apparmor.d/abstractions
中的许多 abstraction 中都有使用,用来阻断任何对重要文件(夹)的访问。这样做能防止创建 allow 规则时可能的疏忽,使得配置文件不会太宽松。 - deny 规则执行时不会在日志中记录,使得后续执行 aa-logprof 时产生更为简洁的日志。需要注意的是,即使是在 complain 模式下,deny 规则也会被严格执行――因此,如果程序在 complain 模式下还是会出错,应该检查在某一配置文件或其包含的 abstraction 中,是否有一条 deny 规则导致了此问题。
另外,也可以手动编写配置文件, 在此查看教程:AppArmor wiki - Profiling by hand。
除了 /etc/apparmor.d/
中的默认配置文件外,在 /usr/share/apparmor/extra-profiles/
中还有更多预定义的配置文件。不过,这些配置文件并非一定适用于生产环境,因此可能需要手动修改或使用 aa-logprof(8)。
也可以在 apparmor.d 项目处找到额外的 AppArmor 规则集。不过,直到撰写本文时,该项目并非稳定可用。
解读配置文件[编辑 | 编辑源代码]
配置文件是可读性很高的文本文件,保存在 /etc/apparmor.d/
下,定义了某个可执行文件的权限。以下是一个典型的配置文件:
/etc/apparmor.d/usr.bin.test
#include <tunables/global> profile test /usr/lib/test/test_binary { #include <abstractions/base> # Main libraries and plugins /usr/share/TEST/** r, /usr/lib/TEST/** rm, # Configuration files and logs @{HOME}/.config/ r, @{HOME}/.config/TEST/** rw, }
以 @
符号开头的字符串是在 abstraction(/etc/apparmor.d/abstractions/
),tunables(/etc/apparmor.d/tunables/
或配置文件本身中定义的变量。#include
将其他配置文件中的内容包含到此配置文件中来。路径后的字符是访问权限。使用 AppArmor 的通配符语法以实现模式匹配。
以下权限涵盖了最常见的使用场景:
r
— 读取:读取数据w
— 写入:创建,删除,写入文件,或是附加内容到文件尾部m
— 映射:将文件映射为可执行内存x
— 执行:执行文件。需要在前面加上修饰符,形如px
(执行时切换配置文件)
注意,定义的权限始终无法使程序获得大于原本在 DAC 中拥有的权限。
此处仅提到了很浅显的内容。要查询更为详细的文档,请查看 apparmor.d(5) 手册页和 官方文档。
提示与技巧[编辑 | 编辑源代码]
拒绝访问后发出桌面通知[编辑 | 编辑源代码]
当AppArmor拒绝了程序的访问后,通知进程可以显示桌面通知。通过以下步骤,可以在登录时自动启动aa-notify进程:
安装Audit framework并且启动/启用用户空间的Linux Audit进程。之后将你的桌面用户添加到 audit
用户组,从而允许其读取审计日志(audit logs):
# groupadd -r audit # gpasswd -a user audit
Add audit
group to auditd.conf
:
/etc/audit/auditd.conf
log_group = audit
wheel
or adm
.Install python-notify2包 and python-psutil包.
Create a desktop launcher with the below content:
~/.config/autostart/apparmor-notify.desktop
[Desktop Entry] Type=Application Name=AppArmor Notify Comment=Receive on screen notifications of AppArmor denials TryExec=aa-notify Exec=aa-notify -p -s 1 -w 60 -f /var/log/audit/audit.log StartupNotify=false NoDisplay=true
Reboot and check if the aa-notify
process is running:
$ pgrep -ax aa-notify
For more information, see aa-notify(8).
缓存配置文件以提高 AppArmor 启动速度[编辑 | 编辑源代码]
Since AppArmor has to translate the configured profiles into a binary format it may significantly increase the boot time. You can check current AppArmor startup time with:
$ systemd-analyze blame | grep apparmor
To enable caching AppArmor profiles, uncomment:
/etc/apparmor/parser.conf
## Turn creating/updating of the cache on by default write-cache
To change default cache location add:
/etc/apparmor/parser.conf
cache-loc=/path/to/location
/var/cache/apparmor/
, previously it was /etc/apparmor.d/cache.d/
.Reboot and check AppArmor startup time again to see improvement:
$ systemd-analyze blame | grep apparmor
排错[编辑 | 编辑源代码]
无法启动 Samba SMB/CIFS 服务[编辑 | 编辑源代码]
aa-logprof 无法抓取事件[编辑 | 编辑源代码]
Audit framework 日志可能包含特殊字符 0x1d
[5]。这个问题有一个 AppArmor bug report。解决办法是执行以下命令:
# aa-logprof -f <(sed 's/\x1d.*//' < /var/log/audit/audit.log)
升级到 AppArmor v4 后无法登录[编辑 | 编辑源代码]
在非常罕见的情况下,升级到 AppArmor v4 会导致无法登录到任何账户。
系统日志中可能包含类似如下内容的错误:
unix_chkpwd[1612]: check pass; user unknown unix_chkpwd[1612]: password check failed for user (john) gdm-password][1574]: pam_unix(gdm-password:auth): authentication failure; logname= uid=0 euid=0 tty=/dev/tty1 ruser= rhost= user=john kernel: audit: type=1400 audit(1730844640.468:171): apparmor="DENIED" operation="capable" class="cap" profile="unix-chkpwd" pid=1612 comm="unix_chkpwd" capability=2 capname="dac_read_search" kernel: audit: type=1400 audit(1730844640.468:172): apparmor="DENIED" operation="capable" class="cap" profile="unix-chkpwd" pid=1612 comm="unix_chkpwd" capability=1 capname="dac_override"
这可能是由于 root
账户无法读取 /etc/shadow
和/或 /etc/gshadow
导致的(例如,这些文件的权限位(Permission bits)尚未设定)。因此,可以试试以下解决办法:
- 重启,然后停用 AppArmor(在启动时编辑 Bootloader 参数,或者使用尚未启用 AppArmor 的 fallback 启动项)。
- 以
root
身份登录,然后设定正确的文件权限:chmod 600 /etc/shadow /etc/gshadow
- 再次重启。
不同 Linux 发行版之间的区别[编辑 | 编辑源代码]
Information you find often is about AppArmor on Ubuntu, which can be confusing, since Ubuntu carries a lot of kernel patches regarding AppArmor. Other distributions may also carry their own kernel patches, while Arch Linux uses a close-to-mainline kernel.
For example, while apparmor.d(5) already documents dbus
rules, they require support from AppArmor userspace tools, kernel and D-Bus daemon[6]. The corresponding kernel patch[7] is applied by Ubuntu, but not included in mainline Linux and official Arch kernels. (Support also varies by D-Bus implementation.)
AppArmor-specific kernel patches applied by Ubuntu can be found at (replace oracular
with the codename of the Ubuntu version you are interested in):
https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/oracular/log/?qt=grep&q=UBUNTU%3A+SAUCE%3A+apparmor
The ABI versions supported by the userland tools can be found in /etc/apparmor.d/abi/
. The ABI supported by the currently running kernel can be shown with:
$ aa-features-abi --extract
参见[编辑 | 编辑源代码]
- Wikipedia:AppArmor
- AppArmor wiki
- AppArmor Core Policy Reference — Detailed description of available options in a profile
- Ubuntu Tutorial — General overview of available utilities and profile creation
- Ubuntu Wiki — Basic command overview
- AppArmor Versions — Version overview and links to the respective release notes
- Kernel Interfaces — Low level interfaces to the AppArmor kernel module
- wikipedia:Linux Security Modules — Linux kernel module on which basis AppArmor is build upon
- AppArmor in openSUSE Security Guide