利用docker提权的一次尝试

Posted by kevin on May 31, 2020

preface

前几天服务器出了点事故找到茗哥咨询,了解到了关于 docker 的一些比较 hack 知识,今天亲自实践了一下,说声 docker 牛逼!

大型的服务器一般都有很多人会一起用,为了防止一些用户操作不当导致服务器出事故,一般都不会给 sudo 权限给用户,只有几个管理员拥有 sudo 权限,这样保证了服务器的安全性,但是如果普通用户属于 docker 组的话,其实还是可以通过一些操作来做一些有 sudo 权限才能做的事,这就是利用 docker 进行提权。

environment

实验室的服务器上不敢乱搞,本次实验就在我的阿里云服务器上进行操作,服务器上已经安装了 docker,有两个用户,一个 root,一个 kevin,root 拥有所有权限,而 kevin 不具有 sudo 权限,无法安装软件等,由于是普通用户,所以也用不了 docker,但是为了演示本次提权过程,我在 root 用户用以下命令将 用户 kevin 添加到了 docker 组

创建一个名为 docker 的组

$ sudo groupadd docker 

将 kevin 用户添加至 docker 组(移除组时将 -a 换成 -d)

$ sudo gpasswd -a kevin docker

重启 docker,否则不会生效

$ sudo systemctl restart docker

start

首先用 id 命令查看一下 kevin 用户的账户信息(用户 id,所属群组 id),说明 kevin 用户在 kevin 和 docker 组里面

$ id kevin

uid=1000(kevin) gid=1000(kevin) groups=1000(kevin),1001(docker)

现在让我们忘记 root 用户的存在,我们的目的是让 kevin 这个普通用户也能够拥有 root 权限。开始吧,让我们先 在 docker 中 pull 一个 ubuntu 系统(理论上任何 Linux 都可以),如果已经有 Linux 的 docker 的话可以不用做这一步

$ docker pull ubuntu

我们知道,在 docker 中我们是拥有 root 权限的,这也是为什么能够用 docker 进行提权的原因,docker 有个选项 -v 能够将 host 的目录映射到 docker 中访问,我们可以将 /etc 中的内容映射到 docker 的/etc 目录中实现覆盖,因为很多重要的文件都在 /etc 目录中(比如 passwd,sudoers ,groups)

$ docker run -it -v /etc:/etc ubuntu

然后在 docker 中利用下面这个命令将 kevin 用户添加到 root 组,因为这里没有 sudo 组,只有 root 组,其实也一样

$  usermod -aG root kevin

此时 kevin 用户就已经被加入到了 root 组,之后这个 docker 容器就已经没啥用了,可以退出去了,在主机中再次查询一下 kevin 的用户信息,得到如下结果,说明在 docker 中进行的改动已经生效

uid=1000(kevin) gid=1000(kevin) groups=1000(kevin),0(root),1001(docker)

一般情况下的话,如果是有 sudo 组的,这样就 ok 了,然后用 sudo apt-get install xx 试试水,没想到还是会报错,说没有权限。

error

害,不过改一下也简单,为用户赋予 sudo 权限时,只需要改动一下 /etc/sudoers 这个文件,同样用 docker 来操作一下就可以了,不过我这里遇到了坑,因为阿里云服务器是 centOS 的,下载的 docker 镜像是 ubuntu,ubuntu docker 默认是没有任何编辑器的,得自己安装,但是安装源在 /etc/apt/xx 里面,我用 centOS 的 /etc 目录替换了 ubuntu 的 /etc 目录,所以就找不到源,无法安装。

然后我将 ubuntu docker 装好 vim 之后打 tag 成为一个新的镜像,再用上面的步骤,还是说没有 vim 这个命令,emm,所以最好 host 主机是什么 OS 就 pull 什么 OS 镜像吧,反正最后我是在 docker 容器中用 echo 加上重定向操作符解决问题的。

$ echo "kevin ALL=(ALL) ALL" >> /etc/sudoers

到这里,kevin 用户就已经拥有了 sudo 权限,接下去就可以随意操作这台服务器了。

success

这里也可以用另一种方法,就是在 docker 容器中新增加一个用户,为用户赋予 sudo 权限,再到 host 里面用这个用户为 kevin 赋权限,不过是麻烦了点

end

不知道拥有了 sudo 权限能干吗?连 root 的密码都能改掉!在 linux 系统上,普通用户修改密码可以用 passwd user 自行修改,但如果密码忘记的话,就可以寻求拥有 sudo 权限的管理员利用 sudo passwd user 进行更改,管理员可以直接修改,但是不能知道用户之前的密码是多少。同理,kevin 现在拥有了 sudo 权限,可以用下面的命令修改 root 用户的密码,而不需要知道 root 的密码是多少。

$ sudo passwd root

addition

DockerHub 上有人已经开源了一个镜像 rootplease ,只要用户在 docker 组中,运行下面命令就能直接在 docker 中获取到 root 权限(2015 年的东西了,我现在才知道)

$ docker run -v /:/hostOS -i -t chrisfosterelli/rootplease

他的脚本里面有用的就是这一句,chroot /hostOS /bin/sh,就是 chroot (change root directory) 到容器的 /hostOS (也就是宿主机的 /),然后获取到宿主机的 root 权限,并启动 shell 程序,直接在 docker 中执行命令

prevent

预防这种情况发生的方法,就是不要使用 docker 组

reference

https://www.freebuf.com/articles/system/170783.html