如何执行一个进程,在缺失基于文件系统的特权情况下保留特权?

6
我希望使系统可用,而不需要使用setuid、文件"+p"功能,通常情况下也不需要使用在设置PR_SET_NO_NEW_PRIVS时禁用的东西。

采用这种方法(init设置了PR_SET_NO_NEW_PRIVS且基于文件系统的能力提升不再可能),您无法“重新填充”您的能力,只需小心不要“溅”它们即可。

如何在不“溅”任何授予的能力的情况下execve其他进程(例如,如果新程序的文件是setcap =ei)?只需像“我信任这个新进程一样信任自己”一样。例如,向一个用户授予一个能力(并且该用户希望在启动的任何程序中行使该能力)...

我可以让整个文件系统永久地=ei吗?我希望保持文件系统不干扰该方案,不能授予或撤销能力;通过父->子关系来控制所有内容。


请问您能否澄清一下,您在标题中写道“尽管缺少文件功能”,但在问题中又说您想要使用此功能并将整个文件的功能位设置为ei。那么这个功能在您的系统中是否存在? - Étienne
文件系统的能力不允许对用户刚编译的文件使用 +i,但我们仍希望用户能够使用此功能。使用 +i 获取能力只能作为进程(用户的)+i 和文件系统的+ i 之间的交集。如果没有文件系统的竞争(没有 +p 和没有 +i),我无法运行其他可执行文件以保留我已经拥有的有效能力。这会产生差异(例如,可以加载将使用我的能力的动态库,但是该库无法生成进程而不失去能力)。 - Vi.
所以它是在工作,但不是你预期的那样。 - ctrl-alt-delor
3个回答

3
我并不是在建议你做什么,但以下是相关内容。
从手册中提取,有一些变化。根据它:fork 不会改变能力。而且现在Linux内核4.3中增加了环境集合,看起来这正是你所尝试的。
   Ambient (since Linux 4.3):
          This is a set of capabilities that are preserved across an execve(2) of a program that is not privileged.  The ambient capability set obeys the invariant that no capability can ever
          be ambient if it is not both permitted and inheritable.

          The ambient capability set can be directly modified using
          prctl(2).  Ambient capabilities are automatically lowered if
          either of the corresponding permitted or inheritable
          capabilities is lowered.

          Executing a program that changes UID or GID due to the set-
          user-ID or set-group-ID bits or executing a program that has
          any file capabilities set will clear the ambient set.  Ambient
          capabilities are added to the permitted set and assigned to
          the effective set when execve(2) is called.

   A child created via fork(2) inherits copies of its parent's
   capability sets.  See below for a discussion of the treatment of
   capabilities during execve(2).

Transformation of capabilities during execve()
   During an execve(2), the kernel calculates the new capabilities of
   the process using the following algorithm:

       P'(ambient) = (file is privileged) ? 0 : P(ambient)

       P'(permitted) = (P(inheritable) & F(inheritable)) |
                       (F(permitted) & cap_bset) | P'(ambient)

       P'(effective) = F(effective) ? P'(permitted) : P'(ambient)

       P'(inheritable) = P(inheritable)    [i.e., unchanged]

   where:

       P         denotes the value of a thread capability set before the
                 execve(2)

       P'        denotes the value of a thread capability set after the
                 execve(2)

       F         denotes a file capability set

       cap_bset  is the value of the capability bounding set (described
                 below).

   A privileged file is one that has capabilities or has the set-user-ID
   or set-group-ID bit set.

在我的工具dived中实现设置环境能力。 - Vi.
@vi,您能否再用完整的句子重复一遍? - ctrl-alt-delor
我四处寻找一种工具,可以实验环境能力,但是没有找到(特别是在Debian Stable上)。因此,我将另一个选项添加到我的自己的工具“dive”中。为了帮助其他想玩弄环境能力而不必等待适当的工具和库赶上的用户,我决定在相关的地方发布一个链接。这个回答让我对这个功能有了更深入的了解,看起来就像这个相关的地方。 - Vi.

3
目前还没有简单的方法来实现这一点,如果您参考功能手册:
During an execve(2), the kernel calculates the new capabilities of the process
using the following algorithm:

P'(permitted) = (P(inheritable) & F(inheritable)) | (F(permitted) & cap_bset)

P'(effective) = F(effective) ? P'(permitted) : 0 

P'(inheritable) = P(inheritable)    [i.e., unchanged]

where:

P        denotes the value of a thread capability set before the execve(2)
P'       denotes the value of a capability set after the execve(2)
F        denotes a file capability set
cap_bset is the value of the capability bounding set 

