我正在 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
.
我现在已经试过了 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
如果我放在==
之前--print
,它现在显示Current: = cap_net_raw+i
,这样就解释了之前的错误,但不是为什么我们在切换出 root 时会失去能力,我认为这secure-keep-caps
应该解决这个问题。
从我所见,当 exec 被调用时,我失去了 Effective (e) 和 Permitted (p)。这是意料之中的,但我认为安全保持上限应该可以防止它们丢失。我是不是错过了什么。
我一直在做更多的研究,并再次阅读手册。似乎在以下情况下通常e
和p
功能会丢失:您从 user root
(或 apply secure-noroot
,从而使 root 成为普通用户)切换,这可以被覆盖secure-keep-caps
;当你打电话时exec
,据我所知,这是一个不变量。
据我所知,它是根据手册工作的。据我所知,没有办法对capsh
. 据我所知,要使用功能,您需要:使用文件功能或具有功能感知程序,该程序不使用exec
. 因此没有特权包装器。
所以现在我的问题是我错过了什么,是capsh
为了什么。
我添加了一个关于环境功能的答案。也许capsh
也可以与继承的功能一起使用,但要有用,这些需要在可执行文件上设置。我看不出 capsh 如何在没有环境功能的情况下做任何有用的事情,或者允许继承功能。
版本:
capsh
从包libcap2-bin
版本1:2.22-1.2
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
能力是过程的属性。传统上有三组:
以 root 身份运行的程序始终具有完全允许且有效的功能,因此“添加”更多功能不会产生明显影响。(可继承功能集通常为空。)setcap cap_net_raw+ep ping
默认情况下,您为运行此程序的任何用户启用这些功能。
不幸的是,这些功能绑定到执行的文件,并且在执行新的子进程后不会保留。Linux 4.3 引入了环境功能,允许子进程继承功能。(另请参见execve的()中转化的能力在功能(7) 。)
在使用功能时,请注意以下陷阱:
--keep=1
选项capsh
来避免清除集合。从 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)
提示:您可以--print
在capsh
命令行的任何位置添加该选项并查看其当前功能状态。
注意:cap_setpcap
需要--addamb
while选项cap_setuid,cap_setgid
需要--user
。
对 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_CAPS
,execve
非特权(无 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 个感兴趣的系统调用会导致重新计算(并可能丢弃)功能:
setuid
:根据man capabilities
:SECBIT_KEEP_CAPS 设置此标志允许具有一个或多个 0 UID 的线程在将其所有 UID 切换为非零值时保留其功能。如果未设置此标志,则此类 UIDswitch 会导致线程失去所有功能。
换句话说,在我们capsh
上面的命令中,我们需要确保在setuid
系统调用期间设置了SECBIT_KEEP_CAPS 。否则所有功能都将丢失。这就是它的--keep=1
作用。所以现在命令变成sudo capsh --user=<some_user> --keep=1 --
execve
:如果我们使用的--keep=1
选项,所有的能力集(有效的,允许的,可继承)将被保留,直到该execve
系统调用,但execve
会导致功能被重新计算(非root用户)的欢迎,并在一个不那么明显的方式。简而言之,在添加环境能力 set 之前,对于在execve
调用后处于线程“允许”集中的能力,要么:
setcap cap_net_raw+p /bin/bash
. 这样做会使整个练习变得毫无用处,因为线程的能力集(除了边界集)不再有任何影响。setcap cap_net_raw+i
会execve
奏效,但事实证明,当被非特权用户调用时,会导致线程的不可继承权限被删除(我们目前感谢setuid
)。所以作为非特权用户,没有办法满足这个条件。Linux 4.3 中引入的环境功能使线程可以保留其功能,即使是在setuid
非特权用户后跟一个 之后execve
,而不必依赖于文件功能。
内核中可能存在错误/功能。曾经有过一些讨论:
我不知道是否采取了任何措施来解决它。
不要误会我的意思 - 当前的行为是安全的。但它太安全了,以至于妨碍了看起来应该正常工作的事情。
编辑:根据http://man7.org/linux/man-pages/man7/capability.7.html,有一个新的功能集Ambient(自Linux 4.3起)。看起来这将允许我们需要的东西。
归档时间: |
|
查看次数: |
13584 次 |
最近记录: |