根据机箱入侵检测执行操作

根据机箱入侵检测执行操作

鉴于:

  • 运行 GNU/Linux 的服务器,以及

  • 该服务器上的机箱入侵检测开关,以及

  • 该服务器中的 BIOS(或 UEFI),用于跟踪入侵检测状态,以便可以通过freeipmi或类似方式读取该状态,

如果服务器机箱打开,如何才能最好地使该服务器执行某些操作(例如发送电子邮件或简单地关闭)?

用户森林关于 security.stackexchange 建议轮询“/dev/nvram每 0.5 秒左右解析一次,以获取存储机箱入侵计数的任何值。“ (执照:抄送-SA 3.0.)这似乎效率低下。当然有更好的方法吗?

答案1

以下引用自:firmware.intel.com/blog/accessing-uefi-variables-linux

由 mfleming 发表于 01/3/2014

本文总结了 Linux 提供的两种用于访问 UEFI 运行时变量的方法,以及权衡和一些历史记录。

The Legacy efivars Interface

由 Matt Domsch 编写的用于与 UEFI 变量交互的原始接口通过通用 Linux 内核 sysfs 文件系统导出。该接口是在 UEFI 之前的 EFI 时代创建的,用于安腾计算机,因此带有一定的历史包袱。

旧版 efivars 接口通过相对于 sysfs 挂载点的路径“firmware/efi/vars/”导出。假设 sysfs 安装在 /sys,则包含 efivars 文件的目录将是:

    /sys/firmware/efi/vars/

除了特殊文件new_var和之外del_var,上述挂载点中的每个条目本身就是一个目录 - 每个在运行时可访问的 UEFI 变量都有一个目录,

    Boot0000-12345678-abcd-abcd-abcd-123456789abc/
    Boot0001-12345678-abcd-abcd-abcd-123456789abc/
    BootCurrent-12345678-abcd-abcd-abcd-123456789abc/
    BootOrder-12345678-abcd-abcd-abcd-123456789abc/
    BootSetup-12345678-abcd-abcd-abcd-123456789abc/
    del_var
    Lang-12345678-abcd-abcd-abcd-123456789abc/
    LangCodes-12345678-abcd-abcd-abcd-123456789abc/
    new_var
    Setup-12345678-abcd-abcd-abcd-123456789abc/ 

UEFI 变量的目录名称由变量名称和变量的全局唯一标识符 (GUID) 组成。这个例子:

    Boot0000-12345678-abcd-abcd-abcd-123456789abc/ 

可能是第一个 UEFI 引导变量的目录。在每个目录中可以找到以下文件,

    attributes
    data
    guid
    raw_var
    size 

大多数这些文件的内容是人类可读的,并且对应于同名的 UEFI 变量参数。 “raw_var”文件是个例外,它包含二进制数据。例如,上述引导条目的“属性”文件将包含类似以下 ASCII 字符串的内容,

    EFI_VARIABLE_NON_VOLATILE
    EFI_VARIABLE_BOOTSERVICE_ACCESS
    EFI_VARIABLE_RUNTIME_ACCESS 

指示该变量是非易失性的,并且在调用 UEFI 引导服务 ExitBootServices() 之前和之后都可以访问。不可能写入这些人类可读的文件 - 它们的唯一目的是为用户提供变量的详细信息。

raw_var允许从用户空间读取/写入内核中使用的 UEFI 变量二进制数据结构,并且是遗留接口的核心部分。对现有变量的所有修改都是通过传递“struct efi_variable”对象通过此文件执行的,

struct efi_variable {

    efi_char16_t VariableName[1024/sizeof(efi_char16_t)];
    efi_guid_t VendorGuid;
    unsigned long DataSize;
    __u8 Data[1024];
    efi_status_t Status;
    __u32 Attributes;

} __attribute__((packed));

顾名思义,顶层目录中的特殊文件“new_var”和“del_var”用于创建和删除 UEFI 变量。这些文件不使用人类可读的文本。相反,“struct efi_variable”对象在内核和用户空间之间来回传递,以创建新变量或删除现有 UEFI 变量。