如果您想要执行的文件没有设置fP位或其fI位未设置,则您的进程将没有允许权限,因此也没有有效权限。
设置整个文件系统的允许和继承位是技术上可行的,但这并没有多大意义,因为它会极大地降低系统的安全性。(编辑:正如您提到的,这对于新的可执行文件也不起作用)。
确实可以使用pam_cap为用户提供一些功能,但不能让他们使用刚编译的任何文件。按设计,功能是为程序而不是为用户提供权力的,您可以在Hallyn's paper中阅读:

关键洞察是观察到特权由程序而不是人员行使。也就是说,在计算机中完成的所有工作都是通过代理-程序-完成的,只有这些程序知道如何处理特权,才能信任它们行使特权。

另请参见POSIX draft 1003.1e,其中定义了POSIX功能,第310页:

在一个过程链(一个单一进程内的程序序列)中建立一组保持不变且在整个链的生命周期内处于活动状态的能力是不合适的。[...] 这是最小权限原则的应用,同样适用于用户和进程。

最近(2012年12月),有人在this Linux内核邮件列表上要求介绍将您想要做的内容作为功能引入,给出了一些非常有趣的答案。一些人认为,在跨exec的继承规则中放弃文件能力会引入一些安全问题,并且能力并未为此功能设计,尽管没有说明它会引入哪些安全问题:

目前唯一的方法是修改Linux内核中能力的继承方式(需要修改两个文件,在3.7内核上测试成功),但如上所述,这是否安全还不清楚。

在旧内核(2.6.33之前)中,有一种编译选项可以不包含文件的功能 (CONFIG_SECURITY_FILE_CAPABILITIES),但我怀疑使用这样一个古老的内核对你来说可能不是一个选择。

设置整个文件系统的有效位或者为/lib/ld-linux*设置它将严重降低系统安全性。但是如果您监控获取 +i 的进程,则不应如此。它将“授予权限给程序”转变为“授予权限给用户”,即用户可以编译和启动任何行使该特权的程序。 - Vi.
您不能直接将能力授予用户,您能详细描述一下您想要实现什么吗?为什么不想从您的 shell 设置文件能力,然后只允许您信任的用户运行此 shell?您是想编写一个程序吗?还是想黑进内核? - Étienne
允许用户仅对任何程序(包括他刚编译的程序)使用CAP_NET_BIND_SERVICE。可以使用PAM为该用户设置CAP_NET_BIND_SERVICE+i。hacky解决方法涉及为/lib/ld-linux.so.2设置+i。 - Vi.
但这正是你想做的事情,不是吗? - Étienne
目前这是不可能的,请阅读我提供的内核邮件列表讨论,他们将trusted_execve称为SECURE_CAP_INHERITANCE - Étienne
显示剩余8条评论

0

我认为(我的理解),使用能力的最佳方式是:

对于需要能力且可信的程序,包括被信任不会泄露能力的程序,例如 WireShark 的数据包嗅探部分、需要监听 80 端口的 Web 服务器。
- 新程序,能力感知:设置允许。 - 旧程序,不能感知能力:设置允许和有效。
对于将泄露能力并且代码可能(有时)使用能力的程序:设置继承。
- 例如,对于 chmod,设置继承 CAP_FOWNER,如果用户需要超级权限(通常由 root 持有),则需要使用 setpriv(或等效项,这可以合并到 sudo 中),否则它将在非特权模式下运行。
当进程需要 fork 并共享一些能力时,只有在这种情况下使用 ambient。可能是相同的可执行文件;如果是另一个文件,则该文件上将设置允许或继承。[编辑:我刚意识到如果您不执行,则不需要 ambient。如果我想到了在良好设置的系统中使用 ambient 的用例,我会在此添加。Ambient 可以用作过渡机制,当未在可能使用它的文件上设置继承时。]

ambient 的用途:

  • 在文件没有正确的权限的系统上使用(一种过渡技术)。
  • 对于无法拥有权限的 shell 脚本(因为它们不能具有 setuid),除非在已修复并允许脚本 setuid 的系统上。
  • 在此添加更多内容。

1
s/leek/leak/? - Vi.
环境能力可以用来取消“仅限根用户使用小于1024的端口”规则,例如。或将网络设置代码分解为一个shell脚本,而不在/bin/sh上设置任何位。或者当文件系统愚蠢且没有扩展属性时。 - Vi.
@Vi 我按照你说的做了。顺便说一下,s/[?]/g/ - ctrl-alt-delor
@Vi,你说得很对,我没有看到的是:启动shell脚本的环境。至于你的第一个观点,如果需要监听<1024端口,则在可执行文件上设置适当的继承位。sudo/setpriv或者无论何时被调用,都可以默认查看已设置的继承位,并将它们设置为激活状态(或者对于脚本使用ambient)。 - ctrl-alt-delor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接