跳转到内容跳转到页面导航:上一页 [访问键 p]/下一页 [访问键 n]
适用于 openSUSE Leap 15.6

30 Profile 组件和语法 编辑源文件

构建 AppArmor profile 来限制应用程序是直接且直观的。 AppArmor 附带了几个辅助创建 profile 的工具。它不需要您进行任何编程或脚本处理。管理员唯一需要完成的任务是确定最严格的访问策略和执行权限,以加固需要加固的每个应用程序。

如果软件配置或期望的活动范围发生变化,则只需要更新或修改应用程序 profile。 AppArmor 提供了直观的工具来处理 profile 更新和修改。

在选择要 profile 的程序后,您就可以开始构建 AppArmor profile 了。为此,了解 profile 的组件和语法非常重要。 AppArmor profile 包含几个构建块,有助于构建简单且可重用的 profile 代码

包含文件

包含语句用于从其他 AppArmor profile 中提取部分内容,以简化新 profile 的结构。

抽象

抽象是按常见应用程序任务分组的包含语句。

程序块

程序块是包含语句,其中包含特定于程序套件的 profile 片段。

Capability 条目

Capability 条目是 profile 条目,用于任何 POSIX.1e https://en.wikipedia.org/wiki/POSIX#POSIX.1 Linux capability,允许对受限进程通过需要权限的系统调用所允许的操作进行细粒度控制。

网络访问控制条目

网络访问控制条目根据地址类型和族来调解网络访问。

局部变量定义

局部变量为路径定义快捷方式。

文件访问控制条目

文件访问控制条目指定应用程序可以访问的文件集。

rlimit 条目

rlimit 条目设置和控制应用程序的资源限制。

有关确定要 profile 的程序,请参阅 第 29.2 节,“确定要免疫的程序”。要开始使用 YaST 构建 AppArmor profile,请转到 第 32 章,使用 YaST 构建和管理 profile。要使用 AppArmor 命令行界面构建 profile,请转到 第 33 章,从命令行构建 profile

有关创建 AppArmor profile 的更多详细信息,请参阅 man 5 apparmor

30.1 AppArmor profile 分解为其组成部分 编辑源文件

解释 profile 的组成以及如何创建 profile 的最简单方法是显示示例 profile 的详细信息,在本例中,针对名为 /usr/bin/foo 的假设应用程序。

#include <tunables/global>1

# a comment naming the application to confine
/usr/bin/foo2 {3
   #include <abstractions/base>4

   capability setgid5,
   network inet tcp6,

   link /etc/sysconfig/foo -> /etc/foo.conf,7
   /bin/mount            ux,
   /dev/{,u}8random     r,
   /etc/ld.so.cache      r,
   /etc/foo/*            r,
   /lib/ld-*.so*         mr,
   /lib/lib*.so*         mr,
   /proc/[0-9]**         r,
   /usr/lib/**           mr,
   /tmp/                 r,9
   /tmp/foo.pid          wr,
   /tmp/foo.*            lrw,
   /@{HOME}10/.foo_file   rw,
   /@{HOME}/.foo_lock    kw,
   owner11 /shared/foo/** rw,
   /usr/bin/foobar       Cx,12
   /bin/**               Px -> bin_generic,13

   # a comment about foo's local (children) profile for /usr/bin/foobar.

   profile /usr/bin/foobar14 {
      /bin/bash          rmix,
      /bin/cat           rmix,
      /bin/more          rmix,
      /var/log/foobar*   rwl,
      /etc/foobar        r,
   }

  # foo's hat, bar.
   ^bar15 {
    /lib/ld-*.so*         mr,
    /usr/bin/bar          px,
    /var/spool/*          rwl,
   }
}

1

这会加载包含变量定义的的文件。

2

被限制的程序的规范化路径。

3

花括号 ({}) 作为包含语句、子 profile、路径条目、capability 条目和网络条目的容器。

4

此指令提取 AppArmor profile 的组件以简化 profile。

5

Capability 条目语句启用 29 个 POSIX.1e 草案 capability 中的每一个。

6

一个指令,确定允许应用程序的网络访问类型。有关详细信息,请参阅 第 30.5 节,“网络访问控制”

7

一个链接对规则,指定链接的源和目标。有关详细信息,请参阅 第 30.7.6 节,“链接对”

8

花括号 ({}) 允许列出的每种可能性中的每一个,其中之一是空字符串。

9

一个路径条目,指定程序可以访问的文件系统区域。路径条目的第一部分指定文件的绝对路径(包括正则表达式通配符),第二部分指示允许的访问模式(例如 r 表示读取,w 表示写入,x 表示执行)。任何类型的空白(空格或制表符)都可以位于路径之前,但必须分隔路径和模式说明符。访问模式和尾随逗号之间的空格是可选的。在 第 30.7 节,“文件权限访问模式” 中可以找到有关可用访问模式的综合概述。

10

此变量扩展为一个可以更改的值,而无需更改整个 profile。

11

一个所有者条件规则,授予对用户拥有的文件的读取和写入权限。有关详细信息,请参阅 第 30.7.8 节,“所有者条件规则”

12

此条目定义到本地 profile /usr/bin/foobar 的转换。有关可用执行模式的综合概述,请参阅 第 30.12 节,“执行模式”

13

一个命名 profile 转换到位于全局范围内的 bin_generic profile。有关详细信息,请参阅 第 30.12.7 节,“命名 profile 转换”

14

在此部分中定义了本地 profile /usr/bin/foobar

15

此部分引用了应用程序的 hat 子 profile。有关 AppArmor 的 ChangeHat 功能的更多详细信息,请参阅 第 34 章,使用 ChangeHat profile 您的 Web 应用程序

当为程序创建 profile 时,该程序只能访问 profile 中指定的文件、模式和 POSIX capability。这些限制是 Linux 访问控制之上的补充。

示例: 要获得 capability CAP_CHOWN,该程序必须同时在常规 Linux 访问控制下具有对 CAP_CHOWN 的访问权限(通常,是 root 拥有的进程),并且在 profile 中具有 capability chown。同样,要能够写入文件 /foo/bar,该程序必须同时在文件属性中设置正确的用户 ID 和模式位,并且在 profile 中具有 /foo/bar w

如果安装了 audit 包,则违反 AppArmor 规则的尝试会记录在 /var/log/audit/audit.log 中,或者记录在 /var/log/messages 中,或者仅记录在 journalctl 中(如果没有安装传统的 syslog)。通常,AppArmor 规则会阻止攻击起作用,因为必要的文件不可访问,并且在所有情况下,AppArmor 限制会将攻击者造成的损害限制为 AppArmor 允许的文件集。

30.2 Profile 类型 编辑源文件

AppArmor 知道四种不同类型的 profile:标准 profile、未附加 profile、本地 profile 和 hats。标准 profile 和未附加 profile 是独立的 profile,每个 profile 都存储在 /etc/apparmor.d/ 下的文件中。本地 profile 和 hats 是嵌入在父 profile 中的子 profile,用于为应用程序的子任务提供更严格或替代的限制。

30.2.1 标准 profile 编辑源文件

默认 AppArmor profile 通过其名称附加到程序,因此 profile 名称必须与要限制的应用程序的路径匹配。

/usr/bin/foo {
...
}

每当执行未受限制的进程 /usr/bin/foo 时,都会自动使用此 profile。

30.2.2 未附加 profile 编辑源文件

未附加 profile 不驻留在文件系统命名空间中,因此不会自动附加到应用程序。未附加 profile 的名称以前缀 profile 开头。您可以自由选择 profile 名称,但有一些限制:名称不能以 . 开头。如果它包含空格,则必须用引号括起来。如果名称以 / 开头,则该 profile 被视为标准 profile,因此以下两个 profile 相同

profile /usr/bin/foo {
...
}
/usr/bin/foo {
...
}

未附加 profile 绝不会自动使用,也不能通过 Px 规则进行转换。需要通过使用命名 profile 转换(请参阅 第 30.12.7 节,“命名 profile 转换”)或使用 change_profile 规则(请参阅 第 30.2.5 节,“更改规则”)将其附加到程序。

未附加 profile 对于通常不应由系统范围 profile 限制的系统实用程序(例如 /bin/bash)的专用 profile 非常有用。它们也可以用于设置角色或限制用户。

30.2.3 本地 profile 编辑源文件

本地 profile 提供了一种方便的方法,可以为受限制的应用程序启动的实用程序提供专门的限制。它们像标准 profile 一样指定,但嵌入在父 profile 中,并以 profile 关键字开头

/parent/profile {
   ...
   profile /local/profile {
      ...
   }
}

要转换为本地 profile,请使用 cx 规则(请参阅 第 30.12.2 节,“离散本地 profile 执行模式 (cx)”)或命名 profile 转换(请参阅 第 30.12.7 节,“命名 profile 转换”)。

30.2.4 Hats 编辑源文件

AppArmor “hats” 是具有某些附加限制的本地 profile,并且隐式规则允许使用 change_hat 进行转换。有关详细描述,请参阅 第 34 章,使用 ChangeHat profile 您的 Web 应用程序

30.2.5 更改规则 编辑源文件

AppArmor 提供了 change_hatchange_profile 规则,用于控制域转换。change_hat 通过在 profile 中定义 hats 来指定,而 change_profile 规则引用另一个 profile,并以关键字 change_profile 开头

change_profile -> /usr/bin/foobar,

change_hatchange_profile 都提供了一种应用程序引导的 profile 转换,而无需启动单独的应用程序。change_profile 提供了一种单向转换,可以在任何已加载的 profile 之间进行转换。change_hat 提供了一种可返回的父子转换,应用程序可以从父 profile 切换到 hat profile,并在稍后时间提供正确的密钥后返回到父 profile。

change_profile 最适合在应用程序经过受信任的设置阶段后,可以降低其权限级别的情况。在启动阶段映射或打开的任何资源仍然可用,但新的 profile 限制了新资源的打开,并限制了启动前打开的某些资源。具体来说,内存资源仍然可用,而 capability 和文件资源(如果它们未内存映射)可以受到限制。

change_hat 最适合在应用程序运行虚拟机或解释器,而解释器不直接访问应用程序资源的情况(例如 Apache 的 mod_php)。由于 change_hat 将返回密钥存储在应用程序的内存中,因此权限降低阶段不应直接访问内存。同样重要的是,文件访问应该正确分离,因为 hat 可以限制对文件句柄的访问,但不会关闭它。如果应用程序进行缓冲并提供对使用缓冲打开的文件的访问,则内核可能看不到对这些文件的访问,因此新 profile 无法限制这些访问。

Warning
警告:域转换的安全性

与通过 exec 进行的域转换相比,change_hatchange_profile 域转换的安全性较低,因为它们不会影响进程的内存映射,也不会关闭已打开的资源。

30.3 包含语句 编辑源代码

包含语句是指令,用于提取其他 AppArmor 配置文件的组件,以简化配置文件。包含文件检索程序的访问权限。通过使用包含,您可以授予程序访问其他程序也需要的目录路径或文件。使用包含可以减小配置文件的尺寸。

包含语句通常以井号 (#) 开头。这令人困惑,因为相同的井号也用于配置文件中的注释。因此,#include 仅在没有前导井号 (#) 的情况下才被视为包含 (##include 是注释),并且在 #include 之间没有空格 (# include 是注释)。

您也可以在前面没有井号 (#) 的情况下使用 include

include "/etc/apparmor.d/abstractions/foo"

与使用

#include "/etc/apparmor.d/abstractions/foo"
Note
注意:没有尾随的逗号“,”

由于包含遵循 C 预处理器的语法,因此它们没有像大多数 AppArmor 规则那样的尾随逗号“,”。

通过对语法进行微小的更改,您可以修改 include 的行为。如果您在包含路径周围使用 "",则指示解析器执行绝对或相对路径查找。

include "/etc/apparmor.d/abstractions/foo"   # absolute path
include "abstractions/foo"   # relative path to the directory of current file

在使用相对路径包含时,当文件被包含时,它被视为其包含的当前文件。例如,假设您位于 /etc/apparmor.d/bar 文件中,那么

include "abstractions/foo"

包含文件 /etc/apparmor.d/abstractions/foo。如果随后在

include "example"

/etc/apparmor.d/abstractions/foo 文件中,它包含 /etc/apparmor.d/abstractions/example

使用 <> 指定尝试包含路径(由 -I 指定,默认为 /etc/apparmor.d 目录),按顺序进行。因此,假设包含路径是

-I /etc/apparmor.d/ -I /usr/share/apparmor/

那么包含语句

include <abstractions/foo>

尝试 /etc/apparmor.d/abstractions/foo,如果该文件不存在,则下一个尝试是 /usr/share/apparmor/abstractions/foo

Tip
提示

可以通过将 -I 传递给 apparmor_parser,或在 /etc/apparmor/parser.conf 中设置包含路径来覆盖默认包含路径

Include /usr/share/apparmor/
Include /etc/apparmor.d/

允许多个条目,并且它们以与使用 -I--Includeapparmor_parser 命令行相同的顺序获取。

如果包含以“/”结尾,则认为它是目录包含,并且目录中的所有文件都将被包含。

为了帮助您分析应用程序,AppArmor 提供了三类包含:抽象、程序块和可调参数。

30.3.1 抽象 编辑源代码

抽象是按常见应用程序任务分组的包含。这些任务包括访问身份验证机制、访问名称服务例程、常见的图形要求和系统记账。这些抽象中列出的文件特定于命名的任务。需要其中一个文件的程序还需要抽象文件中列出的其他文件(具体取决于本地配置和程序的特定要求)。在 /etc/apparmor.d/abstractions 中找到抽象。

30.3.2 程序块 编辑源代码

program-chunks 目录 (/etc/apparmor.d/program-chunks) 包含特定于程序套件的某些配置文件块,通常在套件外部没有用处,因此从不建议在配置文件向导 (aa-logprofaa-genprof) 中将它们用于配置文件。目前,程序块仅适用于 postfix 程序套件。

30.3.3 可调参数 编辑源代码

tunables 目录 (/etc/apparmor.d/tunables) 包含全局变量定义。在配置文件中使用时,这些变量会扩展为一个可以更改的值,而无需更改整个配置文件。将应提供给每个配置文件的所有可调参数定义添加到 /etc/apparmor.d/tunables/global

30.4 能力条目 (POSIX.1e) 编辑源代码

能力规则只是单词 capability,后跟 capabilities(7) man 页中定义的 POSIX.1e 能力的名称。您可以在单个规则中列出多个能力,或使用 bare 关键字 capability 授予所有已实现的能力。

capability dac_override sys_admin,   # multiple capabilities
capability,                          # grant all capabilities

30.5 网络访问控制 编辑源代码

AppArmor 允许基于地址类型和族进行网络访问调解。以下说明了网络访问规则的语法

network [[<domain>1][<type2>][<protocol3>]]

1

支持的域:inet, ax25, ipx, appletalk, netrom, bridge, x25, inet6, rose, netbeui, security, key, packet, ash, econet, atmsvc, sna, pppox, wanpipe, bluetooth, unix, atmpvc,netlink, llc, can, tipc, iucv, rxrpc, isdn, phonet, ieee802154, caif, alg, nfc, vsock

2

支持的类型:stream, dgram, seqpacket, rdm, raw, packet

3

支持的协议:tcp, udp, icmp

AppArmor 工具仅支持族和类型规范。 AppArmor 模块仅在 “访问被拒绝” 消息中发出 network DOMAIN TYPE。并且只有这些由配置文件生成工具(YaST 和命令行)输出。

以下示例说明了可以在 AppArmor 配置文件中使用的可能的网络相关规则。最后两个的语法当前不受 AppArmor 工具的支持。

network1,
network inet2,
network inet63,
network inet stream4,
network inet tcp5,
network tcp6,

1

允许所有网络。不应用有关域、类型或协议的限制。

2

允许常规使用 IPv4 网络。

3

允许常规使用 IPv6 网络。

4

允许使用 IPv4 TCP 网络。

5

允许使用 IPv4 TCP 网络,释义上述规则。

6

允许使用 IPv4 和 IPv6 TCP 网络。

30.6 配置文件名称、标志、路径和通配符 编辑源代码

通过指定程序可执行文件的完整路径,将配置文件附加到程序。例如,标准配置文件(参见 第 30.2.1 节,“标准配置文件”),配置文件由

/usr/bin/foo { ... }

以下部分描述了在命名配置文件或将其置于其他现有配置文件的上下文中,或指定文件路径时可以应用的几种有用的技术。

AppArmor 明确区分目录路径名称和路径名称。对于需要明确区分的任何目录路径,请使用尾随斜杠 /

/some/random/example/* r

允许读取 /some/random/example 目录中的文件。

/some/random/example/ r

仅允许读取目录。

/some/**/ r

授予从 /some 下的任何目录读取访问权限(但不包括 /some/ 本身)。

/some/random/example/** r

授予对 /some/random/example 下的文件和目录的读取访问权限(但不包括 /some/random/example/ 本身)。

/some/random/example/**[^/] r

授予对 /some/random/example 下的文件读取访问权限。明确排除目录 ([^/])。

通配符(或正则表达式匹配)是指使用通配符修改目录路径以包含一组文件或子目录。文件资源可以使用类似于流行的 shell(例如 csh、Bash 和 zsh)使用的通配符语法指定。

*

替换任何字符的任意数量,但不包括 /

示例:任意数量的路径元素。

**

替换任何字符的任意数量,包括 /

示例:任意数量的路径元素,包括整个目录。

?

替换任何单个字符,但不包括 /

[abc]

替换单个字符 abc

示例:允许访问 /home[01]/*/.plan 文件的规则允许程序访问 /home0/home1 中的用户的 .plan 文件。

[a-c]

替换单个字符 abc

{ab,cd}

扩展为匹配 abcd 的一个规则。

示例:允许访问 /{usr,www}/pages/** 的规则授予对 /usr/pages/www/pages 中的网页的访问权限。

[^a]

替换任何字符,但不包括 a

30.6.1 配置文件标志 编辑源代码

配置文件标志控制相关配置文件的行为。您可以通过手动编辑配置文件来添加配置文件标志,请参见以下语法

/path/to/profiled/binary flags=(list_of_flags) {
  [...]
}

您可以使用逗号“,”或空格“ ”分隔多个标志。有三种基本的配置文件标志:模式、相对和附加标志。

模式 标志是 complain(允许非法访问并记录)。如果省略,配置文件将处于 enforce 模式(强制执行策略)。

Tip
提示

将整个配置文件置于 complain 模式的更灵活方法是在 /etc/apparmor.d/force-complain/ 目录中创建指向配置文件文件的符号链接。

ln -s /etc/apparmor.d/bin.ping /etc/apparmor.d/force-complain/bin.ping

相对 标志是 chroot_relative(表示配置文件相对于 chroot 而不是命名空间)或 namespace_relative(默认,路径相对于 chroot 外部)。它们是互斥的。

附加 标志由两对互斥标志组成:attach_disconnectedno_attach_disconnected(确定解析为命名空间外部的路径名是否附加到根,这意味着它们在开头具有“/”字符),以及 chroot_attachchroot_no_attach(控制在 chroot 环境中访问 chroot 外部但在命名空间内的文件时路径名生成)。

30.6.2 在配置文件中使用变量 编辑源代码

AppArmor 允许在配置文件中使用保存路径的变量。使用全局变量使您的配置文件可移植,并使用局部变量为路径创建快捷方式。

全局变量何时派上用场的一个典型示例是网络场景,其中用户主目录安装在不同的位置。与其在所有受影响的配置文件中重写主目录的路径,您只需更改变量的值。全局变量在 /etc/apparmor.d/tunables 下定义,需要通过包含语句提供。在此用例中找到变量定义 (@{HOME}@{HOMEDIRS}) 在 /etc/apparmor.d/tunables/home 文件中。

局部变量在配置文件的头部定义。这对于提供 chrooted 路径的基础很有用,例如

@{CHROOT_BASE}=/tmp/foo
/sbin/rsyslogd {
...
# chrooted applications
@{CHROOT_BASE}/var/lib/*/dev/log w,
@{CHROOT_BASE}/var/log/** w,
...
}

在以下示例中,虽然 @{HOMEDIRS} 列出了所有用户主目录的存储位置,但 @{HOME} 是一个空格分隔的主目录列表。 稍后,@{HOMEDIRS} 将通过两个新的特定位置扩展,这些位置存储着用户主目录。

@{HOMEDIRS}=/home/
@{HOME}=@{HOMEDIRS}/*/ /root/
[...]
@{HOMEDIRS}+=/srv/nfs/home/ /mnt/home/
Note
注意

使用当前的 AppArmor 工具,变量只能在手动编辑和维护配置文件时使用。

30.6.3 模式匹配 编辑源代码

配置文件名称可以包含通配符表达式,允许配置文件与多个二进制文件匹配。

以下示例对于 foo 二进制文件位于 /usr/bin/bin 的系统有效。

/{usr/,}bin/foo { ... }

在以下示例中,当与可执行文件 /bin/foo 匹配时,/bin/foo 配置文件是精确匹配,因此会被选中。 对于可执行文件 /bin/fat,配置文件 /bin/foo 不匹配,并且由于 /bin/f* 配置文件比 /bin/** 更具体(更不通用),因此选择了 /bin/f* 配置文件。

/bin/foo { ... }

/bin/f*  { ... }

/bin/**  { ... }

有关配置文件名称通配符示例的更多信息,请参阅 AppArmor 的 man 页面,man 5 apparmor.d,,章节 Globbing

30.6.4 命名空间 编辑源代码

命名空间用于提供不同的配置文件集。 例如,一个用于系统,另一个用于 chroot 环境或容器。 命名空间是分层的——命名空间可以看到其子项,但子项无法看到其父项。 命名空间名称以冒号 : 开头,后跟一个字母数字字符串,一个尾随冒号 : 和一个可选的双斜杠 //,例如

:childNameSpace://

加载到子命名空间的配置文件在其命名空间名称前缀(从父级的角度查看)

:childNameSpace://apache

可以通过 change_profile API 或命名配置文件转换进入命名空间

/path/to/executable px -> :childNameSpace://apache

30.6.5 配置文件命名和附加规范 编辑源代码

配置文件可以有一个名称和一个附加规范。 这允许使用逻辑名称的配置文件,该名称对用户/管理员来说比包含模式匹配的配置文件名称更有意义(请参阅 第 30.6.3 节,“模式匹配”)。 例如,默认配置文件

/** { ... }

可以命名为

profile default /** { ... }

此外,可以使用模式匹配命名的配置文件。 例如

/usr/lib64/firefox*/firefox-*bin { ... }

可以命名为

profile firefox /usr/lib64/firefox*/firefox-*bin { ... }

30.6.6 别名规则 编辑源代码

别名规则提供了一种替代方法来操作配置文件路径映射,以适应特定站点的布局。 它们是使用变量的路径重写的另一种形式,并且在变量解析之后完成。 别名规则表示将具有相同源前缀的规则视为位于目标前缀的规则。

alias /home/ -> /usr/home/

所有具有与 /home/ 匹配的前缀的规则都提供对 /usr/home/ 的访问。 例如

/home/username/** r,

也允许访问

/usr/home/username/** r,

别名提供了一种无需重写规则即可重新映射规则的快速方法。 它们使源路径仍然可访问——在我们的示例中,别名规则使 /home/ 下的路径仍然可访问。

使用 alias 规则,您可以同时指向多个目标。

alias /home/ -> /usr/home/
alias /home/ -> /mnt/home/
Note
注意

使用当前的 AppArmor 工具,别名规则只能在手动编辑和维护配置文件时使用。

Tip
提示

将全局别名定义插入到文件 /etc/apparmor.d/tunables/alias 中。

30.7 文件权限访问模式 编辑源代码

文件权限访问模式由以下模式的组合组成

r

读取模式

w

写入模式(与 a 互斥)

a

追加模式(与 w 互斥)

k

文件锁定模式

l

链接模式

link FILE -> TARGET

链接对规则(不能与其他访问模式组合)

30.7.1 读取模式 (r) 编辑源代码

允许程序对资源具有读取访问权限。 读取访问权限对于 shell 脚本和其他解释内容是必需的,并确定执行进程是否可以 core dump。

30.7.2 写入模式 (w) 编辑源代码

允许程序对资源具有写入访问权限。 如果要取消链接(删除)文件,则文件必须具有此权限。

30.7.3 追加模式 (a) 编辑源代码

允许程序写入文件的末尾。 与 w 模式相反,追加模式不包括覆盖数据、重命名或删除文件的能力。 追加权限通常与需要能够写入日志文件但不得操纵日志文件中任何现有数据的应用程序一起使用。 由于追加权限是与写入模式相关的权限的子集,因此不能同时使用 wa 权限标志,并且它们是互斥的。

30.7.4 文件锁定模式 (k) 编辑源代码

应用程序可以获取文件锁。 AppArmor 的早期版本允许锁定文件,如果应用程序可以访问它们。 通过使用单独的文件锁定模式,AppArmor 确保锁定仅限于需要文件锁定的文件,并加强安全性,因为锁定可用于多种拒绝服务攻击场景。

30.7.7 可选的 allowfile 规则 编辑源代码

如果未指定 allow 前缀是可选的,并且在未使用 deny 关键字(请参阅 第 30.7.9 节,“拒绝规则”)时,则表示它。

allow file /example r,
allow /example r,
allow network,

您还可以使用可选的 file 关键字。 如果您省略它并且没有其他以关键字开头的规则类型,例如 networkmount,则会自动推断它。

file /example/rule r,

等效于

/example/rule r,

以下规则授予对所有文件的访问权限

file,

等于

/** rwmlk,

文件规则可以使用前导或尾随权限。 权限不应指定为尾随权限,而应在规则的开头使用。 这很重要,因为它使文件规则的行为与其他规则类型一样。

/path rw,            # old style
rw /path,            # leading permission
file rw /path,       # with explicit 'file' keyword
allow file rw /path, # optional 'allow' keyword added

30.7.8 所有者条件规则 编辑源代码

文件规则可以扩展,以便它们可以根据用户是文件的所有者(fsuid 需要与文件的 uid 匹配)来有条件地扩展。 为此,将 owner 关键字放在规则前面。 所有者条件规则像常规文件规则一样累积。

owner /home/*/** rw

当使用带有链接规则的文件所有权条件时,所有权测试是对目标文件进行的,因此用户必须拥有该文件才能链接到它。

Note
注意:常规文件规则的优先级

所有者条件规则被视为常规文件规则的子集。 如果常规文件规则与所有者条件文件规则重叠,则这些规则将被合并。 考虑以下示例。

/foo r,
owner /foo rw,  # or w,

规则合并——结果是每个人都有 r,只有所有者才有 w

Tip
提示

要解决除了文件所有者以外的每个人,请使用关键字 other

owner /foo rw,
other /foo r,

30.7.9 拒绝规则 编辑源代码

拒绝规则可用于注释或抑制已知的拒绝。 配置文件生成工具不会询问使用拒绝规则处理的已知拒绝。 这种拒绝不会出现在被拒绝时的审核日志中,从而使日志文件保持精简。 如果这不是期望的,请在拒绝条目前面放置关键字 audit

也可以将拒绝规则与允许规则结合使用。 这允许您指定一个广泛的允许规则,然后减去一些已知不应允许的几个文件。 拒绝规则也可以与所有者规则结合使用,以拒绝由用户拥有的文件。 以下示例允许对用户目录中的所有内容进行读/写访问,但禁止对 .ssh/ 文件的写入访问

deny /home/*/.ssh/** w,
owner /home/*/** rw,

拒绝规则的广泛使用通常不鼓励,因为它使理解配置文件内容更加困难。 但是,明智地使用拒绝规则可以简化配置文件。 因此,工具仅生成拒绝特定文件的配置文件,并且不使用拒绝规则中的通配符。 手动编辑您的配置文件以添加使用通配符的拒绝规则。 使用工具更新此类配置文件是安全的,因为拒绝条目不受影响。

30.8 挂载规则 编辑源代码

AppArmor 可以限制挂载和卸载操作,包括文件系统类型和挂载标志。 规则语法基于 mount 命令语法,并以 mountremountumount 关键字之一开头。 条件是可选的,未指定的条件假定与所有条目匹配。 例如,不指定文件系统意味着匹配所有文件系统。

可以使用 options=options in 指定条件。

options= 指定必须完全满足的条件。 规则

mount options=ro /dev/foo -E /mnt/,

匹配

# mount -o ro /dev/foo /mnt

但不匹配

# mount -o ro,atime /dev/foo /mnt
# mount -o rw /dev/foo /mnt

options in 要求使用所列出的挂载选项中的至少一个。 规则

mount options in (ro,atime) /dev/foo -> /mnt/,

匹配

# mount -o ro /dev/foo /mnt
# mount -o ro,atime /dev/foo /mnt
# mount -o atime /dev/foo /mnt

但不匹配

# mount -o ro,sync /dev/foo /mnt
# mount -o ro,atime,sync /dev/foo /mnt
# mount -o rw /dev/foo /mnt
# mount -o rw,noatime /dev/foo /mnt
# mount /dev/foo /mnt

使用多个条件时,规则授予每组选项的权限。 规则

mount options=ro options=atime

匹配

# mount -o ro /dev/foo /mnt
# mount -o atime /dev/foo /mnt

但不匹配

# mount -o ro,atime /dev/foo /mnt

单独的挂载规则是不同的,选项不会累积。 规则

mount options=ro,
mount options=atime,

不等于

mount options=(ro,atime),
mount options in (ro,atime),

以下规则允许以只读方式挂载 /dev/foo/mnt/ 并使用 inode 访问时间,或者允许以某种组合的 'nodev' 和 'user' 挂载 /dev/foo/mnt/

mount options=(ro, atime) options in (nodev, user) /dev/foo -> /mnt/,

允许

# mount -o ro,atime /dev/foo /mnt
# mount -o nodev /dev/foo /mnt
# mount -o user /dev/foo /mnt
# mount -o nodev,user /dev/foo /mnt

30.9 Pivot root 规则 编辑源代码

AppArmor 可以限制更改根文件系统。 语法是

pivot_root [oldroot=OLD_ROOT] NEW_ROOT

在“pivot_root”规则中指定的路径必须以“/”结尾,因为它们是目录。

# Allow any pivot
pivot_root,

# Allow pivoting to any new root directory and putting the old root
# directory at /mnt/root/old/
pivot_root oldroot=/mnt/root/old/,

# Allow pivoting the root directory to /mnt/root/
pivot_root /mnt/root/,

# Allow pivoting to /mnt/root/ and putting the old root directory at
# /mnt/root/old/
pivot_root oldroot=/mnt/root/old/ /mnt/root/,

# Allow pivoting to /mnt/root/, putting the old root directory at
# /mnt/root/old/ and transition to the /mnt/root/sbin/init profile
pivot_root oldroot=/mnt/root/old/ /mnt/root/ -> /mnt/root/sbin/init,

30.10 PTrace 规则 编辑源代码

AppArmor 支持限制 ptrace 系统调用。 ptrace 规则会累积,因此授予的 ptrace 权限是所列 ptrace 规则权限的并集。 如果规则未指定访问列表,则隐式授予权限。

权限 tracetracedby 控制 ptrace(2);readreadby 控制 proc(5) 文件系统访问、kcmp(2)、futexes (get_robust_list(2)) 和 perf trace 事件。

为了允许 ptrace 操作,跟踪和被跟踪的进程需要正确的权限。 这意味着跟踪进程需要 trace 权限,而被跟踪的进程需要 tracedby 权限。

示例 AppArmor PTrace 规则

# Allow all PTrace access
ptrace,

# Explicitly allow all PTrace access,
ptrace (read, readby, trace, tracedby),

# Explicitly deny use of ptrace(2)
deny ptrace (trace),

# Allow unconfined processes (eg, a debugger) to ptrace us
ptrace (readby, tracedby) peer=unconfined,

# Allow ptrace of a process running under the /usr/bin/foo profile
ptrace (trace) peer=/usr/bin/foo,

30.11 信号规则 编辑源代码

AppArmor 支持限制进程间信号。AppArmor 信号规则会累积,因此授予的信号权限是所有列出的信号规则权限的并集。当规则未明确声明访问列表时,AppArmor 信号权限是隐含的。

发送和接收进程都必须具有正确的权限。

示例信号规则

# Allow all signal access
signal,

# Explicitly deny sending the HUP and INT signals
deny signal (send) set=(hup, int),

# Allow unconfined processes to send us signals
signal (receive) peer=unconfined,

# Allow sending of signals to a process running under the /usr/bin/foo
# profile
signal (send) peer=/usr/bin/foo,

# Allow checking for PID existence
signal (receive, send) set=("exists"),

# Allow us to signal ourselves using the built-in @{profile_name} variable
signal peer=@{profile_name},

# Allow two real-time signals
signal set=(rtmin+0 rtmin+32),

30.12 执行模式 编辑源代码

执行模式,也称为配置文件转换,包括以下模式

Px

离散配置文件执行模式

Cx

离散本地配置文件执行模式

Ux

未限制执行模式

ix

继承执行模式

m

允许使用 PROT_EXEC 进行 mmap(2) 调用

30.12.1 离散配置文件执行模式 (px) 编辑源代码

此模式要求为在 AppArmor 域转换处执行的资源定义一个离散的安全配置文件。如果没有定义配置文件,则拒绝访问。

Uxuxpxix 不兼容。

30.12.2 离散本地配置文件执行模式 (cx) 编辑源代码

Px 类似,但不是搜索全局配置文件集,Cx 仅搜索当前配置文件的本地配置文件。此配置文件转换提供了一种方法,使应用程序可以为辅助应用程序提供替代配置文件。

Note
注意:离散本地配置文件执行模式 (cx) 的限制

当前,Cx 转换仅限于顶级配置文件,不能在帽子和子配置文件中使用。此限制将在未来删除。

UxuxPxpxcxix 不兼容。

30.12.3 未限制执行模式 (ux) 编辑源代码

允许程序在不应用任何 AppArmor 配置文件的情况下执行该资源。当受限制的程序需要执行特权操作(例如重新启动机器)时,此模式很有用。通过将特权部分放在另一个可执行文件中,并授予未限制的执行权限,可以绕过对所有受限制的进程施加的强制约束。允许 root 进程变为未限制意味着它可以更改 AppArmor 策略本身。有关约束内容,请参阅 apparmor(7) 手册页。

此模式与 uxpxPxix 不兼容。

30.12.4 不安全执行模式 编辑源代码

仅在特殊情况下使用执行模式的小写版本——pxcxux。它们不会清除环境变量(例如 LD_PRELOAD)。因此,调用域可能对被调用资源产生过大的影响。仅当子进程绝对 必须 以未限制的模式运行并且必须使用 LD_PRELOAD 时,才使用这些模式。使用这些模式的任何配置文件都提供的安全性微乎其微。请自行承担风险。

30.12.5 继承执行模式 (ix) 编辑源代码

ix 阻止在配置程序执行命名程序时正常的 AppArmor 域转换。相反,执行的资源继承当前配置文件。

当受限制的程序需要调用另一个受限制的程序而无需获得目标配置文件的权限或失去当前配置文件的权限时,此模式很有用。由于 ix 执行不会更改权限,因此没有用于清除环境的版本。

cxuxpx 不兼容。隐含 m

30.12.6 允许可执行映射 (m) 编辑源代码

此模式允许使用 mmap(2)PROT_EXEC 标志将文件映射到内存中。此标志将页面标记为可执行。在某些体系结构上,它用于提供不可执行的数据页面,这会使利用尝试复杂化。AppArmor 使用此模式来限制行为良好的程序(或在强制执行不可执行内存访问控制的体系结构上的所有程序)可以将哪些文件用作库,以限制给定给 ld(1)LD_PRELOADLD_LIBRARY_PATH 给定给 ld.so(8) 的无效 -L 标志。

30.12.7 命名配置文件转换 编辑源代码

默认情况下,pxcx(以及它们的干净执行变体)将转换为名称与可执行文件名称匹配的配置文件。使用命名配置文件转换,您可以指定要转换到的配置文件。如果多个二进制文件需要共享单个配置文件,或者它们需要使用与名称指定的配置文件不同的配置文件,这很有用。命名配置文件转换可与 cxCxpxPx 一起使用。当前每个配置文件最多允许十二个命名配置文件转换。

命名配置文件转换使用 -> 来指示需要转换到的配置文件的名称

/usr/bin/foo
{
  /bin/** px -> shared_profile,
  ...
  /usr/*bash cx -> local_profile,
  ...
  profile local_profile
  {
    ...
  }
}
Note
注意:正常转换和命名转换之间的区别

在使用通配符时,正常转换提供“一对多”关系——/bin/** px 转换为 /bin/ping/bin/cat 等,具体取决于正在运行的程序。

命名转换提供“多对一”关系——无论名称如何,匹配规则的所有程序都转换为指定的配置文件。

命名配置文件转换在日志中显示为具有模式 Nx。要更改到的配置文件的名称列在 name2 字段中。

30.12.8 配置文件转换的备用模式 编辑源代码

pxcx 转换指定硬依赖关系——如果指定的配置文件不存在,则执行失败。通过继承备用,执行成功但继承当前配置文件。要指定继承备用,ixcxCxpxPx 组合成模式 cixCixpixPix

/path Cix -> profile_name,

或者

Cix /path -> profile_name,

其中 -> profile_name 是可选的。

如果您添加未限制的 ux 模式,则结果模式为 cuxCUxpuxPUx。这些模式允许在找不到指定的配置文件时回退到“未限制”。

/path PUx -> profile_name,

或者

PUx /path -> profile_name,

其中 -> profile_name 是可选的。

备用模式也可以与命名配置文件转换一起使用。

30.12.9 执行模式中的变量设置 编辑源代码

在选择 Px、Cx 或 Ux 执行模式之一时,请注意以下环境变量在子进程继承它之前会被从环境中删除。因此,依赖于这些变量的应用程序或进程如果在应用于它们的配置文件中带有 Px、Cx 或 Ux 标志,将不再起作用

  • GCONV_PATH

  • GETCONF_DIR

  • HOSTALIASES

  • LD_AUDIT

  • LD_DEBUG

  • LD_DEBUG_OUTPUT

  • LD_DYNAMIC_WEAK

  • LD_LIBRARY_PATH

  • LD_ORIGIN_PATH

  • LD_PRELOAD

  • LD_PROFILE

  • LD_SHOW_AUXV

  • LD_USE_LOAD_BIAS

  • LOCALDOMAIN

  • LOCPATH

  • MALLOC_TRACE

  • NLSPATH

  • RESOLV_HOST_CONF

  • RES_OPTIONS

  • TMPDIR

  • TZDIR

30.12.10 “safe”和“unsafe”关键字 编辑源代码

您可以对规则使用“safe”和“unsafe”关键字,而不是使用执行模式的大小写修饰符。例如

/example_rule Px,

与以下任何一个相同

safe /example_rule px,
safe /example_rule Px,
safe px /example_rule,
safe Px /example_rule,

规则

/example_rule px,

与以下任何一个相同

unsafe /example_rule px,
unsafe /example_rule Px,
unsafe px /example_rule,
unsafe Px /example_rule,

“safe”/“unsafe”关键字是互斥的,可以在文件规则的“owner”关键字之后使用,因此规则关键字的顺序是

[audit] [deny] [owner] [safe|unsafe] file_rule

30.13 资源限制控制 编辑源代码

AppArmor 可以设置和控制应用程序的资源限制(rlimits,也称为 ulimits)。默认情况下,AppArmor 不控制应用程序的 rlimits,并且它控制限制配置文件中指定的那些限制。有关资源限制的更多信息,请参阅 setrlimit(2)ulimit(1)ulimit(3) 手册页。

AppArmor 利用系统的 rlimits,因此不提供通常会发生的额外审计。它也不能提高系统设置的 rlimits,AppArmor rlimits 只能降低应用程序的当前资源限制。

这些值由进程的子进程继承,即使转换到新的配置文件或应用程序变为未限制,仍然保留。因此,当应用程序转换为新的配置文件时,该配置文件可以进一步降低应用程序的 rlimits。

AppArmor 的 rlimit 规则提供应用程序尝试提高它们时设置应用程序硬限制的调解。应用程序无法将硬限制提高到配置文件中指定的水平以上。提高硬限制的调解不会被继承,因为设置的值会被继承,因此当应用程序转换为新的配置文件时,它可以根据配置文件中指定的水平提高其限制。

AppArmor 的 rlimit 控制不会影响应用程序的软限制,除非确保它们小于或等于应用程序的硬限制。

AppArmor 的硬限制规则具有以下通用形式

set rlimit RESOURCE <= value,

其中 RESOURCEVALUE 应该替换为以下值

cpu

以秒为单位的 CPU 时间限制。

fsize, data, stack, core, rss, as, memlock, msgqueue

字节数,或者带有后缀的数字,后缀可以是 K/KB(千字节)、M/MB(兆字节)、G/GB(吉字节),例如

rlimit data <= 100M,
fsize, nofile, locks, sigpending, nproc, rtprio

大于或等于 0 的数字

nice

介于 -20 和 19 之间的值

Note
注意

nproc rlimit 的处理方式与其他所有 rlimit 不同。它不是指示标准的进程 rlimit,而是控制在任何时候可以运行在配置下的最大进程数。当超过限制时,在减少当前运行的进程数之前,在配置下创建新进程将失败。

Note
注意

目前,工具无法用于向配置中添加 rlimit 规则。将 rlimit 控制添加到配置的唯一方法是使用文本编辑器手动编辑配置。工具仍然可以与包含 rlimit 规则的配置一起工作,并且不会删除它们,因此可以安全地使用工具来更新包含它们的配置。

30.14 审计规则 编辑源文件

AppArmor 提供了审计给定规则的能力,以便在匹配规则时,审计消息会出现在审计日志中。要为给定规则启用审计消息,需要在规则前面放置 audit 关键字

audit /etc/foo/*        rw,

如果希望仅审计给定的权限,可以将规则拆分为两个规则。以下示例导致在打开文件进行写入时生成审计消息,但在打开文件进行读取时不会生成审计消息

audit /etc/foo/*  w,
/etc/foo/*        r,
Note
注意

对于文件的每次读取或写入,不会生成审计消息,而仅在打开文件进行读取或写入时生成。

可以将审计控制与 owner / other 条件文件规则结合使用,以便在用户访问他们拥有/不拥有的文件时提供审计

audit owner /home/*/.ssh/**       rw,
audit other /home/*/.ssh/**       r,
打印此页面