在 Linux 上对 root 保密

信息安全 linux 硬化
2021-08-29 12:05:44

我正在寻找强化 linux 系统的方法,以便即使获得完全的 root 访问权限(通过合法或非法手段),一些秘密仍然无法访问。但首先有一点背景。

许多不同的 linux 安全模型(SELinux、TOMOYO 等)都专注于限制进程可以通过策略执行的操作,并确保它们不需要完全的 root 访问权限。他们的目标是控制任何漏洞,以免系统的其他部分受到损害。然而,这些似乎并没有直接解决已经获得完整 root 的情况 - 或者更进一步,对有效的 root 用户保密。似乎通常这些可以由真正的根在运行时关闭。

另一种方法是限制获得完全不受限制的 root 的方式 - 例如,不允许远程连接的 root 用户进行所有访问,但需要从物理控制台登录。但是,这也不是我的目标 - 假设任何此类保护都已经被克服,并且根是尽可能合法的。

很明显,任何对机器有物理访问权限的人都可以将所有内容存储在硬盘上,也可能将所有内容存储在内存中。同样显而易见的是,如果 root 用户有权修改二进制文件或内核映像,那么在重新启动后就无法做出任何安全承诺。我只对无需重新启动系统即可完成的攻击感兴趣。

此外,在启动过程中,秘密很可能会通过许多地方传输,并且需要许多安全关键功能。如果在启动过程中也可以保护秘密当然很好,但对我来说,启动过程中的一个步骤就足够了,可以放弃提升的特权,之后就无法重新获得它们。

那么,有了这些限制,Linux 上有哪些方法可以防止完全 root 用户访问某些机密呢?

  • 文件系统上是否存在即使完全根用户也无法通过任何方式访问但某些进程可以访问的文件?一些当前正在运行的进程,甚至是由当前有权访问的进程启动的新进程?

  • 是否可以通过运行进程将机密保存在内存中,这样即使是完整的根也无法通过任何方式访问它们?这些秘密是否可以通过某种根无法影响的方式传输到新进程?

这是一个很难写的问题,所以我会得到与我相关的答案,所以我会在必要时尝试编辑这个问题,使其更具体。


