5

试图设置cap_setgid, cap_setuid, cap_setpcap.

#include <sys/types.h>
#include <sys/capability.h>

int main()
{
    cap_t caps;
    caps = cap_get_proc();
    cap_value_t cap_list[2];

    cap_list[0] = CAP_SETUID;
    cap_list[1] = CAP_SETGID;

    cap_set_flag(caps, CAP_EFFECTIVE, 2, cap_list, CAP_SET);
    cap_set_flag(caps, CAP_INHERITABLE, 2, cap_list, CAP_SET);
    cap_set_proc(caps);
    cap_free(caps);
    setgid(65534);
    setuid(65534);

    cap_get_proc();
    setgid(0);
    setuid(0);

    return 0;
}

执行在 root 用户下进行。跟踪程序显示了这一点

capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0
capset({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_SETGID|CAP_SETUID|CAP_SETPCAP}) = 0
setgid(65534)                           = 0
setuid(65534)                           = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, {0, 0, CAP_SETGID|CAP_SETUID|CAP_SETPCAP}) = 0
setgid(0)                               = -1 EPERM (Operation not permitted)
setuid(0)                               = -1 EPERM (Operation not permitted)
exit_group(0)                           = ?
+++ exited with 0 +++

权限已设置但不起作用。任何建议如何解决这个问题?

更新:prctl添加到代码

21a22
> prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
24a26
> cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_list, CAP_SET);

所以现在是

prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
setgid(65534);
setuid(65534);
cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_list, CAP_SET);

之后继承了setuid大写,手动设置的大写仍然存在,但没有解决问题

setgid(65534)                           = 0
setuid(65534)                           = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, {0, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_SETGID|CAP_SETUID|CAP_SETPCAP}) = 0
setgid(0)                               = -1 EPERM (Operation not permitted)
setuid(0)                               = -1 EPERM (Operation not permitted)
exit_group(0)                           = ?
+++ exited with 0 +++

UPDATE2:无法理解。我在 1st 之后添加了 2strs setuid,以检查上限。

printf("cape set %d\n", cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_list, CAP_SET));
printf("%s\n", cap_to_text(cap_get_proc(), NULL));

它回来了

catp set 0
=p cap_setgid,cap_setuid,cap_setpcap+i

未设置有效标志,但 cap_set_flag 返回 0

4

2 回答 2

12

默认情况下,能力集在 UID 转换过程中丢失;采用

prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);

保留允许的能力 ( cap_set_flag(caps, CAP_PERMITTED, ...))。请注意,有效能力集将被重置,但可以重新建立。


以下对我来说很好。

#include <sys/capability.h>
#include <sys/prctl.h>
#include <unistd.h>

