这部分是上一篇文章的延续,将继续探索 docker
宿主机中更多的底层错误配置,以及如何利用它们来获取 root
用户 shell
。
在本实验中,会发现没有安装 docker
,但安装了runc
。基本上 runc
是一个使用 OCI
规范(存储在 JSON 文件中)的容器创建和运行工具。早期采用容器化的旧系统中会安装 runc
那么就在当前目录下创建OCI
规范的配置,并配置挂载,使得宿主机根目录绑定挂载到容器根目录且有读写权限。
{
"destination": "/",
"source": "/",
"type": "bind",
"options": ["rbind", "rw"]
}
在配置中使用了 rbind
选项以允许递归地将所有子项绑定到容器中,并使用 rw
选项以允许对系统的读写权限。
一旦配置绑定挂载,在工作目录中创建“rootfs
”目录,因为容器将使用该目录。
现在只需执行runc run <name>
即可运行容器,它将生成 root 用户 shell。从这里可以检索flag
文件或系统的后门
默认情况下,docker
运行其 Unix
域socket
,并且该socket
的用户是root
,组是docker
。这个socket
文件可以在/run/docker.sock
中找到
如果当前用户在docker
组中,那么可以与 docker
守护进程通信,因为socket
文件中的组具有读写权限。
如果不确定,请使用docker images
检查当前登录用户是否可以与 Docker
守护进程通信。成功的响应将至少有列名,如果失败,将收到类似“permission denied while trying to connect to the Docker daemon socket
”的错误
使用 bind-mount
配置运行 docker 容器并使用镜像modified-ubuntu:latest
。会发现它正在运行一个 SSH 服务器,因为这是在容器入口点配置的。要覆盖容器的容器入口点,可以通过将--entrypoint /path/to/new/entrypoint
参数传递给容器创建或运行命令来实现
在这种情况下,不要通过 chroot
提权。可以看到 sudo
已安装。因此,为student
用户配置 sudo
以在没有任何密码的情况下以任何用户或组的身份运行任何命令。为此,需要在文件中添加以下配置
student ALL=(ALL:ALL) NOPASSWD: ALL
将以上行附加到/etc/sudoers
文件中,这是 sudo
命令的主要配置文件,并通过使用tail
命令列出最后 10 行来验证它
现在关闭容器并使用sudo -l
命令检查当前用户的 sudo
权限。会发现student
用户现在可以以 root
用户身份运行命令。要升级到 root
用户,只需使用 sudo
– 执行切换用户命令sudo su -l root
。这将执行 root
用户登录并进入 root
的主目录 ( /root )
在本实验和下一个实验中,将了解另一种管理容器的工具,即containerd
及其客户端ctr
。正如在容器架构系列开始时讲述的那样,docker
不仅是市场上可用的容器技术,还有其他容器技术。
在本实验中,containerd
服务正在运行,它在本地存储库中有两个镜像。使用第一个 modified-alpine:latest
。
所有内容都与 docker
相同,但在这,必须详细定义挂载配置。mount
的参数如下所述
ctr run --rm \
--mount type=bind,src=/,dst=/,options=rbind:ro \
registry:5000/modified-alpine:latest \
exploit \
bash -c "whoami;id"
通常,当容器以 root
身份运行时,它只有一个组,即用户本身(root
)。在这种情况下,当执行上面的命令时,它会向你显示 root
用户,其中有很多组。这意味着您已经在 root
主机上,不需要 chroot
。这是因为已经把宿主机的根挂载到容器的根上了
由于 sudo
已经安装在主机上,将student
用户添加到 sudoers
文件中,这样它就可以以任何用户身份运行任何命令,而不会提示输入密码。可以通过执行以下命令来执行此操作
ctr run --rm \
--mount type=bind,src=/,dst=/,options=rbind:rw \
registry:5000/modified-alpine:latest \
exploit \
bash -c "echo 'student ALL=NOPASSWD: ALL' | tee -a /etc/sudoers"
现在可以使用 sudo
将用户切换为 root
用户。这将直接登录并进入 root
用户的主目录。
在本实验中,不会专注于实际获取 root
用户 shell
,因为该flag
保存在正在运行的进程的内存中,需要从那里自行转储它。
出于安全原因,只能通过特权用户或当前用户具有 CAP_SYS_PTRACE
能力来执行读取操作。那么通过ctr
快速为student
用户添加sudo
配置,让它不用输入密码就可以以任何用户的身份执行任何命令。
在实验室的描述中,它提到“检索存储在主机系统上运行的flag-holder
进程的内存中的flag
!”。已经在主机系统上,但没有 root 用户权限。
通过简单的 Google
搜索,发现实际上可以使用 gcore
通过提及其 PID 和输出文件来转储正在运行的进程的内存。如果程序异常终止,系统会创建一个core
文件来存储终止进程的内存映像。gcore
产生的一个core
文件等同于进程崩溃时内核产生的一个文件
转储文件后,可以使用strings
和 grep
在转储中查找标志(如下所示)