当大多数 Linux 用户听到“root”时,他们会想到计算机上可能的最大权限。有些人甚至认为 root 在 ring 0 中运行。但实际上,root 只是在 ring 3 中运行的普通用户,尽管内核信任这个用户(许多敏感的内核操作都通过检查来保护if (!uid_eq(current_uid(), GLOBAL_ROOT_UID)) return -EPERM;
以防止滥用,这只是如果 ) 则返回错误uid != 0
。
在大多数 Linux 系统上,内核非常信任 root,以至于它可以轻松地利用内核并随意访问 ring 0。但是,通常可以使用 grsecurity、SELinux 等安全工具通过降低 root 的危险能力并在内核级别强制执行这些限制来防止这种情况发生。
我想列举一个方法列表,root 可以通过这些方法利用内核来访问内核模式和 ring 0。到目前为止,这些是我想到或了解到的可能发生这种情况的方法,以及潜在的缓解措施:
ioperm()
并且iopl()
可以设置 I/O 端口权限,并且可以被滥用来写入任意内存区域,包括内核所在的内存。这些系统调用可以通过从系统调用表中删除或使用 grsecurity 来禁用。- root 只能在块设备中
/boot
或通过块设备修改内核映像。MAC 可以限制 root 对这两者的访问。 /dev/{k,}mem
旨在允许 rw 访问任意内存。这些可以通过使用 grsecurity 或 MAC 在内核配置中完全禁用。- 一些 MSR 可用于写入任意内存。通过在内核配置中禁用它们或使用 grsecurity 来拒绝写入 MSR 可以缓解此问题。
kexec
允许 root 选择一个备用内核来引导。这是一个可选的内核功能,因此只需在没有kexec
支持的情况下编译内核就足以使这成为非问题。sysfs
提供对大部分硬件的低级别访问,这可以劫持许多易受攻击的系统上锁定不佳的 BIOS/UEFI 以获得 ring 0 甚至 ring -2 访问权限。MAC 可以限制对 的访问/sys
,并且各种工具可以检测 UEFI/BIOS 中的漏洞。- 如果允许 root 在运行时加载 ACPI 表(DSDT、SSDT 等),它可能会导致内核执行 AML,即 ACPI 字节码,并改变内核的行为方式以及对其运行的硬件的反应方式。我对 ACPI 和 AML 知之甚少,但这听起来绝对是灾难的根源。在内核中禁用可加载 ACPI 表支持应该可以缓解这种情况。
- 加载恶意内核模块可以直接劫持内核。这可以通过需要模块签名或构建没有模块支持的内核来轻松解决。
显然,我将使用最小特权的主体作为 root,而不是试图将它可以打破其链的所有可能方式列入黑名单。这并没有改变它仍然非常有用和有趣的事实,以了解它可以滥用内核信任的所有方式。
这让我想到了我的问题:root 是否可以使用任何其他方法来访问 ring 0,而不使用 0days 并且不利用 opsec 错误,我没有在这里介绍?