SDB:Ima evm

跳转到:导航搜索

简介

本文档描述了来自 Linux 完整性子系统的 IMAEVM 技术,以及如何在 SUSE Linux 发行版上利用它们。

基本上,IMA 和 EVM 提供以下功能

  • 测量(哈希)文件内容,并在访问时跟踪此信息并将其保存在审计日志中。
  • 评估文件,允许在测量(哈希)或数字签名与预期值不匹配时防止访问。

这两个功能将在以下部分中更详细地介绍。

通用概念

在本节中,从高级别的角度讨论了 IMA 和 EVM 的不同功能。这应该有助于理解后续章节中将介绍的实际用法。

扩展属性中的元数据

IMA 和 EVM 都将每个文件的哈希或签名数据存储在名为 security.imasecurity.evm 的扩展属性中。在这些属性中找到的数据是二进制数据结构,由 IMA 和 EVM 内部创建、处理和更新。

IMA 扩展属性存储有关实际文件内容的数据。EVM 扩展属性另一方面存储有关文件元数据的数据,例如所有权、模式位、其他扩展属性等。

IMA 测量

借助 IMA 测量,可以通过跟踪文件哈希值在访问时的变化来验证 Linux 系统的完整性。当系统首次安装在已知受信任状态下(在配置期间)时,会记录“良好”哈希值的列表。

在系统正常运行期间,IMA 会维护一个运行时文件哈希值列表,因为它们被访问。然后可以将此列表与最初记录的“良好”哈希值列表进行比较,以检测任何未经授权的更改。

当然,运行时哈希值列表本身可能受到恶意修改。因此,它可以与 TPM 芯片结合使用(有关 TPM,请参阅 SUSE 关于 TPM 的博客文章)。在这种情况下,每个新计算的文件哈希值都会扩展 TPM 的一个寄存器(这些寄存器称为 PCR)。存储在 PCR 中的值是 IMA 看到的所有文件的聚合哈希值。通过计算 hash(PCR.value || file.hash) 来维护它。有关更多信息,请参阅 TPM 版本 2.0 的 TPM2_PCR_Extend() 库函数。

在称为 TPM 远程证明 的过程中,TPM 芯片创建包含当前 PCR 值的加密签名消息。此消息与包含运行时测量哈希值的审计日志一起发送到远程方。远程方然后可以从审计日志重新计算聚合哈希值,并将其与在 TPM 的 PCR 寄存器中找到的聚合哈希值进行比较。

如果两个值匹配,则它确保审计日志未被篡改,因为重新计算产生与 TPM 中存储的值相同的值。PCR 寄存器无法重置,只能扩展。因此,即使恶意攻击者设法访问系统并修改文件,相应地操纵审计日志也会导致验证失败。

可以看出,IMA 的 测量 功能仅用于 检测 系统潜在的恶意更改,而不用于 防止 它们。本文档更多地关注 IMA 和 EVM 的评估部分。有关 测量 的更多实际细节,请参阅 参考文献官方文档

IMA 评估

借助 评估 功能,可以防止执行或甚至读取不受信任的文件。这是通过对文件内容进行哈希签名并使用公钥密码学检查签名来实现的。签名存储在每个文件的 security.ima 扩展属性中。

数字签名仅适用于预计在运行时不会更改的文件,因为否则需要使用私钥重新计算签名,出于安全原因,不应将私钥保存在系统上。因此,签名最适合二进制文件,不适合配置文件。

IMA 评估也可以在没有数字签名的情况下使用,而只是存储纯文件哈希值。这种变体本身不提供真正的安全性。但是,它可以与 EVM 结合使用,以防止离线文件篡改(如下一节所述)。

EVM 用于防止离线文件篡改

EVM(扩展验证模块)的设计目的是为了防止离线文件篡改。这里的目标是检测在系统关闭时(“邪恶女仆攻击”)文件在磁盘上是否被修改。

全盘加密可以阻止这种攻击,但会引入开销。此外,它可能不适用于所有情况(例如,因为输入解密密码是不可能的)。在这些情况下,IMA/EVM 可以作为替代方案。

EVM 通过对单个文件的许多元数据进行签名哈希或 HMAC 来解决此问题,例如以下内容

  • 与安全相关的扩展属性(IMA 哈希值、SELinux 或其他安全框架的数据)。
  • Linux 功能。
  • 文件所有者、组和模式。
  • 文件系统 UUID。
  • 文件 inode 号码。

如果元数据的验证失败,则拒绝访问相关文件。数字签名或 HMAC 存储在每个文件的 security.evm 扩展属性中。

EVM 不能单独工作,只能与安全框架(如 IMA 或 SELinux)结合使用。这意味着只有在例如执行 IMA 评估时才会进行 EVM 元数据检查。

EVM 数字签名

这种方法使用签名哈希,工作方式类似于 IMA 评估:计算收集到的元数据的哈希值。然后使用公钥密码学对哈希值进行签名。激活 EVM 后,只有可以验证哈希值和签名的文件才能被允许访问。

同样,这种技术仅适用于不经常更改的文件。由于所有这些元数据都是哈希值的一部分,即使文件被完全复制,也会因为新的 inode 号码或不同的文件系统 ID 而导致验证失败。

EVM HMAC

通过使用 HMAC,可以使用对称密钥对文件元数据进行身份验证。最好将对称密钥保存在 TPM 芯片上。这样,对称密钥只有在成功完成受信任启动后才能访问。密钥也永远不会离开 TPM 芯片。

与基于数字签名的 EVM 相比,功能上的区别在于,对称密钥将在正常操作期间可用,因此 IMA/EVM 子系统可以随着文件的更改重新计算 HMAC。因此,EVM HMAC 方法也适用于经常更改的文件,例如配置文件。

由于秘密对称密钥保存在 TPM 芯片上,这种方法可以防止离线文件篡改。秘密密钥在系统关闭时无法找到。但是,也可以使用基于软件的对称密钥进行测试。

IMA 和 EVM 之间的区别

IMA 和 EVM 紧密合作,有时很难将它们分开。一些主要区别

  • IMA 关心实际的文件内容,而 EVM 关心元数据
  • IMA 提供逻辑来检测运行时文件更改,并相应地更新计算的哈希值。EVM HMAC 方法也需要此逻辑。
  • IMA 行为可以通过自定义策略进行微调,而 EVM 只是启用或禁用,并且仅代表 IMA 评估执行。


可信计算基 (TCB)

IMA 和 EVM 的开发考虑了可信计算组织 (TCG) 的一些目标。其中一个目标是保护所谓的 TCB 免受未经授权的修改。

TCB 被定义为一组用于在系统上执行安全策略的程序和文件(另请参阅 此处,了解有关此主题的更深入讨论)。

通过安全启动或可信启动等概念,固件、引导加载程序和 Linux 内核的签名已经过检查。信任链通常在此处结束。然而,TCB 包含的范围比这些更广。例如,/etc 中的许多配置文件或负责处理用户登录或权限提升的程序对于系统的整体安全性同样重要。

IMA 和 EVM 允许将信任链扩展到用户空间,并在软件执行时检测不受信任的软件(测量),甚至阻止访问它(评估)。IMA 和 EVM 子系统附带一组预定义的策略,专门旨在保护系统的 TCB。

IMA 和 EVM 实践

在本节中,将讨论设置 IMA 和 EVM 不同功能的实际步骤。首先,提供可用实用程序和接口的参考。然后在示例部分,将逐步解释一些实际用例。

由于并非每个人都可以访问 TPM 芯片,而且芯片有 1.2 和 2.0 两个主要的不同版本,因此以下部分目前侧重于使用基于软件的密钥。

evmctl 实用程序

