有一个非能力感知程序至少需要 1)cap_sys_admin
和 2)cap_dac_override
或cap_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
分销网站。如果所有这些内容仍然令人困惑,那么那里的示例可能会有所帮助。