首页 > 编程知识 正文

docker提权,比docker更好的容器

时间:2023-05-05 23:45:49 阅读:106121 作者:3237

集装箱的安全性是一个很大的话题,集装箱的安全性在很大程度上是由集装箱的体系结构特性决定的。 例如,容器与宿主机共享Linux内核,通过Namespace进行资源隔离。通过 shim/runC 的方式来启动等等。

这些容器体系结构的特性是,选择使用容器后,作为使用容器的用户,不太有能力安全地更改体系结构这个级别。 你可能会说使用Kata Container、gVisor是安全的“容器”。 但是,Kata和gVisor只是与容器接口标准兼容,内部实现是完全不同的技术。

那么,对于使用容器的用户,在运行容器时,在安全方面能做什么呢? 我们主要可以从这两个方面来考虑:

3358 www.Sina.com/http://www.Sina.com /为什么是这两点呢? 我通过两个故事的内容和你讨论,这个故事我们先来看看容器capabilities的问题。

问题的再现

刚使用容器的同学往往会发现,用默认的docker run启动容器后,容器不允许执行许多操作,即使以root用户运行程序也不行。

下面的例子来再现这个问题吧。 运行make image以创建容器镜像,然后运行以下脚本:

# docker run-- name iptables-itregistry/iptables : v1 bash [ root @ 0b88d 6486149/] # iptables-liptablesv1.8.4 () name iptables-liptablesv 1.8.4 3360 couldnotfetchrulesetgenerationid 3360 permission denied 现在,我想通过在容器上运行iptables命令来查看防火墙规则。 但是,运行命令时,结果输出将显示错误消息“permissiondenied(youmustberoot )”,并要求以root用户身份运行。

但是,在容器中,我们现在以root用户的身份运行。 为什么不能运行“iptables”命令呢?

你一定会想,是不是在容器里又做了别的权限。 如果您查看资料,就会发现启动容器中有“privileged”参数。 试着使用这个参数吧。 是的。 使用此参数后,iptables命令成功执行。

# docker stop iptables; dockerrmiptablesiptablesiptables # docker run---name iptables---privileged-itregistry/iptables 3360 v1 bash [ root ] iptables-lchaininput (策略访问) targetprotoptsourcedestinationchainforward (策略访问) )。 在target prot opt source destinationchainoutput (policy accept ) targetprotoptsourcedestination中,问题看起来像是通过使用配置参数解决的,而且似乎很简单。 但是,现在让我们考虑一下,用“privileged”参数解决问题不是一个合理的方法吗? 用那个有什么问题吗?

要回答这些问题,请先理解“privileged”是什么意思吧。 从Docker的代码中可以看到,放置privileged的参数将检索所有capabilities。 什么是capabilities呢?

ifec.privileged { p.capabilities=caps.getallcapabilities ()基本概念Linux capabilities

有关Linux capabilities的定义,请参考《Linux程序手册》中的Linux capabilities说明。

在Linux capabilities出现之前,进程权限简单地分为两类。 第一个是特权用户进程(进程的有效用户ID为0,简单来说,可以将其视为root用户的进程),第二个是非特权用户的进程)进程的有效用户ID为0,非root用户

第一是赋予容器合理的 capabilities其实这个概念也是我

们通常对 Linux 中 root 用户与非 root 用户的理解。

从 kernel 2.2 开始,Linux 把特权用户所有的这些“特权”做了更详细的划分,这样被划分出来的每个单元就被称为 capability。 

所有的 capabilities 都在Linux capabilities的手册列出来了,你也可以在内核的文件capability.h中看到所有 capabilities 的定义。

对于任意一个进程,在做任意一个特权操作的时候,都需要有这个特权操作对应的 capability。

我还要提醒你的是,CAP_SYS_ADMIN 这个 capability 里允许了大量的特权操作,包括文件系统,交换空间,还有对各种设备的操作,以及系统调试相关的调用等等。

在普通 Linux 节点上,非 root 用户启动的进程缺省没有任何 Linux capabilities,而 root 用户启动的进程缺省包含了所有的 Linux capabilities。 

我们可以做个试验,对于 root 用户启动的进程,如果把 CAP_NET_ADMIN 这个 capability 移除,看看它是否还可以运行 iptables。

在这里我们要用到capsh这个工具,对这个工具不熟悉的同学可以查看超链接。接下来,我们就用 capsh 执行下面的这个命令:

# sudo /usr/s文静的咖啡/capsh --keep=1 --user=root --drop=cap_net_admin -- -c './iptables -L;sleep 100'Chain INPUT (policy ACCEPT)target prot opt source destination Chain FORWARD (policy ACCEPT)target prot opt source destination Chain OUTPUT (policy ACCEPT)target prot opt source destinationiptables: Permission denied (you must be root).

 这时候,我们可以看到即使是 root 用户,如果把"CAP_NET_ADMIN"给移除了,那么在执行 iptables 的时候就会看到"Permission denied (you must be root)."的提示信息。

同时,我们可以通过 /proc 文件系统找到对应进程的 status,这样就能确认进程中的 CAP_NET_ADMIN 是否已经被移除了。

# ps -ef | grep sleeproot 22603 22275 0 19:44 pts/1 00:00:00 sudo /usr/s文静的咖啡/capsh --keep=1 --user=root --drop=cap_net_admin -- -c ./iptables -L;sleep 100root 22604 22603 0 19:44 pts/1 00:00:00 /文静的咖啡/bash -c ./iptables -L;sleep 100 # cat /proc/22604/status | grep CapCapInh: 0000000000000000CapPrm: 0000003fffffefffCapEff: 0000003fffffefffCapBnd: 0000003fffffefffCapAmb: 0000000000000000

运行上面的命令查看 /proc//status 里 Linux capabilities 的相关参数之后,我们可以发现,输出结果中包含 5 个 Cap 参数。

这里我给你解释一下, 对于当前进程,直接影响某个特权操作是否可以被执行的参数,是"CapEff",也就是"Effective capability sets",这是一个 bitmap,每一个 bit 代表一项 capability 是否被打开。

在 Linux 内核capability.h里把 CAP_NET_ADMIN 的值定义成 12,所以我们可以看到"CapEff"的值是"0000003fffffefff",第 4 个数值是 16 进制的"e",而不是 f。

这表示 CAP_NET_ADMIN 对应的第 12-bit 没有被置位了(0xefff = 0xffff & (~(1 << 12))),所以这个进程也就没有执行 iptables 命令的权限了。

对于进程 status 中其他几个 capabilities 相关的参数,它们还需要和应用程序文件属性中的 capabilities 协同工作,这样才能得到新启动的进程最终的 capabilities 参数的值。

我们看下面的图,结合这张图看后面的讲解:

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。