openSUSE 包 evmctl (ima-evm-utils 的子包) 中的 evmctl 实用程序用于显式创建用于 IMA 和 EVM 不同用例的扩展属性 security.imasecurity.evm。以下列表显示了 evmctl 可以执行的一些主要操作及其用途。

  1. evmctl ima_hash [...]使用哈希摘要进行 IMA 评估。计算选定文件的哈希摘要,并将其存储在单独的 security.ima 扩展属性中。还存储一个二进制头,用于标识属性数据的类型和使用的摘要算法。
  2. evmctl ima_sign [...]使用数字签名进行 IMA 评估。使用配置的私有 RSA 密钥创建选定文件的哈希摘要的签名,并将其存储在单独的 security.ima 扩展属性中。
  3. evmctl sign [...]EVM 数字签名。如果同时传递了 -s-d 开关之一,则首先创建并存储在 security.ima 中的 IMA 哈希或签名,如 1. 和 2. 中所述。然后计算涉及的元数据的 sha1 摘要,并使用配置的私有 RSA 密钥对其进行签名。然后将结果签名存储在 security.evm 中。
  4. evmctl hmac [...]EVM HMAC。操作方式与 3. 相同,但不是创建 RSA 私钥签名,而是使用对称密钥计算 HMAC,并将其存储在 security.evm 中。
  5. evmctl ima_verify [...]验证附加到文件中扩展属性 "security.ima" 的 IMA 数字签名。如果成功验证,则 stdout 不会反馈任何内容。
  6. evmctl verify [...]:就像 ima_verify 一样,而是验证附加到文件中扩展属性 "security.evm" 的 EVM 数字签名。如果成功验证,则 stdout 不会反馈任何内容。

摘要算法

可以使用 evmctl-a 选项选择用于计算哈希的摘要算法。当前默认算法是 sha1,应避免使用,因为它 不再安全。如果涉及 TPM 芯片版本 1.2,则实际上无法避免使用 sha1,因为这些芯片不支持更强的摘要。

EVM 相关功能目前似乎也仅限于 sha1。但 IMA 可以使用更强的摘要。sha256 应该是一个安全的选择。但是,在使用 IMA 签名方案版本 1 时,仍然存在一些限制。请参阅下一节了解更多信息。

RSA 密钥格式

IMA/EVM 当前支持两种不同的签名方案版本。较旧的版本(签名方案 v1)使用通过 openssl genrsa [...] 生成的 PEM 格式的公钥/私钥 RSA 密钥对。该方案仅可靠地支持 sha1 摘要。如果选择 sha256,签名将被创建,但内核将无法验证这些签名。

较新的签名格式版本 2 使用通过 openssl req [...] 生成的 X.509 证书。只有使用此方案才能使用更强的摘要算法,例如 sha256

evmctl 期望的默认签名方案已从旧版本更改。当前的 evmctl 期望基于 X.509 的密钥。要使用旧的签名方案,需要传递 --rsa 选项,这有点令人困惑,因为在两种情况下都涉及 RSA 密钥。

RSA 密钥长度

通常使用 2048 位 RSA 密钥,目前应该足够了。

如何启用 IMA

IMA 通过策略规则集进行控制,该规则集定义了哪些文件应该被测量和/或评估。有关策略语法的详细信息,请参阅 IMA 策略语法。IMA 附带一些内置策略,可以通过内核命令行参数 ima_policy 激活,请参阅 内核命令行选项

要加载自定义策略,需要将策略文本写入 securityfs 中的伪文件 ima/policy,通常挂载在 /sys/kernel/security

root # cat /root/ima.policy >/sys/kernel/security/ima

如果在策略文件中检测到错误,则写入将失败并显示 EINVAL,并且策略将不会被激活。一旦成功读取了策略文件,出于安全原因,策略文件节点将消失。

在较新的内核中,配置选项 IMA_WRITE_POLICY 更改了此行为,并允许将其他策略规则附加到策略文件节点。类似地,配置选项 IMA_READ_POLICY 允许从内核读取当前加载的策略。

如果策略涉及数字签名,则需要在激活策略之前将适当的公钥或对称密钥加载到内核密钥环中,因为否则 IMA 或 EVM 评估将无法进行,所有验证都将失败并且访问将被拒绝。

在较新的内核中,所需的公钥路径(以 X.509 DER 格式)也可以编译到内核中,以便立即可用。

对于自定义策略,需要在启动期间尽快在 initrd 中激活策略。请参阅 在早期启动期间启用 IMA/EVM。为了测试,策略也可以稍后手动加载。

一旦 IMA 策略变为活动状态,相应的测量和评估就会发生。除了重新启动之外,无法禁用该行为。因此,如果评估设置中断,系统可能会变得无法使用。内核命令行参数,如 ima_appraise=off,可用于完全禁用 IMA 限制。

如何启用 EVM

与 IMA 不同,EVM 不使用策略规则集。元数据保护由 IMA 隐式强制执行。

对于 EVM,只有一个单向开启开关。在启动期间,EVM 最初将被禁用。这是必要的,以便加载将用于验证签名或 HMAC 的密钥到内核中。这应该在 initrd 中完成,请参阅 在早期启动期间启用 IMA/EVM

要手动启用 EVM,需要将值 "1" 写入通常挂载在 /sys/kernel/security 上的 securityfs 中的文件节点 evm

root # echo 1 >/sys/kernel/security/evm

激活 EVM 仅在内核密钥环中加载了密钥后才有效。可以在内核日志中 dmesg 中检查 EVM 激活的结果。也可以从 evm 文件节点读取该值以检查 EVM 是否已成功启用。启用后,无法再次禁用它。

在启用 EVM 之前,必须为 IMA 或 SELinux 或其他与 EVM 交互的安全框架保护的所有相关文件生成适当的数字签名或 HMAC。

IMA 策略语法

对于 IMA,存在一个策略规则集,该规则集定义了文件系统上的哪些文件应该被测量或评估。官方文档可以在 此处 找到。但是,该文档有点稀疏。

在编写自定义策略时,应该采用默认策略中的 dont_measuredont_appraise 行。它们将 /proc/sys、远程网络文件系统等伪文件排除在 IMA 处理之外。

无法将规则限制为路径,例如“测量 /home 中的所有文件”。此限制可能是出于性能原因。由于 IMA 需要挂钩每个文件 open() 和其他文件相关操作,因此比较路径会很昂贵。此外,在某些情况下,甚至不知道路径,例如在 mmap() 中。

每个策略规则必须以以下操作之一开头

  • measure:执行 IMA 测量
  • dont_measure:排除 IMA 测量
  • appraise:执行 IMA 评估
  • dont_appraise:排除 IMA 评估
  • audit:将消息添加到审计日志

可以根据以下表中列出的条件限制规则的应用

条件 description
fsmagic=<magic> 文件必须位于给定的文件系统类型上。有关可能的值,请参阅 man 2 statfs
fsuuid=<id> 文件必须位于具有给定 UUID 的文件系统上。
fowner=0, fowner<1000 文件必须由给定的 UID 拥有,或者必须小于/大于给定的 UID。后者仅在内核 >= 4.12 中才可能。
uid=0, euid=0 尝试访问文件的进程必须以给定的(有效)uid 运行。
func=<context> 限制为特定的文件操作,请参阅下表。
mask=MAY_READ 限制为特定的文件打开模式,MAY_READ 表示该进程请求/具有文件的读取权限。也可以使用 ^ 反转,例如 ^MAY_READ 表示该进程请求/具有文件的读取权限。

下表列出了 func=<context> 条件的可能值

description
BPRM_CHECK “二进制程序检查”。这意味着文件即将作为程序执行。
MMAP_CHECK 文件即将映射到进程内存中。
FILE_CHECK 文件即将被打开。
MODULE_CHECK 文件应该作为内核模块加载。
FIRMWARE_CHECK 文件应该作为固件 blob 加载到内核中。
KEXEC_KERNEL_CHECK 文件应该作为 kexec() 系统调用中的内核加载(自 Kernel 4.6 起)。
KEXEC_INITRAMFS_CHECK 文件应该作为 kexec() 系统调用中的 initramfs 加载(自 Kernel 4.6 起)。
POLICY_CHECK 文件应该作为额外的 IMA 策略加载。

最后,每个规则都有一些选项

  • appraise_type=imasig:对于评估,这要求文件带有数字签名,而不仅仅是摘要。
  • pcr=<num>:对于测量规则,应扩展选定的 TPM PCR 寄存器,而不是默认 PCR 寄存器。

处理逻辑

对于 IMA 遇到的每个文件,都会循环遍历完整的规则堆栈,按给定的顺序。如果 dont_measuredont_appraise 规则匹配,则处理将中止,并且不会应用其他规则。否则,其余规则的操作会累积。例如

measure func=BPRM_CHECK
measure func=FILE_MMAP
appraise fowner=0

这两个规则意味着对于执行或内存映射文件,将执行测量操作。此外,对于由 root 拥有的文件,将执行评估操作。

规则条件在逻辑上是 AND 的,即,如果任何条件未满足,则规则将不会执行。例如,以下规则

measure func=FILE_CHECK mask=MAY_READ euid=0

仅当文件由以 uid 零运行的进程以包含 READ 权限打开文件打开时才匹配。

内核命令行选项

以下是 IMA 内核选项 的摘录。它们会影响 IMA 和 EVM 的操作,并且主要用于在配置期间启用默认策略或以修复模式运行。这些参数需要在启动期间传递给内核,例如通过临时从引导加载程序菜单中添加它们,或通过配置通过附加的引导加载程序条目。

  • ima_appraise=off|enforce|fix|log
    • off:不评估任何文件
    • enforce:拒绝访问不符合策略中预期哈希的文件(默认值)
    • fix:更新不符合预期的文件的哈希值,仅针对在 security.ima 中没有数字签名的文件!
    • log:允许访问哈希值错误的的文件,但将其记录(通常记录到 /var/log/audit/audit.log)
  • ima_appraise_tcb(自 Linux 4.13 起已弃用):请参阅 ima_policy=appraise_tcb
  • ima_tcb:请参阅 ima_policy=tcb
  • ima_policy=tcb|appraise_tcb|secure_boot
    • tcb:应用满足可信计算基 (TCB) 需求的 IMA 策略。测量所有 exec'd 程序、为 exec 映射的文件,由 (euid, uid) == 0 以读取位集打开的文件。
    • appraise_tcb:使用内置的 IMA 评估策略,即评估由 uid=0 拥有的所有文件。
    • secure_boot:根据文件签名评估文件的完整性
  • evm=fix:允许更新 security.evm 属性,即使当前无效。
  • ima_hash=md5|sha1|rmd160|sha256|sha384:用于 IMA 测量的默认哈希算法
  • integrity_audit=0|1:如果设置,则会记录其他信息性审计消息(不在内核文档中?)
  • ima_template=ima|ima-ng|ima-sig:选择测量日志的记录格式
    • ima 仅支持 sha1 摘要
    • ima-ng 支持更长的摘要
    • ima-sig 还包括数字签名
  • ima_template_fmt:允许从字段名称定义自定义记录格式
  • evmkey=<path>:(仅 dracut) 指定要加载的 EVM HMAC 密钥的替代位置
  • evmx509=<path>:(仅 dracut):指定要加载的 EVM X.509 证书的替代位置

在早期启动期间启用 IMA/EVM

Dracut

Dracut 支持加载 IMA 和 EVM 密钥、加载 IMA 策略以及启用 EVM。为此,需要安装 openSUSE 包 dracut-ima。如果您的发行版中没有此软件包,则可以尝试手动安装 dracut 完整性模块 此处

Dracut 执行以下步骤

对于 IMA

  • IMA 密钥在 /etc/keys/ima 中查找。仅支持 X.509 证书。它们将被 dracut 传递给 evmctl import
  • IMA 策略在 /etc/sysconfig/ima-policy 中查找,并在设置公共密钥后加载。

对于 EVM

  • masterkey 模块在 /etc/keys/kmk-trusted.blob 中查找内核主密钥环(如果使用 TPM,则为 trusted;如果使用基于软件的密钥,则为 user)。
  • 完整性模块在 /etc/keys/evm-trusted.blob 中查找加密的 HMAC 密钥,并在 /etc/keys/x509_evm.der 中查找要加载的公共 X.509 证书。仅当也找到 HMAC 密钥时,才会加载 X.509 证书。
  • 如果至少加载了一个 EVM HMAC 密钥,那么 EVM 就启用了内核。

安装 dracut IMA 模块并放置密钥、证书和策略到正确的位置后,可以使用 dracut -f 构建一个新的 initrd。下次使用这个新的 initrd 启动时,dracut 应该尝试加载密钥并启用 IMA 策略。

如果 initrd 中的 IMA/EVM 设置不正确,系统可能根本无法启动。在这种情况下,内核选项 ima_appraise=offevm=fix 可以提供帮助。为了安全起见,保留一个没有 IMA 支持的 initrd 以备回退是有用的。

systemd

systemd 目前仅支持加载自定义 IMA 策略文件。IMA 支持当前未在 openSUSE 的 systemd 包中启用。启用后,它会在 /etc/ima/ima-policy 中查找策略文件并将其加载到内核中。

附加助手

getfattr

可以使用 attr 包中的 getfattr 命令来检查文件是否有任何 IMA/EVM 相关的扩展属性

# getfattr -m . -d /usr/bin/strace

类似地,可以使用 setfattr 命令来删除 IMA 或 EVM 属性

# setfattr -x security.ima /usr/bin/strace

ima_inspect

存储在 security.evmsecurity.ima 属性中的二进制数据不能使用 evmctlgetfattr 程序轻松查看。为了获得包含数据的可读描述,可以使用 ima_inspect 程序,该程序可以在 这里 找到。 相应的 ima-inspect 包现在是更多最近的 openSUSE 和 SUSE Linux Enterprise 版本(SLE-15 及更高版本,Tumbleweed,Leap 15 及更高版本)的一部分。

要使用它,只需将程序指向相关文件即可

user $ ./ima_inspect /usr/bin/ls
/usr/bin/ls

security.ima
------------
digital signature version 2
digest algorithm: sha256
key-id v2 (gpg compatible): 5f3bcd3a
signature length: 2048 bits
signature data:

87f3310cd4a917e9 ac74691e75a0790a 9e6d3f3e9c93b386 093913487ec96884 c51558521af5a124 7efea335d92a494f ef0e16b5b60a4434 0aef5df778ec97d4
728e154a202bc03b 4a464ebc271821dd f58f10c4a85d31c0 b0a66333cfd93938 54ceb3cd3dfb30d7 02ffa491f8c75223 c398c1c2bf1c5603 e7e19822016964fd
61c5eb7e428a0858 363987a41864129a a421c3770496dee8 944f974917322474 0b8a00df5bcc38b3 9c911c75ee5c8188 3ae8933d657e0a72 11a60d8934c75003
b842a5535bd0a0f2 76628e699d2ef1c6 18aad63686d6873b 0cf1242e872c4db3 5a6f248bb1efc756 f8278f0b79e4677a 941c4cc1e05b59ec 6d72a8e2e76a3112


security.evm
------------
no such attribute

示例

以下实践指南基于 openSUSE 发行版,但大多适用于任何当前的 Linux 发行版,除非在软件包管理和内核支持方面存在差异。

Icon-warning.png
警告: 以下命令需要由 root 用户运行,并且通常会修改磁盘上的所有文件。数据很容易因错误而丢失,或者系统将无法再启动。因此,这些示例应该只在可丢弃的机器上或非常小心地进行测试(并进行备份)。

通用先决条件

  • 内核需要支持 IMA。检查 zgrep CONFIG_IMA /proc/config.gz 的输出,以查看启用了哪些 IMA 相关功能。

  • 需要一个当前版本的 evmctl,它通过 zypper in evmctl 安装,或者需要从 上游项目 检查并手动编译。

  • 需要来自 attr 包的 getfattrsetfattr 命令,它通过 zypper in attr 安装。

  • dracut 完整性模块对于创建具有加载 IMA 和 EVM 密钥、证书和策略支持的合适的 initrd 是必需的。通过 zypper in dracut-ima 安装它,或 手动 获取必要的模块。

  • 对于除仅依赖于数字签名以实现不可变文件之外的所有示例,必须使用支持 iversion 挂载选项的文件系统。btrfs 默认启用 iversion。xfs 在 v5 中具有 iversion 支持,默认也启用。ext4 需要将 iversion 挂载选项添加到 /etc/fstab,并添加内核命令行参数 rootflags=iversion,这将导致基于 dracut 的 initrd 添加此挂载标志到根文件系统。在旧版本的 dracut 中,据称需要使用 rootflags=i_version,但当前的 dracut 使用此变体无法启动。

    iversion 挂载选项的目的是使 IMA 能够注意到文件的更改并能够重新测量其内容或更新 HMAC 的哈希值,具体取决于配置。有关更多信息,请参阅 mount(8) 中的 FILESYSTEM-INDEPENDENT MOUNT OPTIONS 部分。

  • 为了能够在扩展属性中存储数据,需要对所有相关文件系统使用 xattr 挂载选项(通常默认启用)。

  • 在 SUSE Linux Enterprise MicroOS 等小型系统上,可能还需要安装 keyutils

IMA 测量

本示例演示如何启用文件内容的 IMA 测量。在这种情况下,测量将限制为由 root 读取的文件以及以某种方式执行的所有文件。

使用 tcb 策略重新启动

首先,需要使用内核命令行参数 ima_policy=tcb 设置重新启动系统。这将激活内置的策略规则集,该规则集对所有 root 拥有的文件执行测量。请注意,这也会导致某种程度的本地拒绝服务,因为普通用户可以导致完整性日志快速增长。

检查完整性日志

完整性日志可以在 /sys/kernel/security/ima/ascii_runtime_measurements 中找到。格式根据可选的 ima_template=ima_template_fmt= 内核命令行参数而异。通常,每行由摘要算法、哈希值和被测文件的文件名组成。

ima_template

使用以下命令选择一个定义的 IMA 测量模板格式:ima_template={ "ima" | "ima-ng" | "ima-sig" }

  1. ima_template=ima:在这种模式下,系统将使用 SHA1 摘要创建目标文件的测量值,例如
    10 45adda1f5d7fc3885f4e6d14b1107673f1cbc786 ima 3b7621d11aee17e96aef4fc2adfa5c344c586157 /lib64/ld-2.26.so
    
  2. ima_template=ima-ng:如果未指定 ima_template,则为默认模式。系统将使用 SHA256 摘要创建更长的目标文件测量值,例如
    10 8674f3f06a823e6a06da98f409a67be0101f9bf7 ima-ng sha256:0ea8d8b9f6527ad176fcab0321271fa936c8faf9bac71eb7eef4c68e76e0e5f1 /lib64/ld-2.26.so
    
  3. ima_template=ima-sig:系统将创建目标文件的测量值,如下所示
    10 60e1faa9118bda69cdec0976e94c30993aaff7ea ima-sig sha256:0ea8d8b9f6527ad176fcab0321271fa936c8faf9bac71eb7eef4c68e76e0e5f1 /lib64/ld-2.26.so
    
ima_template_fmt

使用以下命令定义自定义模板格式:ima_template_fmt={ "field1|...|fieldN" }

字段的有效值为

  • d - 事件的摘要(即,被测文件的摘要),使用 SHA1 或 MD5 散列算法计算
  • n - 事件的名称(即,文件名),大小最多为 255 字节
  • d-ng - 事件的摘要,使用任意散列算法计算(字段格式:[:]摘要,仅当散列算法不是 SHA1 或 MD5 时才显示摘要前缀)
  • n-ng - 事件的名称,无大小限制
  • sig - 文件签名

自定义 ima_template_fmt 字段等效于内置格式

  • ima_template=ima 的默认格式与 ima_template_fmt='d|n' 相同
  • ima_template=ima-ng 的默认格式与 ima_template_fmt='d-ng|n-ng' 相同
  • ima_template=ima-sig 的默认格式与 ima_template_fmt='d-ng|n-ng|sig' 相同

使用 TPM 验证日志

如果系统中可用 TPM 芯片,则默认情况下,IMA 测量中每个测量值的 TPM 的预定义 PCR 寄存器都会被扩展,如 IMA 测量中所述。有关此主题的更多信息,请参阅官方文档。

使用哈希的 IMA 评估

在本示例中,将设置 IMA 以在允许访问属于 TCB 的文件之前检查文件哈希摘要。为了我们的目的,所有由 root 拥有的文件都被认为是 TCB 的一部分。

  1. 以 IMA fix 模式重新启动:需要使用内核参数 ima_appraise=fix ima_appraise_tcb 重新启动系统。在这种模式下,可以更新 IMA 哈希值,并且如果文件被修改,IMA 模块会在内核中自动更正它们。

  2. 创建哈希值:需要对所有由 root 拥有的常规文件进行哈希处理。需要排除伪文件系统。请注意,需要将 -fstype 替换为系统上存在的文件系统类型。在这种情况下,假定默认的 openSUSE 文件系统 btrfs。要更新文件的哈希值,只需将其打开以进行读取即可。因此,语句sh -c "< '{}'"对遇到的每个文件执行此操作

    root # /usr/bin/find / -fstype btrfs -type f -uid 0 -exec sh -c "< '{}'" \;
    

    可以使用 getfattr -m . -d <path> 检查文件,以查看它们都应该具有一个 security.ima 扩展属性,该属性携带文件的 sha256 摘要。

    为了演示目的,可以从一些可丢弃的文件中删除该属性,以便在下一步中看到评估的操作

    # drop the digest from 'strace' for demo purposes
    root # setfattr -x security.ima /usr/bin/strace
    
  3. 使用 IMA 评估策略重新启动:现在需要删除步骤 1 中的内核参数 ima_appraise=fix(但不要删除其他参数)。这将启用内置的策略规则集,该规则集对所有由 root 拥有的文件执行评估。之后,只有当它们具有有效的哈希摘要时,才能访问由 root 拥有的文件。

    继续从步骤 2 开始的演示,现在应该无法由 root 执行 strace

    root # /usr/bin/strace
    -bash: /usr/bin/strace: Permission denied
    # dmesg should show what caused this
    root # dmesg | tail -n 1
    audit: type=1800 audit(1508942646.831:35): pid=2237 uid=0 auid=0 ses=1 op="appraise_data" cause="missing-hash" comm="bash" name="/usr/bin/strace" dev="vda2" ino=332 res=0
    

易变文件(如配置文件或日志文件)在编辑或更改后将无法通过验证,因为摘要将不再匹配。因此,IMA 会隐式地重新计算并存储更新的哈希值到 security.ima 属性中,一旦文件被更改。这就是 iversion 挂载选项所必需的原因

这种 IMA 评估本身并不能提供严格的安全性。只要将正确的 security.ima 属性添加到文件,就可以进行离线文件篡改。为了使其更安全,可以将其与 EVM HMAC 结合使用。在这种情况下,EVM 使用存储在 TPM(在最佳情况下)中的密钥来保护 security.ima 免受篡改。有关更多信息,请参阅 EVM 概念EVM HMAC 示例

使用数字签名进行 IMA 评估

在本示例中,将使用 IMA 仅允许执行数字签名的文件。

生成证书和私钥

对于早于 openSUSE Leap 15 或 SLE 15 的版本

首先需要使用 OpenSSL 创建一个 X.509 证书和一个相应的 PEM RSA 私钥。需要编写一个用于创建证书的配置文件。应根据您的需要调整组织 (O)、通用名 (CN) 和电子邮件地址。

# store the certificates and keys in a separate folder
root # mkdir ~/certs
root # cd ~/certs

# write the config file for openssl
root # cat <<END >self_signed.conf
[ req ]
default_bits = 2048
default_md = sha256
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = myexts

