如何使用 capsh:我正在尝试以最少的功能运行无特权的 ping

ctr*_*lor 24 capabilities

我正在 Debian Gnu/Linux 上试验功能。

我已将 /bin/ping 复制到我当前的工作目录。正如预期的那样,它不起作用,它最初是 setuid root。

然后,我通过执行 来为我的 ping 提供最小的功能(不是 root)sudo /sbin/setcap cap_net_raw=ep ./ping,并且我的 ping 可以正常工作。

然后sudo /sbin/setcap -r ./ping撤销那个能力。它现在没有按预期工作。

我现在尝试使用capsh.

capsh 没有权限,所以我需要以 root 身份运行它,然后删除 root 并因此删除所有其他权限。

我想我也需要secure-keep-caps,这在 中没有记录capsh,但在能力手册中。我从/usr/include/linux/securebits.h. 它们看起来是正确的,因为输出--print显示这些位是正确的。

我已经摆弄了几个小时,到目前为止我有这个。

sudo /sbin/capsh --keep=1 --secbits=0x10 --caps="cap_net_raw+epi" == --secbits=0x10 --user=${USER} --print -- -c "./ping localhost"

但是ping有错误ping: icmp open socket: Operation not permitted,这是当它没有能力,会发生什么。也--print说明了Current: =p cap_net_raw+i,这还不够我们需要e

sudo /sbin/capsh --caps="cap_net_raw+epi" --print -- -c "./ping localhost"将能力设置为Current: = cap_net_raw+eip这是正确的,但让我们成为root.

编辑-1

我现在已经试过了 sudo /sbin/capsh --keep=1 --secbits=0x11 --caps=cap_net_raw+epi --print -- -c "touch zz; ./ping -c1 localhost;"

这产生:

touch: cannot touch `zz': Permission denied
ping: icmp open socket: Operation not permitted
Run Code Online (Sandbox Code Playgroud)

第一个错误预期为secure-noroot: yes 但第二个不是Current: = cap_net_raw+eip

编辑-2

如果我放在==之前--print,它现在显示Current: = cap_net_raw+i,这样就解释了之前的错误,但不是为什么我们在切换出 root 时会失去能力,我认为这secure-keep-caps应该解决这个问题。

编辑-3

从我所见,当 exec 被调用时,我失去了 Effective (e) 和 Permitted (p)。这是意料之中的,但我认为安全保持上限应该可以防止它们丢失。我是不是错过了什么。

编辑-4

我一直在做更多的研究,并再次阅读手册。似乎在以下情况下通常ep功能会丢失:您从 user root(或 apply secure-noroot,从而使 root 成为普通用户)切换,这可以被覆盖secure-keep-caps;当你打电话时exec,据我所知,这是一个不变量。

据我所知,它是根据手册工作的。据我所知,没有办法对capsh. 据我所知,要使用功能,您需要:使用文件功能或具有功能感知程序,该程序不使用exec. 因此没有特权包装器。

所以现在我的问题是我错过了什么,是capsh为了什么。

编辑-5

我添加了一个关于环境功能的答案。也许capsh也可以与继承的功能一起使用,但要有用,这些需要在可执行文件上设置。我看不出 capsh 如何在没有环境功能的情况下做任何有用的事情,或者允许继承功能。


版本:

  • capsh从包libcap2-bin版本1:2.22-1.2
  • 在 edit-3 之前,我capsh从中获取了最新版本git://git.debian.org/collab-maint/libcap2.git并开始使用它。
  • uname -a Linux richard-laptop 3.2.0-4-amd64 #1 SMP Debian 3.2.65-1+deb7u2 x86_64 GNU/Linux 用户空间是 32 位。

Lek*_*eyn 19

能力是过程的属性。传统上有三组:

  • 允许的能力(p):在当前进程中可能被“激活”的能力。
  • 有效能力(e):当前流程中当前可用的能力。
  • 可继承能力 ( i ):可继承的文件能力。

以 root 身份运行的程序始终具有完全允许且有效的功能,因此“添加”更多功能不会产生明显影响。(可继承功能集通常为空。)setcap cap_net_raw+ep ping默认情况下,您为运行此程序的任何用户启用这些功能。

不幸的是,这些功能绑定到执行的文件,并且在执行新的子进程后不会保留。Linux 4.3 引入了环境功能,允许子进程继承功能。(另请参见execve的()中转化的能力功能(7) 。)

在使用功能时,请注意以下陷阱:

  • 将用户从 root 更改为非 root 时,将清除有效和允许的功能(请参阅功能用户 ID 更改对功能的影响(7))。您可以使用--keep=1选项capsh来避免清除集合。
  • 更改用户或组 ID 时会清除环境功能集。解决方案:更改用户 ID 之后,但执行子进程之前添加环境功能。
  • 如果一个能力已经在允许和可继承的能力集中,那么它只能被添加到环境能力集中。

从 libcap 2.26 开始,该capsh程序获得了通过诸如--addamb( commit ) 之类的选项来修改环境功能的能力。请注意,选项顺序很重要。用法示例:

sudo capsh --caps="cap_net_raw+eip cap_setpcap,cap_setuid,cap_setgid+ep" \
    --keep=1 --user=nobody --addamb=cap_net_raw -- \
    -c "./ping -c1 127.0.0.1"
Run Code Online (Sandbox Code Playgroud)

提示:您可以--printcapsh命令行的任何位置添加该选项并查看其当前功能状态。

注意:cap_setpcap需要--addambwhile选项cap_setuid,cap_setgid需要--user


JP *_*oad 9

对 Lekensteyn 的答案进行轻微调整,可以缩短最近内核的调用时间:

sudo /usr/sbin/capsh --keep=1 --user=$USER \
  --inh=cap_net_raw --addamb=cap_net_raw -- \
  -c './ping -c1 localhost'
Run Code Online (Sandbox Code Playgroud)

注意:根据您的 sudoers 文件,这可能会使您的环境变得混乱(例如更改 HOME)。capsh 会更改您的 uid,但不会执行任何操作来恢复 sudo 的环境更改。

那么这是怎么回事呢?我们来看一下:

  • sudo /usr/sbin/capsh:我们从 root 开始,它在其有效(可以执行此操作)和允许(可以将其添加到有效)集中具有所有功能,但在其他集中没有任何功能。我们稍后将讨论其他集合。
  • --keep=1:出于安全(读取:遗留)原因,功能通常不会跨根->非根 ID 交换机继承。该标志启用了一项称为 的功能SECBIT_KEEP_CAPS,可以实现此目的。值得注意的是,它会在 exec 时自动清除,这是一个好主意。
  • --user=$USER:既然我们不会失去 UID 更改的所有功能,我们就退出 root 状态。感谢SECBIT_KEEP_CAPS,我们保留了类似 root 的权限,这让我们进一步混乱了我们的能力。
  • --inh=cap_net_raw:这会将我们的目标功能添加到可继承集中,因为如果功能不可继承,则无法将其设置为环境功能(请参阅下一项)。
  • --addamb=cap_net_raw:即使我们已经请求SECBIT_KEEP_CAPSexecve非特权(无 setuid/setgid/setcap)二进制文件仍然会清除我们的功能,导致没有特权。Linux 4.3 添加了环境集,在执行非特权二进制文件时,该环境集会添加回有效集和允许集。完美的!
  • -- -c ...:设置完所有内容后,我们使用这些参数执行 bash。功能集被清除(因为 bash 没有特权),环境集被添加回来,瞧!我们拥有打开原始套接字所需的权限。

您可以使用 capsh 的特殊==参数来检查这一点,这会导致它使用命令行的其余部分执行自身:

sudo /usr/sbin/capsh --keep=1 --user=$USER \
  --inh=cap_net_raw --addamb=cap_net_raw == --print

Current: = cap_net_raw+eip
Run Code Online (Sandbox Code Playgroud)

这意味着我们将 cap_net_raw 视为有效(可以执行)、可继承(可以将其传递给子进程)和允许(允许获取)。其中没有任何其他功能。

有关功能及其工作方式的更多信息,最好的选择是功能(7)手册页。具体是标题Transformation of capabilities during execve()


小智 6

Lekensteyn 的回答似乎准确且完整,但我将尝试从不同的角度提供另一种解释,尝试强调环境功能集解决的问题。

运行时sudo capsh --user=<some_user> --有 2 个感兴趣的系统调用会导致重新计算(并可能丢弃)功能:

  1. setuid:根据man capabilities

SECBIT_KEEP_CAPS 设置此标志允许具有一个或多个 0 UID 的线程在将其所有 UID 切换为非零值时保留其功能。如果未设置此标志,则此类 UIDswitch 会导致线程失去所有功能。

换句话说,在我们capsh上面的命令中,我们需要确保在setuid系统调用期间设置了SECBIT_KEEP_CAPS 。否则所有功能都将丢失。这就是它的--keep=1作用。所以现在命令变成sudo capsh --user=<some_user> --keep=1 --

  1. execve:如果我们使用的--keep=1选项,所有的能力集(有效的,允许的,可继承)将被保留,直到execve系统调用,但execve会导致功能被重新计算(非root用户)的欢迎,并在一个不那么明显的方式。简而言之,在添加环境能力 set 之前,对于在execve调用后处于线程“允许”集中的能力,要么:

    • 该文件必须在其“允许的”集合中具有该功能。这可以通过setcap cap_net_raw+p /bin/bash. 这样做会使整个练习变得毫无用处,因为线程的能力集(除了边界集)不再有任何影响。
    • 文件和线程都必须在其“可继承的”集合中具有该功能。您可能认为这setcap cap_net_raw+iexecve奏效,但事实证明,当被非特权用户调用时,会导致线程的不可继承权限被删除(我们目前感谢setuid)。所以作为非特权用户,没有办法满足这个条件。

Linux 4.3 中引入的环境功能使线程可以保留其功能,即使是在setuid非特权用户后跟一个 之后execve而不必依赖于文件功能。


ctr*_*lor 2

内核中可能存在错误/功能。曾经有过一些讨论:

我不知道是否采取了任何措施来解决它。

不要误会我的意思 - 当前的行为是安全的。但它太安全了,以至于妨碍了看起来应该正常工作的事情。

编辑:根据http://man7.org/linux/man-pages/man7/capability.7.html,有一个新的功能集Ambient(自Linux 4.3起)。看起来这将允许我们需要的东西。