百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程文章 > 正文

【容器安全篇】原来root在容器里也不是万能的

qiyuwang 2024-11-03 16:32 11 浏览 0 评论

在启动容器时,一般都是通过 docker run 来启动容器,但在容器里有很多操作是不被允许的,即使使用的是root用户,这一点在刚开始接触容器时,经常会有疑惑。为什么已经是root了,但还是会报错呢?

问题现象

现有一个iptables环境的Dockerfile,创建镜像 iptables:v1

FROM centos:7.6.1810

RUN yum install -y iptables

启动容器

docker run -d --name iptables-test iptables:v1

进入容器测试

docker exec -it iptables-test /bin/bash
[root@master iptables-test]# id
uid=0(root) gid=0(root) 组=0(root)
[root@346430e4132e /]# iptables -L
iptables v1.4.21: can't initialize iptables table `filter': Permission denied (you must be root)

这里提示,权限不够,需要使用root用户。

但当我们使用以下启动容器时

[root@master home]# docker run --name iptables-test --privileged -it iptables:v1 bash
[root@29b21ccce0ac /]# iptables -L
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               destination 

这时发现可以正常使用iptables的操作了,和前面的操作唯一的差异在 --privileged

--privileged代表使用真正root权限的账号,默认情况下,Docker在启动容器时,它的权限是有限制的,即使是使用root,也是会被docker进行限制,而这个限制就是依赖于 linux capabilities。

linux capabilities

linux capabilities 是在 Linux 2.2 之后出现的,在这之前进程的权限可以分成两类:特权用户和非特权用户。

特权用户可以简单理解为 root ,可以执行系统的所有操作;非特权用户可以理解为 非root用户,会被linux 内核进行限制,如果普通用户需要使用到root的一些权限,则需要通过SUID的方式进行处理,但这会带一些安全问题。

在 linux 2.2 之后,将特权用户的权限更加细化,被划分成几个部分,每一个部分就是 capabilities。每一个进程在需要进行做一个特权操作时,它就需要有这个特权操作的授权。常用的特权如下表(具体列表请查看linux官网):

capability

描述

CAP_NET_ADMIN

允许执行网络管理任务

CAP_NET_BIND_SERVICE

允许绑定到小于 1024 的端口

CAP_NET_RAW

允许使用原始套接字

比如iptables 命令,需要 CAP_NET_ADMIN 这个capabilities,如给nginx赋予了 CAP_NET_BIND_SERVICE,则它就能以普通用户运行并监听在80端口上。

linux capabilities 分成进程 capabilities 和 文件 capabilities。对于进程来说,是细分到线程的,每个线程都有自己的capabilities,而对于文件来说,是保存在文件的扩展属性上的。

进程capabilities

进程 capabilities 有五集合,每个集合使用64位bit来表示,显示为16进制格式

permitted

定义线程使用的capabilities上限,只有在这个列表内的权限才可能被使用

effective

内核检查线程是否可以进行特权操作的对象

inheritable

可以被子线程继承的capabilities,不会自动加入到子线程的Effective,而是影响子线程的permitted列表

bounding

如果某个capabilities不在Bounding集合中,即使在permitted集合中,该线程也不能将该capabilities添加到它们的inheritable集合

ambient

linux 4.3以后加

文件capabilities

permitted

该集合包含的capabilities,会与线程的Bounding 集合进行计算交集,合并到线程程的permitted集合

effective

不是一个集合,是一个标识位。如果开启,在执行完以后,会将线程permitted集合添加到 effective集合。

inheritable

与线程的inheritable进行交集,在execve后添加到permitted集合

文件capabilities的 Effective会影响到线程capabilities,具体可以查看官网的介绍

通常使用非root用户启动的进程,默认是没有任何linux capabilities,而root用户的进程缺省是包含了所有的Linux capabilities.

通过capsh 这个工具,可以将root的权限进行降级,执行以下的脚本, 切换到root下执行

[root@master bin]# /usr/sbin/capsh --keep=1 --drop=cap_net_admin -- -c 'iptables -L'
/bin/bash: /usr/sbin/iptables: 不允许的操作

上面的例子,看到即使是root账号,如果将 cap_net_admin 特权拿掉,也是不能执行的。

修改下上面的脚本,看下进程的信息

[root@master bin]# /usr/sbin/capsh --keep=1 --drop=cap_net_admin -- -c 'iptables -L;sleep 100'
/bin/bash: /usr/sbin/iptables: 不允许的操作

这个进程id 是88507,查看 /proc/88507/status 文件,这里记录了当前进程相关的信息

这里的五个键值对就是上面表里的内容,主要查看CapEff 里的内容是0000001fffffefff, 使用以下capsh命令查看,发现是没有cap_net_admin这个权限的

[root@master 88507]# capsh --decode=0000001fffffefff
0x0000001fffffefff=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_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_mac_override,cap_mac_admin,cap_syslog,35,36