[ req_distinguished_name ]
O = IMASUSE
CN = Executable Signing Key
emailAddress = some@body.com

[ myexts ]
basicConstraints=critical,CA:FALSE
keyUsage=digitalSignature
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid
END

接下来,将使用 OpenSSL 和配置文件创建证书和私钥。如果打算将其用于生产目的,则应选择合适的密码短语并妥善保管私钥。

# this environment variable will contain the passphrase for the private key
root # export PASS=mypass
root # /usr/bin/openssl req -x509 -new -passout env:PASS -utf8 -days 60 -batch -config self_signed.conf -outform DER -out ima_cert.der -keyout ima_priv.pem

对于 openSUSE Leap 15、SLE 15 及更高版本(MOK 方法)

由于即将发布的 SUSE Linux Enterprise 和 openSUSE 发行版,MOK(机器所有者密钥)是注册自定义 IMA 密钥的唯一方法,UEFI 安全启动是先决条件。不要使用上述方法,请按照 UEFI - Booting_a_custom_kernel 中的详细信息来

# 创建一个 X.509 密钥/证书对,并将证书转换为 DER 格式 (ima_cert.der) # 使用 pesign 为内核文件创建新的签名 # 重新启动到 MokManager,注册证书

确保已启用安全启动,并使用 MOK 签名内核启动系统

MOK 目前无法用于 IMA/EVM 的原因

创建相关文件的签名

现在已经有了合适的证书和私钥,就可以创建 IMA 签名了。数字签名仅适用于不可变文件,即在运行时或交互式更改的文件。对于本示例,所有由 root 拥有的可执行文件(脚本、二进制文件、库、内核模块)都将被签名。

请注意,在以下命令行中,私钥密码短语通过 evmctl 的命令行开关传递,这是一种不好的做法,因为普通用户可以在 ps 列表中看到此参数。遗憾的是,evmctl 目前没有提供替代方法。

# replace the filesystem type with what you're using
root # export FS=btrfs
# sign all executable files owned by root
root # /usr/bin/find / -fstype $FS -type f -executable -uid 0 -exec evmctl -a sha256 ima_sign -pmypass -k /root/certs/ima_priv.pem '{}' \;
# sign all libraries which don't carry an executable bit
root # for D in /lib /lib64 /usr/lib /usr/lib64; do
    /usr/bin/find "$D" -fstype $FS -\! -executable -type f -name "*.so*" -uid 0 -exec evmctl -a sha256 ima_sign -pmypass -k /root/certs/ima_priv.pem '{}' \;
done
# also sign kernel modules
root # /usr/bin/find /lib/modules -fstype $FS -type f -name "*.ko" -uid 0 -exec evmctl -a sha256 ima_sign -pmypass -k /root/certs/ima_priv.pem '{}' \;
# also sign firmware files
root # /usr/bin/find /lib/firmware -fstype $FS -type f -uid 0 -exec evmctl -a sha256 ima_sign -pmypass -k /root/certs/ima_priv.pem '{}' \;

配置 IMA 策略和 dracut 早期初始化

下一步是将公共 X.509 证书复制到基于 dracut 的 initrd 将从中找到并加载的位置。这在 /etc/keys/ima

root # mkdir -p /etc/keys/ima
root # cp /root/certs/ima_cert.der /etc/keys/ima

最后,需要将 IMA 策略规则集写入 /etc/sysconfig/ima-policy,initrd 将从那里加载并激活它。为了本示例的目的,使用了以下策略

root # cat <<END >/etc/sysconfig/ima-policy
# PROC_SUPER_MAGIC
dont_measure fsmagic=0x9fa0
dont_appraise fsmagic=0x9fa0
# SYSFS_MAGIC
dont_measure fsmagic=0x62656572
dont_appraise fsmagic=0x62656572
# DEBUGFS_MAGIC
dont_measure fsmagic=0x64626720
dont_appraise fsmagic=0x64626720
# TMPFS_MAGIC
dont_measure fsmagic=0x01021994
dont_appraise fsmagic=0x01021994
# RAMFS_MAGIC
dont_appraise fsmagic=0x858458f6
# DEVPTS_SUPER_MAGIC
dont_measure fsmagic=0x1cd1
dont_appraise fsmagic=0x1cd1
# BINFMTFS_MAGIC
dont_measure fsmagic=0x42494e4d
dont_appraise fsmagic=0x42494e4d
# SECURITYFS_MAGIC
dont_measure fsmagic=0x73636673
dont_appraise fsmagic=0x73636673
# SELINUX_MAGIC
dont_measure fsmagic=0xf97cff8c
dont_appraise fsmagic=0xf97cff8c
# CGROUP_SUPER_MAGIC
dont_measure fsmagic=0x27e0eb
dont_appraise fsmagic=0x27e0eb
# CGROUP2_SUPER_MAGIC
dont_measure fsmagic=0x63677270
dont_appraise fsmagic=0x63677270
# NSFS_MAGIC
dont_measure fsmagic=0x6e736673
dont_appraise fsmagic=0x6e736673

appraise func=BPRM_CHECK fowner=0 appraise_type=imasig
appraise func=BPRM_CHECK euid=0 appraise_type=imasig
appraise func=FILE_MMAP fowner=0 mask=MAY_EXEC appraise_type=imasig
appraise func=FILE_MMAP euid=0 mask=MAY_EXEC appraise_type=imasig
appraise func=MODULE_CHECK appraise_type=imasig
appraise func=FIRMWARE_CHECK appraise_type=imasig
# this is only for newer kernels that support loading policies
# from file by writing the file path to the ima sysfs node
appraise func=POLICY_CHECK appraise_type=imasig
END

该规则集的大部分由从 IMA 策略文档 借用的 dont_measuredont_appraise 规则组成。这些规则从 IMA 评估中排除伪文件系统。

有趣的规则是 appraise 规则,它们实际上是这样说的:要求所有直接执行或以执行权限内存映射的文件都带有数字签名。这仅限于由 root 拥有的文件(fowner=0)或由以 root 身份运行的进程打开的文件(euid=0)。此外,加载到内核中的内核模块和固件文件也需要数字签名。

使用此规则集,可以确保

  • 所有由 root 拥有的由 root 或任何其他用户执行的二进制文件都经过数字签名并且可以信任
  • 所有由具有 root 权限的进程执行的文件都经过数字签名并且可以信任
  • 所有加载到内核中的文件都经过数字签名并且可以信任

普通用户仍然可以构建自己的二进制文件并在无需数字签名的情况下运行它们。

要验证单个文件是否已正确签名

root # evmctl ima_verify /usr/bin/strace

如果验证成功,该命令不应输出任何内容。

或者,您可以直接在 security.ima 中检查签名

root # getfattr -m . -d /usr/bin/strace
# file: usr/bin/strace
security.ima=0sAwIE6yGPDAEAk0bU/ZA1iwEB/aYPx6bdlPDnMSPGggrwqdAALHKrVlOJEH/mD8OLazqM/+skok9EE/3JR04IKaIYDRqwU9XOVpE1P040ZFrvXp3L3t8CJCqHUW0JxDJ7gpbAgzWxeqeaW3nfErNwvlUxaG8CDrXjpZjd/bGeGemCm7gD+t3DhNS0HSgCh4ijTbD90+65WdE4UDCYBrdc+zRZRz77Xn/eHbj8b2ilh5dEtVufvZL9LfUqUiCcw9oq3Zn/9rnXlX1kxcOrmbwxAfpItFjbM3bAJS8QQYajU7l1A+w/4VA/mfcMuthNZJtdlawlk+eSH2MJNXmKr/qoYuFlRwxGHnFOCw==

重启和测试

一切就绪后,需要重启系统,initrd 应该自动将 X.509 证书加载到内核密钥环中并激活自定义 IMA 策略。如果启动失败,则内核参数 ima_appraise=off 有助于再次暂时禁用 IMA 评估。如果一切顺利,系统应该像往常一样启动。您应该在内核日志中看到有关策略更新的消息