int main(int argc, char **argv) {
    cap_value_t cap_values[] = {CAP_SETUID, CAP_SETGID};
    cap_t caps;

    caps = cap_get_proc();
    cap_set_flag(caps, CAP_PERMITTED, 2, cap_values, CAP_SET);
    cap_set_proc(caps);
    prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
    cap_free(caps);

    setgid(65534);
    setuid(65534);

    caps = cap_get_proc();
    cap_set_flag(caps, CAP_EFFECTIVE, 2, cap_values, CAP_SET);
    cap_set_proc(caps);
    cap_free(caps);

    setgid(0);
    setuid(0);

    return 0;
}
$ sudo strace ./a.out
...
capget({_ LINUX_CAPABILITY_VERSION_3,0},{CAP_CHOWN | CAP_DAC_OVERRIDE | CAP_DAC_READ_SEARCH | CAP_FOWNER | CAP_FSETID | CAP_KILL | CAP_SETGID | CAP_SETUID | CAP_SETPCAP | CAP_LINUX_IMMUTABLE | CAP_NET_BIND_SERVICE | CAP_NET_BROADCAST | CAP_NET_ADMIN | CAP_NET_RAW | CAP_IPC_LOCK | CAP_IPC_OWNER | CAP_SYS_MODULE | CAP_SYS_RAWIO | CAP_SYS_CHROOT | CAP_SYS_PTRACE | CAP_SYS_PACCT |CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP,CAP_CHOWN | CAP_DAC_OVERRIDE | CAP_DAC_READ_SEARCH | CAP_FOWNER | CAP_FSETID | CAP_KILL | CAP_SETGID | CAP_SETUID | CAP_SETPCAP | CAP_LINUX_IMMUTABLE | CAP_NET_BIND_SERVICE | CAP_NET_BROADCAST | CAP_NET_ADMIN | CAP_NET_RAW | CAP_IPC_LOCK | CAP_IPC_OWNER | CAP_SYS_MODULE | CAP_SYS_RAWIO | CAP_SYS_CHROOT | CAP_SYS_PTRACE | CAP_SYS_PACCT | CAP_SYS_ADMIN | CAP_SYS_BOOT | CAP_SYS_NICE | CAP_SYS_RESOURCE | CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0
capset({_ LINUX_CAPABILITY_VERSION_3,0},{CAP_CHOWN | CAP_DAC_OVERRIDE | CAP_DAC_READ_SEARCH | CAP_FOWNER | CAP_FSETID | CAP_KILL | CAP_SETGID | CAP_SETUID | CAP_SETPCAP | CAP_LINUX_IMMUTABLE | CAP_NET_BIND_SERVICE | CAP_NET_BROADCAST | CAP_NET_ADMIN | CAP_NET_RAW | CAP_IPC_LOCK | CAP_IPC_OWNER | CAP_SYS_MODULE | CAP_SYS_RAWIO | CAP_SYS_CHROOT | CAP_SYS_PTRACE | CAP_SYS_PACCT |CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP,CAP_CHOWN | CAP_DAC_OVERRIDE | CAP_DAC_READ_SEARCH | CAP_FOWNER | CAP_FSETID | CAP_KILL | CAP_SETGID | CAP_SETUID | CAP_SETPCAP | CAP_LINUX_IMMUTABLE | CAP_NET_BIND_SERVICE | CAP_NET_BROADCAST | CAP_NET_ADMIN | CAP_NET_RAW | CAP_IPC_LOCK | CAP_IPC_OWNER | CAP_SYS_MODULE | CAP_SYS_RAWIO | CAP_SYS_CHROOT | CAP_SYS_PTRACE | CAP_SYS_PACCT | CAP_SYS_ADMIN | CAP_SYS_BOOT | CAP_SYS_NICE | CAP_SYS_RESOURCE | CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0
prctl(PR_SET_KEEPCAPS, 1) = 0
setgid(65534) = 0
setuid(65534) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0
capget({_ LINUX_CAPABILITY_VERSION_3,0},{0,CAP_CHOWN | CAP_DAC_OVERRIDE | CAP_DAC_READ_SEARCH | CAP_FOWNER | CAP_FSETID | CAP_KILL | CAP_SETGID | CAP_SETUID | CAP_SETPCAP | CAP_LINUX_IMMUTABLE | CAP_NET_BIND_SERVICE | CAP_NET_BROADCAST | CAP_NET_ADMIN | CAP_NET_RAW | CAP_IPC_LOCK | CAP_IPC_OWNER | CAP_SYS_MODULE | CAP_SYS_RAWIO | CAP_SYS_CHROOT | CAP_SYS_PTRACE |CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0
capset({_ LINUX_CAPABILITY_VERSION_3,0},{CAP_SETGID | CAP_SETUID,CAP_CHOWN | CAP_DAC_OVERRIDE | CAP_DAC_READ_SEARCH | CAP_FOWNER | CAP_FSETID | CAP_KILL | CAP_SETGID | CAP_SETUID | CAP_SETPCAP | CAP_LINUX_IMMUTABLE | CAP_NET_BIND_SERVICE | CAP_NET_BROADCAST | CAP_NET_ADMIN | CAP_NET_RAW | CAP_IPC_LOCK | CAP_IPC_OWNER | CAP_SYS_MODULE | CAP_SYS_RAWIO | CAP_SYS_CHROOT |CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0
setgid(0) = 0
setuid(0) = 0
...
于 2012-08-28T06:33:01.383 回答
0

我认为您将 CAP_PERMITTED 集与 CAP_INHERITABLE 混淆了,除非您使用线程/exec,否则您想使用 CAP_PERMITTED。

可继承的(以前称为允许的):该集合与线程的可继承集合进行“与”运算,以确定在 execve(2) 之后线程的允许集合中启用了哪些可继承能力

至于update2:尝试在之前/之后打印出来,并考虑和cap_to_text(cap_get_proc())之间有什么区别。cap_set_flagcap_set_proc

于 2018-09-27T20:56:05.247 回答