在 Linux 内核中保留 efivars 接口的主要原因是仍然有一些工具仅使用此接口:efibootmgr 工具在所有 Linux 发行版上都可用,用于控制 UEFI 系统上的启动顺序,但仍然使用此传统工具界面。

然而,旧版 efivars 界面存在一些限制,随着时间的推移,这些限制已开始成为一个令人头疼的问题。

最明显的缺点是可以读取/写入的 UEFI 变量数据的大小有上限。由于内核数据结构的设计方式,无法读取或写入超过 1024 字节的变量数据,并且对于某些用例,该限制是一个问题。

此外,efivars 接口本质上需要工具来操作 UEFI 变量,因为该接口仅通过“new_var”、“del_var”和“raw_var”处理 UEFI 变量的重要“struct efi_variable”数据结构的读写副本特殊文件。如果不构建“struct efi_variable”对象并将其写入“del_var”文件,则无法删除 UEFI 变量。

efivarfs 文件系统

为了避开旧版 efivar 接口的限制,Matthew Garrett 和 Jeremy Kerr 创建了全新的 Linux 文件系统。这个新文件系统被命名为“efivarfs”,是 Linux 内核 v3.10 版本的一部分。

与所有其他 Linux 文件系统一样,efivarfs 必须安装在某个位置才能访问其文件,这可以通过发出以下命令来完成:

    mount -t efivarfs none /sys/firmware/efi/efivars 

efivarfs 不包含目录,而是包含名称根据 UEFI 变量名称和 GUID 构建的文件,

    Boot0000-12345678-abcd-abcd-abcd-123456789abc
    Boot0001-12345678-abcd-abcd-abcd-123456789abc
    BootCurrent-12345678-abcd-abcd-abcd-123456789abc
    BootOrder-12345678-abcd-abcd-abcd-123456789abc
    BootSetup-12345678-abcd-abcd-abcd-123456789abc 

尽管每个文件都包含二进制数据(如旧版接口的new_var, del_var),但 efivarfs 的数据结构要简单得多,仅包含 4 个字节用于 UEFI 变量属性位掩码,其余部分是 UEFI 变量数据,例如

struct new_efi_variable
{

   u32 attributes;
   u8 data[0];

};

所有其他信息(例如变量名称、GUID 和大小)都是从正在读取/写入的文件名推断出来的。这使得通过创建或删除文件来创建或删除 UEFI 变量变得很简单。

例如,以下 shell 命令创建一个新变量,

    printf "\x07\x00\x00\x00\x00" > myvar-12345678-1234-1234-1234-123456789abc 

myvar使用 GUID12345678-1234-1234-1234-123456789abc以及 属性位掩码中设置的EFI_VARIABLE_NON_VOLATILEEFI_VARIABLE_BOOTSERVICE_ACCESSEFI_VARIABLE_RUNTIME_ACCESS位命名,后跟 1 个字节的数据(最后的\x00)。

可以使用任何获取文件大小的常用方法来找到变量的大小以及 4 个字节的属性数据。例如,运行以下 shell 命令,

    du -b myvar-12345678-1234-1234-1234-12345678abc 

将打印“5”——即变量属性位掩码的 4 个字节,加上 1 个字节的数据。

要删除该变量,只需将其从 efivarfs 文件系统中删除即可,

    rm myvar-12345678-1234-1234-1234-12345678abc 

显然,这是一个更直观的界面,用于从命令行和 shell 脚本访问 UEFI 变量。最重要的是,与传统接口不同,UEFI 变量可读取/写入的数据量没有限制。

当然,尽管 efivarfs 使用的数据结构比遗留接口简单得多,但它仍然作为二进制数据进行读/写,并且比遗留接口提供的人类可读文件需要更多的心理处理。

在本文中,我们简要讨论了 Linux 提供的两种在运行时访问 UEFI 变量的解决方案。虽然新的 efivarfs 文件系统提供了一个有用的接口,用于从 shell 脚本(甚至从命令行)访问 UEFI 变量,但某些工具仍在使用旧接口,并且在某些情况下,人类可读的文件可能比efivarfs 的纯二进制接口。

Matt Fleming 是英特尔开源技术中心的软件工程师和 Linux 内核 (U)EFI 维护者。

相关内容