root # dmesg | grep IMA:.*completed
IMA: policy update completed

如果从文件中删除了携带数字签名的 security.ima 属性,则不应再能够执行该文件

root # setfattr -x security.ima /usr/bin/strace
root # /usr/bin/strace
-bash: /usr/bin/strace: Permission denied

同样,root 用户不应能够运行属于普通用户的任何二进制文件。任何普通用户也不应能够运行属于 root 拥有的且缺少签名的二进制文件。

请注意,脚本无法真正通过 IMA 评估来保护,并且关于数字签名的行为有点奇怪

出于生产目的,/root/certs/ima_priv.pem 中的私钥应从系统中删除。

在数字签名的系统上更新软件将不起作用,如果安装的 RPM 包不携带合适的数字签名。

使用 HMAC 保护 EVM

在本示例中,我们将配置 EVM 以保护文件元数据和 security.ima 扩展属性。

创建内核主密钥和 EVM HMAC 密钥

对于 EVM HMAC 操作,需要将一个秘密对称密钥加载到内核中。该密钥既用于创建更新的 HMAC,也用于验证现有的 HMAC。为了良好的安全性,此秘密密钥应与 TPM 芯片(所谓的受信任密钥)相关联。在本示例中,将使用基于软件的密钥(所谓的加密密钥)。有关密钥生成的更多信息,请参阅 evmctl READMEGentoo Linux EVM 指南

# this creates a "kernel master keyring" and stores its representation in
# /etc/keys
root # /bin/keyctl add user kmk-user "`dd if=/dev/urandom bs=1 count=32 2>/dev/null`" @u
root # /bin/keyctl pipe `/bin/keyctl search @u user kmk-user` > /etc/keys/kmk-user.blob

# this creates an EVM key which will be used for EVM HMACs
root # /bin/keyctl add encrypted evm-key "new user:kmk-user 64" @u
root # /bin/keyctl pipe `/bin/keyctl search @u encrypted evm-key` >/etc/keys/evm.blob

EVM 密钥在 evm.blob 中是从内核主密钥环 kmk-user.blob 派生的,因此需要以正确的顺序和正确的方式加载它们才能工作。dracut 在启动期间会根据调整后的某些配置文件执行此操作

# configuration for loading the kmk via dracut
root # cat <<END >/etc/sysconfig/masterkey
MASTERKEYTYPE="user"
MASTERKEY="/etc/keys/kmk-user.blob"
END

# configuration for loading the evm key via dracut
root # cat <<END >/etc/sysconfig/evm
EVMKEY="/etc/keys/evm.blob"
END

重启进入 IMA/EVM 修复模式

现在需要使用内核参数 evm=fix ima_appraise=fix ima_appraise_tcb 重启系统。与 使用哈希的 IMA 评估 类似,这将导致所有由 root 拥有的文件被评估。IMA 和 EVM 内核模块会自动修复无效的哈希和 HMAC。如果上一步的密钥设置正确并且 dracut 成功加载了它们,那么 EVM 应该现在启用,可以通过这种方式进行测试

root # cat /sys/kernel/security/evm
1

一旦 EVM 启用,就无法禁用它,除非通过重启并更改内核参数或更改 dracut 配置。

以下命令将为所有 root 拥有的文件创建 IMA 哈希。这也会隐式触发这些文件的 EVM HMAC 生成。请注意,需要根据系统上实际使用的文件系统调整 -fstype。此操作需要几分钟,具体取决于磁盘访问速度和文件系统中的文件数量。

Icon-warning.png
警告:-fstype btrfs选项在 openSUSE Tumbleweed 和 SUSE Linux Enterprise 15 Beta 上不起作用,因为 find 的此选项目前已损坏(请参阅 bnc#1073882)。
root # /usr/bin/find / -fstype btrfs -type f -uid 0 -exec evmctl -a sha256 ima_hash '{}' \;

检查文件时,现在应该可以看到 security.imasecurity.evm 属性。

root # getfattr -m . -d /usr/bin/strace
# file: usr/bin/strace
security.evm=0sAjJ76U7zXW65413dvLse3r3Mf7Yf
security.ima=0sBAToCmv9mpTW9VIp7fJ+Cyy4W8LXX4ELzGROf9DEtoZojg==

EVM 属性较短,因为它仅使用 sha1 摘要,而 IMA 属性使用 sha256,如 -a sha256 命令行参数所示。

为了查看 EVM 保护的实际效果,可以从一些可忽略的文件中删除 security.evm 属性

# drop the HMAC from 'strace' for demo purposes
root # setfattr -x security.evm /usr/bin/strace

重启进入强制 IMA/EVM 模式

在所有文件获得其摘要和 HMAC 后,可以仅使用内核参数 ima_appraise_tcb 进行重启。重启后,所有受 IMA 保护的文件也将受到 EVM 的额外保护,即在检查 IMA 摘要之前,将检查 IMA 摘要和其他文件元数据是否可以使用 EVM HMAC 进行验证。

这提供了针对离线文件篡改的保护,因为攻击者需要秘密 EVM HMAC 密钥才能生成正确的 security.imasecurity.evm 属性以使修改后的文件再次有效。但是,使用基于软件的 EVM HMAC 密钥,秘密密钥仍然可以在磁盘上找到。因此,只有使用 TPM 的变体,其中 EVM HMAC 密钥是包装的 TPM 密钥,才能提供真正的保护。

为了完成上一节的演示,现在应该无法再执行 strace 命令

root # /usr/bin/strace
-bash: /usr/bin/strace: Permission denied

即使存在有效的 security.ima 属性

root # getfattr -m . -d /usr/bin/strace
# file: usr/bin/strace
security.ima=0sBAToCmv9mpTW9VIp7fJ+Cyy4W8LXX4ELzGROf9DEtoZojg==

由于 EVM 属性的 HMAC 在运行时存在,因此 EVM 内核模块会在修改有效文件(如配置文件)时隐式更新 security.evm 属性。这与 使用哈希的 IMA 评估 中解释的机制相同。

使用数字签名保护 EVM

与上一节类似,在本示例中,EVM 将被设置为保护文件元数据和 security.ima 扩展属性。不同之处在于,不是使用 EVM HMAC,而是使用使用 X.509 证书的数字签名。就像在 使用数字签名的 IMA 评估 中一样,这种方法仅适用于不可变文件,例如二进制文件。

要继续此示例,请首先使用 使用 HMAC 保护 EVM 中描述的方式设置系统。原因是 EVM HMAC 密钥是 dracut 加载 EVM X.509 证书的先决条件,尽管在本例中不需要 HMAC 密钥。更新:Tumbleweed、Leap 15.0 和 SLES-15 中较新版本的 dracut 现在可以在没有配置 HMAC 密钥的情况下加载 X.509 证书,但内核代码不会初始化 evm(如果未提供 HMAC 密钥),因此这仍然是先决条件。

生成证书和私钥

按照 此处 描述的步骤创建证书和私钥。将生成的私钥放在 /root/certs/evm_priv.pem 中,并将公共证书放在 /etc/keys/x509_evm.der 中。后者是 dracut 放置 EVM X.509 证书的默认位置。

为相关文件创建签名

需要使用内核命令行参数 ima_appraise=fix evm=fix ima_appraise_tcb 重启系统,以便可以替换一些 EVM HMAC 为数字签名。

签名创建方式与 ima 相同,只是 evmctl 命令行进行了调整以创建 EVM 签名。但是,有一个重要区别:我们需要为相关文件设置不可变属性。这是通过 chattr 实用程序完成的。此标志指示文件系统不允许对文件或其元数据进行任何更改。如果未提供此标志,则 EVM 内核代码将在运行时开始用 HMAC 替换签名。以下命令将为相关不可变文件(即可执行文件、内核模块和固件文件)创建 EVM 签名并添加不可变标志

# sign all executable files owned by root
root # /usr/bin/find / -fstype btrfs -type f -executable -uid 0 -exec evmctl sign -pmypass -k /root/certs/evm_priv.pem '{}' \;
# sign all libraries which don't carry an executable bit
root # for D in /lib /lib64 /usr/lib /usr/lib64; do
    /usr/bin/find "$D" -fstype btrfs -\! -executable -type f -name "*.so*" -uid 0 -exec evmctl sign -pmypass -k /root/certs/evm_priv.pem '{}' \; -exec chattr +i '{}' \;
done
# also sign kernel modules
root # /usr/bin/find /lib/modules -fstype btrfs -type f -name "*.ko" -uid 0 -exec evmctl sign -pmypass -k /root/certs/evm_priv.pem '{}' \; -exec chattr +i '{}' \;
# also sign firmware files
root # /usr/bin/find /lib/firmware -fstype btrfs -type f -uid 0 -exec evmctl sign -pmypass -k /root/certs/evm_priv.pem '{}' \; -exec chattr +i '{}' \;

请注意,EVM 数字签名当前在 btrfs 文件系统上失败。有关更多信息,请参阅 btrfs 限制

可以使用以下命令验证已签名文件的 EVM 签名

root # evmctl verify /usr/bin/strace

如果验证成功,该命令不应输出任何内容。

重启进入强制 IMA/EVM 模式

现在需要仅使用内核命令行参数 ima_appraise_tcb 重启系统。EVM 数字签名现在应该被强制执行。

为了获得最佳安全性,应从系统中删除 /root/certs/evm_priv.pem 中的 EVM 私钥。如果不想使用 TPM 芯片并且不仅要保护文件内容,还要保护元数据,则 EVM 数字签名是合适的。如果只需要保护文件内容,则 IMA 数字签名就足够了。

由于 EVM 数字签名无法由 EVM 内核模块自动更新,因此即使更改了文件所有者、模式或与安全相关的扩展属性,也会导致 EVM 验证失败。

使用 IMA 签名在 RPM 包中签名二进制文件

上游的当前 rpm 包支持将 IMA 签名添加到 RPM 包中的所有非配置文件。但是,目前 openSUSE rpm 包没有编译 IMA 支持。

目前无法为 RPM 包添加 EVM 签名。原因是 EVM 涵盖的元数据难以在包中维护(inode 编号等)。evmctl 中有一个(隐藏的?)命令行选项,可以为 EVM 创建一种不同的数字签名格式,用于不可变文件(另请参阅 此处)。但是,此功能似乎并未进入 IMA 内核代码。

使用 rpmsign 附加 security.ima 的示例

  1. 您需要一个支持 IMA 的 RPM 包

  2. 要签名的 RPM 包的 spec 文件必须定义宏 _binary_filedigest_algorithm,如下所示

    %define _binary_filedigest_algorithm 8

    8 代表 sha256。可以在 RPM 源代码 build/files.c 的函数 genCpioListAndHeader() 中找到这些数字。

  3. 添加 IMA 签名还需要向 RPM 添加 GPG 签名。请参阅 此处,了解 rpmsign 和 gpg 的快速设置,以实现此目的。

  4. 如下命令行签名 RPM 包中的所有非配置文件

    root # rpmsign --addsign --signfiles --fskpass=<pass> --fskpath=/root/certs/ima_priv.pem /tmp/some.rpm
    

    此处通过命令行传递私有 PEM 证书的密码,这是不好的做法。据称 $HOME/.rpmmacros 中的宏 _file_signing_key_password 应该有效,但对我不起作用。

    即使添加了 --fskpassrpmsign 仍然在命令行上询问我一次密码。如果没有 --fskpass,它会询问我包中的每个文件。

请注意,即使以这种方式向 RPM 包添加 IMA 签名,也不兼容旧版本的 RPM,这些版本不支持 IMA。因此,它不向后兼容。

进一步强化 IMA/EVM

kexec() 系统调用

从 Linux 内核 4.6 开始,IMA 策略函数 KEXEC_KERNEL_CHECKKEXEC_INITRAMFS_CHECK 也可以使用。它们允许在 kexec() 系统调用上下文中传递的内核和 initramfs 进行评估。

这样做很重要,可以避免执行不受信任的代码,例如,只允许在系统中执行数字签名的二进制文件。

内核中的受信任根证书

为了获得证书使用方面的真正信任锚点,可以将受信任的系统证书编译到 Linux 内核中。从内核 4.5 开始,可以使用内核选项 INTEGRITY_TRUSTED_KEYRING。这允许将 IMA 和 EVM 证书限制为已由受信任的系统证书签名的证书。可以通过内核选项 SYSTEM_TRUSTED_KEYS 将系统受信任的证书编译到内核中。

使用这种方法,可以避免在运行时添加任意额外的 X.509 证书,从而导致接受来自未知来源的 security.imasecurity.evm 属性中的其他签名。

这种方法仍然允许第三方将其自己的 X.509 密钥签名的文件添加到系统中。第三方证书需要由系统受信任的密钥签名,然后 IMA/EVM 将接受第三方签名。

当启用内核选项 INTEGRITY_TRUSTED_KEYRING 时,内核中的完整性代码本身将创建 .ima 密钥环。这是为了确保密钥环获得限制,仅允许添加由 .builtin_trusted_keys 密钥环中的密钥签名的密钥。另一方面,如果未启用内核选项,则 dracut 会从 initrd 中创建 _ima 密钥环(请注意名称不同!)并将密钥加载到其中。

此外,还有内核选项 CONFIG_SECONDARY_TRUSTED_KEYRING,它会稍微降低要求。使用它,在 .secondary_trusted_keys 密钥环中找到的密钥签名的密钥也将在 .ima 密钥环中被接受。

这些内核选项将在即将发布的 SUSE Linux Enterprise 15 发行版中激活。使用 UEFI 安全启动时,可以将 MOK(机器所有者密钥)注册到 UEFI 固件中。在 evmctrl README 的“生成受信任的密钥”部分,记录了设置最小 CA 并使用它对 IMA 公共证书进行签名的必要的 openssl 命令。公共 CA 证书需要作为 MOK 注册,然后可以加载签名的 IMA 公共证书到 .ima 密钥环中。

这种情况使得例如在虚拟机中进行测试变得更加复杂。您需要运行使用 UEFI 固件模拟的 Qemu,并且必须以安全启动模式安装 SLES15。然后,使用 /boot/EFI/sles/MokManager.efi EFI 子例程,您可以注册上述 CA。配置 UEFI 固件以进行安全启动的详细信息因实现而异。请参阅 安全启动页面,了解更多信息。

MOK 目前无法用于 IMA/EVM 的原因

评估策略文件本身

从 Linux 内核版本 4.6 开始,可以评估策略文件本身。为此,不是将策略数据直接写入 /sys/kernel/security/ima/policy,而是写入包含策略数据的文件路径。这允许在接受后续策略更新之前对其进行评估。

要评估策略文件,需要使用策略规则条件 func=POLICY_CHECK

目前似乎无法评估初始策略文件。内核选项 IMA_APPRAISE_SIGNED_INIT 似乎适合实现此目的。此选项需要对 init 二进制文件进行签名。结合受信任的系统密钥,这可能会提供完整的信任链。

禁用 ima_appraise=fix 内核参数

内核启动参数 ima_appraise=[...] 允许攻击者以某种方式访问内核命令行,从而绕过评估。通过禁用内核选项 IMA_APPRAISE_BOOTPARAM,将不再评估此参数。但是,这仅适用于生产系统,其中 IMA/EVM 设置不再存在任何问题。

但是,此选项仅在 Linux 内核版本 4.13 中添加。

评估基于 RAM 的文件系统

IMA 评估的内置文件系统异常列表跳过了对 TMPFS 和 RAMFS 文件系统的评估。因此,在例如基于内存的 /tmp 安装上找到的可执行文件将不会检查签名或摘要。原因是 initrd 在早期启动期间放置在基于 RAM 的文件系统中。initrd 是一个 cpio 归档文件,不支持添加 IMA 所需的扩展属性等元数据。

如果评估初始 initrd 文件系统,则启动将失败。但是,在早期启动完成后,TMPFS 和 RAMFS 文件系统的异常会削弱 IMA 提供的安全性。

已经有尝试扩展 cpio 归档格式以承载扩展属性。但目前似乎尚未实现。

性能影响

IMA 和 EVM 模块在内核侧执行大量的缓存,从而避免了不必要地重复检查。我们需要区分不可变文件和经常更改的文件

  • 很少更改或不可变且带有数字签名的文件,只有在 IMA 首次遇到它们时才会被检查。因此,首次文件访问与未使用 IMA 的系统相比可能会变慢。
  • 经常更改并带有 IMA 摘要和/或 EVM HMAC 的文件,将在首次访问时以及对文件执行的每次修改时进行更新/检查。因此,在这种情况下,速度会降低更多。

仅对可执行文件强制执行 IMA 数字签名的系统,在启动期间会经历轻微的减速。在正常操作期间,不应出现明显的减速。

在人工测试场景中,带有 IMA 数字签名的文件的程序执行速度减慢了约 30%。在实践中,由于并行化、I/O 延迟等原因,预计影响会更小。

注意事项

SUSE 发行版中的限制

  • 当前的 openSUSE Leap 和 SLES-12 发行版都使用基于版本 4.4 的内核,因此本文档中提到的一些功能(如 kexec 评估)尚未可用。

  • systemd 不包含 IMA 支持(请改用 dracut)。

  • 目前,较旧的 SUSE 发行版中不可用 dracut-ima 包。可以从 openSUSE dracut GitHub 仓库 复制缺失的 dracut 模块,如下所示

    user $ git clone git@github.com:openSUSE/dracut.git
    user $ cd dracut/modules.d
    # become root
    user $ su -
    root # cd /home/user/dracut
    root # cp -rvi 96securityfs 97masterkey 98integrity /usr/lib/dracut/modules.d
    # enable inclusion of the new module in the initrd
    # run this command as root
    root # echo 'add_dracutmodules+=" integrity "' >>/etc/dracut.conf.d/40-ima.conf
    # save the current initrd if something goes wrong
    root # cp /boot/initrd /boot/initrd.before.ima
    # rebuild the initrd, takes some time
    root # dracut -f
    
  • rpm 包中的 rpmsign 命令目前缺少对 IMA/EVM 签名的支持。

  • 尝试在 btrfs 文件系统上生成 EVM 哈希时,evmctl 命令会失败。这是因为在 btrfs 上,需要以与传统文件系统不同的方式收集 UUID。此外,Linux 内核似乎假定基于 btrfs 的文件系统具有全零 UUID。要解决此问题,需要将选项 -u00000000-0000-0000-0000-000000000000 传递给 evmctl

    还可以完全从 EVM 哈希中排除文件系统 UUID。为此,需要将 -u 选项(不带值)传递给 evmctl,并且 Linux 内核必须在未设置 CONFIG_EVM_ATTR_FSUUID 选项的情况下进行编译。

  • 较新的 SUSE 发行版,如当前的 Tumbleweed 或 SUSE Enterprise 15 Beta,使用cgroup2伪文件系统,但ima_appraise_tcb默认策略并未将其从测量和评估中排除。这将导致启动错误,出现systemd冻结,因为它无法访问cgroup2挂载点。

复制或编辑带有数字签名的文件

复制或编辑带有数字签名(在扩展属性 security.imasecurity.evm 中)的文件时,必须特别小心。典型的 cp file1 file2 不会复制扩展属性。因此,如果启用了评估,则可能拒绝访问文件副本。

编辑文件时,编辑器通常会重新创建该文件。在此过程中,扩展属性将丢失,并且与复制一样会发生。

使用 PEM RSA 公钥和签名方案版本 1

在使用带有公共/私有 PEM 格式 RSA 密钥的旧签名方案时,适用以下限制

  • 不能使用比 sha1 更强的摘要。
  • dracut 不支持加载 PEM 公钥,因此无法通过这种方式执行早期初始化。

旧签名方案是 evmctl 旧版本中的默认设置,但在当前版本中,必须通过传递 --rsa 作为参数来显式选择。

数字签名和可执行脚本

类似于 appraise func=BPRM_CHECK appraise_type=imasig 的 IMA 策略规则会导致对所有已执行文件进行评估。乍一看,这似乎也适用于脚本

root # cat <<END >test.sh
#!/bin/bash
echo script executed
END

root # chmod +x ./test.sh
root # ./test.sh
-bash: ./test.sh: /bin/bash: bad interpreter: Permission denied

但是,可以通过解释器显式执行脚本,

root # /bin/bash ./test.sh
script executed

原因是解释器具有有效的 IMA 数字签名,并且可以正常执行。传递给解释器的参数不由 IMA 验证。这将是不现实的,因为内核需要知道所有可能的解释器及其支持的参数。

当脚本通过 shebang 行隐式执行时,该脚本被视为可执行文件,但是,IMA 会介入。这不可取,因为它不会提供额外的安全性,因为可以通过显式传递给解释器来执行该脚本。但是,目前无法允许执行未签名的脚本。这是 IMA 缺少的功能。

最小签名和摘要长度

当前的 IMA 策略语法不允许强制执行最小 RSA 密钥长度或摘要强度。因此,即使策略可以要求对文件进行签名,也不能保证涉及强大的加密。这只能由加载到内核中的公共证书限制。

在运行 evm=fix 时启用 EVM 仍然导致权限被拒绝

可能会发生将 evm=fix 添加到内核命令行,并在通过 /sys/kernel/security/evm 启用 EVM 后,文件访问仍然被拒绝的情况。这是因为在 IMA 评估的上下文中,也会检查 EVM,如果检查失败,则拒绝访问。

这可能会导致奇怪的效果,因为 IMA 会缓存评估结果。在启用 EVM 之前已被 IMA 评估过的文件,在启用 EVM 后仍然可以工作。但是,IMA 缓存中没有的文件将无法工作。

要解决此问题,需要以 fix 模式运行 IMA 和 EVM,即还需要将 ima_appraise=fix 添加到内核命令行。

MOK(机器所有者密钥)不能用于 IMA/EVM

如果您发现 MOK(机器所有者密钥)已注册到 openSUSE Leap 15.0 或 SLE15 上的 .secondary_trusted_keys,这只是内核模块验证的副作用,而不是 SLE15 的真正支持功能。此副作用自 SLE15-SP2 起已被删除,以与 v5.3 主线内核保持一致。主线内核也从未具有此功能。在主线内核中,MOK 将注册到 .platform keyring,该 keyring 不与受信任的密钥环(.builtin_trusted_keys 或 .secondary_trusted_keys)链接。

原因是 db 或 mok 中的密钥用于启动。目前,内核上游仅接受来自 db/mok 的密钥用于 kexec。db/mok 密钥的信任不应扩展到其他用途,例如 IMA/EVM。

目前,上游显示了两种可能的解决方案

- David Howells 提出了补丁,以增强基于 x.509 证书上的 extendedKeyUsage 扩展的密钥限制

X.509:根据 X.509 证书中的信息限制密钥的使用

但此更改尚未合并到内核主线中。如果我们可以通过 X.509 信息识别 db/mok 中的密钥的目的,那么就有可能将密钥注册到内核中的不同密钥环中,用于不同的目的。例如,IMA 文件评估。David 的补丁也在 Linux Firmware Signing 邮件循环中讨论

Linux Firmware Signing

但此邮件循环的方向已移动到带有 IMA 的 LSM。我认为主线内核应该首先完成带有 LSM 函数的 IMA-filer-verify。

- Eric Snowberg 提出了两个新的 EFI 变量,以指示用户希望信任平台内核中的密钥或启用安全启动 IMA 策略

添加额外的 MOK 变量

(2021-10-22 更新)

PATCH v6 00/13 通过 MOK 注册内核密钥

引入一个新的 MOK 变量,称为 MokListTrustedRT #423

参考文献