使用 capsh 重现 setcap 行为

使用 capsh 重现 setcap 行为

有一个非能力感知程序至少需要 1)cap_sys_admin和 2)cap_dac_overridecap_dac_read_search。这可以证明如下:

sudo setcap 'all=ep cap_sys_admin-ep' ./binary`                        # ./binary doesn't work
sudo setcap 'all=ep cap_dac_override-ep' ./binary`                     # ./binary works
sudo setcap 'all=ep cap_dac_read_search-ep' ./binary                   # ./binary works
sudo setcap 'all=ep cap_dac_override,cap_dac_read_search-ep' ./binary  # ./binary doesn't work

capsh我想使用而不是进行相同的检查setcap。在进行这些检查之前,将使用 删除所有文件功能sudo setcap -r ./binary。第一棵树成功,结果匹配setcap

sudo capsh --user=jdoe --keep=1 --caps="all=eip" --addamb="all" --delamb="cap_sys_admin" -- -c ./binary
sudo capsh --user=jdoe --keep=1 --caps="all=eip" --addamb="all" --delamb="cap_dac_override" -- -c ./binary
sudo capsh --user=jdoe --keep=1 --caps="all=eip" --addamb="all" --delamb="cap_dac_read_search" -- -c ./binary

最后一个失败了,程序仍然可以运行,但它不应该运行:

sudo capsh --user=jdoe --keep=1 --caps="all=eip" --addamb="all" --delamb="cap_dac_override,cap_dac_read_search" -- -c ./binary

文件系统和进程功能之间是否存在我没​​有注意到的差异?如何正确编写第三个测试?

答案1

所以我认为你的问题的答案在于你的程序正在做什么。 (一般来说,最好在您的问题中提供一些简化的源代码来重现您所看到的内容。)

我很快就编写了一些代码(在 Go 中,因为它生成调试输出的代码比 C 和libcap,它提供了一个工作示例cap去包)。

这是binary.go

package main

import (
    "log"
    "os"

    "kernel.org/pub/linux/libs/security/libcap/cap"
)

func confirm(c *cap.Set, val cap.Value) int {
    on, err := c.GetFlag(cap.Effective, val)
    if err != nil {
        log.Fatalf("unable to confirm %q in effective set: %v", val, err)
    }
    log.Printf("%q in effective set of %q is: %v", val, c, on)
    if on {
        return 0
    }
    return 1
}

func fail() {
    log.Print("FAILURE")
    os.Exit(1)
}

func main() {
    c := cap.GetProc()
    if confirm(c, cap.SYS_ADMIN) != 0 {
        fail()
    }
    if confirm(c, cap.DAC_OVERRIDE)+confirm(c, cap.DAC_READ_SEARCH) > 1 {
        fail()
    }
    log.Print("SUCCESS")
}

编译如下:

$ go mod init binary
$ go mod tidy
$ go build binary.go
$ ./binary 
2022/09/10 16:45:56 "cap_sys_admin" in effective set of "=" is: false
2022/09/10 16:45:56 FAILURE
$ echo $?
1

该程序binary具有您所描述的所有属性,并且按照您期望的方式工作。文件功能版本和周围的继承版本(使用的版本capsh)有可继承现有的工艺能力:

$ sudo setcap 'all=ep cap_dac_override,cap_dac_read_search-ep' ./binary
$ ./binary 
2022/09/10 16:50:37 "cap_sys_admin" in effective set of "=ep cap_dac_override,cap_dac_read_search-ep" is: true
2022/09/10 16:50:37 "cap_dac_override" in effective set of "=ep cap_dac_override,cap_dac_read_search-ep" is: false
2022/09/10 16:50:37 "cap_dac_read_search" in effective set of "=ep cap_dac_override,cap_dac_read_search-ep" is: false
2022/09/10 16:50:37 FAILURE
$ sudo setcap -r binary
$ sudo capsh --user=$(whoami) --keep=1 --caps="all=eip" --addamb="all" --delamb="cap_dac_override,cap_dac_read_search" -- -c ./binary
2022/09/10 16:52:21 "cap_sys_admin" in effective set of "=eip cap_dac_override,cap_dac_read_search-ep" is: true
2022/09/10 16:52:21 "cap_dac_override" in effective set of "=eip cap_dac_override,cap_dac_read_search-ep" is: false
2022/09/10 16:52:21 "cap_dac_read_search" in effective set of "=eip cap_dac_override,cap_dac_read_search-ep" is: false
2022/09/10 16:52:21 FAILURE

也就是说,您"=ep"在文件功能版本"=eip"周围的一。该".i."部分不是对程序直接有用的功能,它仅在程序执行时发挥作用。

我认为你的代码可能正在检查可继承工艺能力。再说一次,这些是不是自己的特权。它们仅在与文件结合时才代表特权可继承能力,或周围的能力。我已经完整地写了能力继承如何在libcap分销网站。如果所有这些内容仍然令人困惑,那么那里的示例可能会有所帮助。

相关内容