为什么要求在非root +不允许特权升级的情况下将所有功能都丢弃在冗余的Kubernetes PodSecurityPolicy中?

时间:2018-11-15 21:23:34

标签: docker kubernetes containers linux-capabilities

PodSecurityPolicy documentation中的第二个示例策略由以下PodSecurityPolicy代码段组成

...
spec:
  privileged: false
  # Required to prevent escalations to root.
  allowPrivilegeEscalation: false
  # This is redundant with non-root + disallow privilege escalation,
  # but we can provide it for defense in depth.
  requiredDropCapabilities:
    - ALL
...

为什么为非root用户+不允许特权升级而放弃所有冗余功能?您可以拥有一个非root用户但没有有效权限的,没有特权升级的容器进程吗?

似乎这对Docker是不可能的:

$ docker run --cap-add SYS_ADMIN --user 1000 ubuntu grep Cap /proc/self/status
CapInh: 00000000a82425fb
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 00000000a82425fb
CapAmb: 0000000000000000

即使尝试显式添加所有有效功能,它们也会被删除。但是其他容器运行时也可以实现它,所以此注释仅适用于Docker吗?

2 个答案:

答案 0 :(得分:1)

  

为什么为非root用户+不允许特权升级而放弃所有冗余功能?

由于需要特权升级才能使用“新”功能,因此有效的allowPrivilegeEscalation: false会在execve系统调用中禁用setuid,从而阻止使用任何新功能。就像在文档中所示:“一旦设置了位,它就会在fork中继承, 克隆并执行,并且无法取消设置。” 。更多信息here。这与privileged: false结合使用会requiredDropCapabilities: [ALL]变得多余。

等效的Docker选项如下:

  • --user=whatever => privileged: false
  • --security-opt=no-new-privileges => allowPrivilegeEscalation: false
  • --cap-drop=all => requiredDropCapabilities: [ALL]
  

似乎这对于Docker是不可能的

这就是Docker所做的事情,即使您指定了CapEff: 0000000000000000,即使您指定了非特权用户,所有有效功能都将被丢弃(--cap-add SYS_ADMIN

此选项与--security-opt=no-new-privileges结合使用,使--cap-drop=all变得多余。

请注意,似乎docker的默认功能掩码包括SYS_ADMIN

$ docker run --rm ubuntu grep Cap /proc/self/status
CapInh: 00000000a80425fb
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
CapBnd: 00000000a80425fb
CapAmb: 0000000000000000
$ capsh --decode=00000000a82425fb
0x00000000a82425fb=cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_sys_admin,cap_mknod,cap_audit_write,cap_setfcap

为什么在没有指定任何00000000a82425fb选项的情况下--cap-add相同的原因。

  

但是其他容器运行时可以实现它,那么此注释仅适用于Docker吗?

我想,因此您可能会遇到privileged: falseallowPrivilegeEscalation: false无法有效禁用功能的情况,可以用requiredDropCapabilities:删除它。 (尽管如此,我不明白为什么另一个运行时会想要更改Docker行为)

答案 1 :(得分:0)

您的问题中有多个(好)子问题。
我想关注主要问题:

  

为什么为非root用户+不允许放弃所有冗余功能   特权升级?

为简化起见,我认为我们可以着重于禁止特权升级部分,只需询问:

当我们在PodSecurityPolicy中设置allowPrivilegeEscalation: false时,幕后会发生什么?

K8S docs中,您可以看到“ 此布尔值直接控制在容器进程上是否设置了no_new_privs标志”。

那么如果设置了此标志会发生什么呢?

kernel docs引述:”“设置此标志后,execve承诺不授予特权,以执行没有execve调用无法完成的任何事情。
例如,setuid和setgid位将不再更改uid或gid。文件功能不会添加到允许的集合中。”

换句话说,设置allowPrivilegeEscalation: false将导致所有功能被丢弃。

这就是为什么添加这部分被认为是多余的原因

 requiredDropCapabilities:
    - ALL

我希望这可以简化一些事情。

我认为其他问题的答案在已接受的答案中都非常清楚,而且我也没有补充。


注意:如果运行的内核> = 4.10,则可以在no_new_privs文件中的功能属性下查看线程的/proc/[pid]/status属性的值:

.
.
CapInh: 00000000a82425fb
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 00000000a82425fb
CapAmb: 0000000000000000
NoNewPrivs: 0 <-----
.
.