需要限制的显而易见的事情是:

  • 禁止访问 /proc/mem

  • 禁止访问 /proc/<pid>/mem

  • 禁止访问 /proc/<pid>/fd/*

  • 禁用模块加载(最好仅在加载某些模块之后)

  • 禁用对任何进程的 ptrace 访问

4个回答

实际上,如果准备将这种限制定义为从根本上信任操作系统,则可以限制 root 这可以使用 SELinux(据我所知)和可能的其他此类系统来完成。我见过的以这种方式使用 SELinux 的最佳示例是 Russell Coker 的Play SELinux Machine

作为对其工作原理的简要概述,“root”这个名称在 Unix 中并不特殊。UID 0 是。UID 0 的意思是“相信我所说的一切”。这特别适用于在 Unices、Unixen 上使用的标准访问模型,或者您将“Unix”复数。

LSM 或 Linux 安全模块允许您连接几乎所有内容并根据您的需要审核/拒绝操作。对于 SELinux,SELinux 权限在 Unix 权限之后检查,因此您的流程如下所示:

Event ----> Has Unix Permissions? ---> Has SELinux Permissions? ---> Let it happen

下一个要了解的阶段是 SELinux 政策有不同的版本,或者在历史上曾经有过不同的版本。在我开始之前,先了解一下 SELinux:

  • inode 有类型,后缀为_t,也可以称为域;
  • 用户有角色,后缀为_r.

结合起来,它们控制给定角色中的用户可以执行的操作,以及给定域中的进程可以执行的操作。

现在,有三个主要的 SELinux 策略:

  1. 有针对性。这是 Fedora 等桌面的默认策略。目标的想法是关键系统服务和守护程序在域中运行,但您最终用户所做的很多事情都是在unconfined_u:unconfined_r:unconfined_t. 猜测这意味着什么没有奖品 - 如果 Unix 权限有效,SELinux 有效地传递。
  2. 严格的。该政策涉及unconfined_u完全删除。这不是一个简单的过程,尤其是在 Linux 桌面(即init 5)上。具体来说,X11 安全模型不是很好,并且通常需要unconfined_t某些应用程序。可以这样做,但我希望使用 X11 会更困难(尽管并非不可能),尤其是在执行需要 root 的 GUI 应用程序时。有一个项目正在进行中,以提供对 X 中类似 SELinux 的功能的支持,称为XACE(X 访问控制扩展)
  3. 职业棒球大联盟。MLS 代表多级安全性,表示权限字符串的结尾:user_u:system_r:httpd_content_t.s0-s2:c5-c7,即那些sc数字实际上意味着什么。具体来说,它们形成了不读取、不写入的设置,因此除非进程以特定级别运行,否则他们可以看到的信息将受到限制。这种信息级别的想法是保护机密资产——SELinux 最初是由 NSA 开发的,大概就是为了这个目的。

这就是你的背景。现在,根据网页(请参阅常见问题解答) ,播放机上的root是 UID 0 ;但是,root 设置为严格策略中以user_r而不是sysadm_r身份运行。这意味着将不允许用户从 shell 执行管理功能。

那么,有趣的是需要 root 的其他进程的状态。据推测,此类流程已被适当标记并具有允许它们访问所需访问的策略。那么问题就变成了您如何管理系统以及这些进程中的任何一个是否可以在该用户的上下文中启动一个 shell。如果发生这种情况,您仍然可以管理漏洞。

由于游戏机目前处于停机状态(在撰写本文时),我正在这里进行假设;但本质上,您需要一个在 sysadm_r 中运行并以 UID 0 作为攻击目标的进程。假设这样的过程存在并且可以利用,您仍然可以获取根。至于仍然能够通过 root 进行管理,我可以想到两个选项:

  • 要么存在某种受信任的过渡,这意味着 root 然后可以过渡到sysadm_r(不太安全)
  • 在不同的运行级别上,应用不同的策略,因此要管理机器,请将运行级别设置为 1,并且该策略不限制 root。我猜这里

概括

如果您的问题是“我现在可以轻松安全地执行此操作吗?” 答案是不。如果您的问题是“我准备好学习 SELinux,对我的发行版感到厌烦,忍受很多不工作的东西”,那么答案是可以比您的平均安装更多地限制 root。也就是说,这绝不会让您对漏洞利用无懈可击——它不会让用户无法在软件或物理上规避这种额外的访问控制。

所以是的,你可以让 root 看不到东西;然而,除了额外的技术负担,同样的警告适用于任何普通用户的任何访问控制设置——没有灵丹妙药。

哦,还有公然的自我推销:你可能会喜欢我关于在软件中存储秘密的博文。它在安全 stackexchange 博客上,所以我对推广它并不感到难过。本质上,正如您所看到的,有一些机制可以使攻击者(和您)的生活变得更加困难,但最终,这是一个“乌龟一路向下”的情况,即根本不可能做到。

以前,当一位希望在网站上的用户之间保持“私人消息”安全的客户联系时,我必须解决这个问题。在某些情况下可以保护某些数据,但这是相当有限的。

我的方法是简单地将便笺的加密版本存储在服务器上,并将其发送给他们(当然,一旦经过身份验证),然后完全在客户端解密。这意味着即使在服务器安全性(即 root 访问)完全妥协的情况下,笔记仍然是安全的。然而,这样做的局限性:

  • 受保护的数据仅在受到威胁之前是安全的,以后不会。根据用于加密信息的方法,有根服务器可能会诱使用户泄露解密密钥(JavaScript 注入,或对于本机 GUI 客户端,发布受感染的客户端更新)或以其他方式截获解密密钥(如果密钥是基于关闭与验证用户相同的方法,例如密码,它们可以在服务器端验证过程中被拦截)。
  • 传输需要完美的前向保密,否则加密的数据可能会被截获、存储,然后如上所述在泄露后解密。
  • 如果客户端也受到威胁,这不会保护任何东西。除非您完全在自己的脑海中处理加密数据(如果可以,您应该获得奖杯或其他东西),否则您将向某些东西提供敏感数据,并且没有什么是完全不妥协的。
  • 除非将可解密/明文元数据存储在旁边,否则无法在服务器端使用此数据(即用于索引目的),这可能会泄露其他信息。

从本质上讲,这限制了这种情况的潜在用途,并且仍然存在弱点,但它有可能在某些情况下工作。密码散列是“root 泄露保护”的一个(相当)成功的例子,因为即使是物理访问也不会泄露用户的密码(当然,除非该密码是在泄露后传输的)。

此线程中还有其他示例也值得研究,但请考虑客户端处理场景,将服务器仅用作安全存储服务。

TC

文件系统上是否存在即使完全根用户也无法通过任何方式访问但某些进程可以访问的文件?一些当前正在运行的进程,甚至是由当前有权访问的进程启动的新进程?

不,当一个进程可以访问它们时,root 也可以。如果你想做这样的事情,你将不得不对整个系统进行大量修改,可能是一个从某个只读设备引导不可变内核的系统,它拒绝 root 某些文件/内存访问,同时允许 root 可以访问的其他用户访问它们。冒充。

是否可以通过运行进程将机密保存在内存中,这样即使是完整的根也无法通过任何方式访问它们?这些秘密是否可以通过某种根无法影响的方式传输到新进程?

不。见上面的答案。

根据定义,您不能限制对 root 的访问。如果您限制 root 的访问权限,那么它就不再是 root 用户了。

如果我想拒绝对秘密的 root 访问,那么我会尝试隐藏它们。加密容器,可能隐藏在交换内存或其他地方,只能通过密码或其他某种隐写术访问。大海捞针很难,尽管并非不可能。

root 可以通过多种间接方式最终执行任意代码。您可以禁用它们,实际上某些安全框架可能会禁用它们,但它们会削弱 root 执行管理任务的能力。

例如,root 可以直接读写磁盘,绕过各种文件系统权限。您可以取消此功能,但在紧急情况下,root 将无法将完整的文件系统移动到新磁盘。

root 可以加载内核模块,从而可以做内核可以做的所有事情。您可以取消此功能,但随后会排除为热插拔媒体加载驱动程序。(这在 0.001% 的 unix 安装中可能是可取的,但这不是一般情况。)

Root 可以更新允许用户登录的可执行文件,例如loginsshd. 这些守护进程处理用户身份验证,因此如果您控制它们的代码,则可以注入后门。您可以取消此功能,但 root 将无法执行安全升级。

Root 可以创建和删除用户以及更改身份验证凭据:如果您可以编辑/etc/passwd以添加帐户,您还可以对其进行编辑以暂时使帐户无密码。您可以通过将某些文件设置为只读来删除此功能,即使对于 root,您也会得到一个在不重新启动的情况下无法创建或删除用户帐户的系统。

安全框架有效地创建了有限的 root 用户,这些用户仅在系统的一个子集中是 root ——仅在虚拟机中,而不是在“真实”系统中。这种受限的根失去了在真实系统上执行管理任务的可能性。我认为虚拟化是你所追求的。