docker 容器的权限

进入到容器里查看当前的权限,当前容器只会允许以下列表中的内容,也可以查看 init进程的 状态值

[root@e7de29a2481a /]# capsh --print
Current: = 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_mknod,cap_audit_write,cap_setfcap+eip

所以,在容器里执行iptables是不允许的,因为没有 cap_net_admin这个权限,但不建议直接以 --privileged的方式,这样会使它的权限过大,也可能会访问宿主机上的系统文件。

可以通过以下方式单独增加 cap_net_admin 权限

docker run -d --name iptables-test --cap-add NET_ADMIN iptables:v1 sleep 3600

这样就可以处理好开头的问题了。

相关推荐

# 安装打开 ubuntu-22.04.3-LTS 报错 解决方案

#安装打开ubuntu-22.04.3-LTS报错解决方案WslRegisterDistributionfailedwitherror:0x800701bcError:0x80070...

利用阿里云镜像在ubuntu上安装Docker

简介:...

如何将Ubuntu Kylin(优麒麟)19.10系统升级到20.04版本

UbuntuKylin系统使用一段时间后,有新的版本发布,如何将现有的UbuntuKylin系统升级到最新版本?可以通过下面的方法进行升级。1.先查看相关的UbuntuKylin系统版本情况。使...

Ubuntu 16.10内部代号确认为Yakkety Yak

在正式宣布Ubuntu16.04LTS(XenialXerus)的当天,Canonical创始人MarkShuttleworth还非常开心的在个人微博上宣布Ubuntu下个版本16.10的内...

如何在win11的wsl上装ubuntu(怎么在windows上安装ubuntu)

在Windows11的WSL(WindowsSubsystemforLinux)上安装Ubuntu非常简单。以下是详细的步骤:---...

Win11学院:如何在Windows 11上使用WSL安装Ubuntu

IT之家2月18日消息,科技媒体pureinfotech昨日(2月17日)发布博文,介绍了3中简便的方法,让你轻松在Windows11系统中,使用WindowsSubs...

如何查看Linux的IP地址(如何查看Linux的ip地址)

本头条号每天坚持更新原创干货技术文章,欢迎关注本头条号"Linux学习教程",公众号名称“Linux入门学习教程"。...

怎么看电脑系统?(怎么看电脑系统配置)

要查看电脑的操作系统信息,可以按照以下步骤操作,根据不同的操作系统选择对应的方法:一、Windows系统通过系统属性查看右键点击桌面上的“此电脑”(或“我的电脑”)图标,选择“属性”。在打开的...

如何查询 Linux 内核版本?这些命令一定要会!

Linux内核是操作系统的核心,负责管理硬件资源、调度进程、处理系统调用等关键任务。不同的内核版本可能支持不同的硬件特性、提供新的功能,或者修复了已知的安全漏洞。以下是查询内核版本的几个常见场景:...

深度剖析:Linux下查看系统版本与CPU架构

在Linux系统管理、维护以及软件部署的过程中,精准掌握系统版本和CPU架构是极为关键的基础操作。这些信息不仅有助于我们深入了解系统特性、判断软件兼容性,还能为后续的软件安装、性能优化提供重要依据。接...

504 错误代码解析与应对策略(504错误咋解决)

在互联网的使用过程中,用户偶尔会遭遇各种错误提示,其中504错误代码是较为常见的一种。504错误并非意味着网站被屏蔽,它实际上是指服务器在规定时间内未能从上游服务器获取响应,专业术语称为“Ga...

猎聘APP和官网崩了?回应:正对部分职位整改,临时域名可登录

10月12日,有网友反映猎聘网无法打开,猎聘APP无法登录。截至10月14日,仍有网友不断向猎聘官方微博下反映该情况,而猎聘官方微博未发布相关情况说明,只是在微博内对反映该情况的用户进行回复,“抱歉,...

域名解析的原理是什么?域名解析的流程是怎样的?

域名解析是网站正常运行的关键因素,因此网站管理者了解域名解析的原理和流程对于做好域名管理、解决常见解析问题,保障网站的正常运转十分必要。那么域名解析的原理是什么?域名解析的流程是怎样的?接下来,中科三...

Linux无法解析域名的解决办法(linux 不能解析域名)

如果由于误操作,删除了系统原有的dhcp相关设置就无法正常解析域名。  此时,需要手动修改配置文件:  /etc/resolv.conf  将域名解析服务器手动添加到配置文件中  该文件是DNS域名解...

域名劫持是什么?(域名劫持是什么)

域名劫持是互联网攻击的一种方式,通过攻击域名解析服务器(DNS),或伪造域名解析服务器(DNS)的方法,把目标网站域名解析到错误的地址从而实现用户无法访问目标网站的目的。说的直白些,域名劫持,就是把互...

取消回复欢迎 发表评论: