HTB Kobold Writeup
Un saludo, hoy traigo el writeup de la máquina Kobold de HTB, espero que el procedimiento sea de su agrado y fácil de comprender.
Reconocimiento
Primero vemos si tenemos conexión con la máquina y de paso gracias al ttl identificamos ante el tipo de máquina que estamos, en linux este suele ser de 64 y en windows de 128. Aunque se puede modificar, no siempre es así
1
2
3
4
5
6
7
ping -c1 10.129.81.243
PING 10.129.81.243 (10.129.81.243) 56(84) bytes of data.
64 bytes from 10.129.81.243: icmp_seq=1 ttl=63 time=111 ms
--- 10.129.81.243 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 111.350/111.350/111.350/0.000 ms
Vemos que el ttl de la máquina es de 63, el cual está próximo a 64 por ende nos encontramos ante una máquina Linux.
Ahora vamos a identificar los puertos abiertos dentro de la máquina, los invito a usar el siguiente script hecho en bash.
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
33
34
#!/bin/bash
GREEN="\e[32m"
RED="\e[31m"
RESET="\e[0m"
IP="$1"
if [ -z "$IP" ]; then
echo "Uso: $0 <IP>"
exit 1
fi
TEMP_FILE=$(mktemp)
echo -e "${GREEN}[+] Escaneando todos los puertos abiertos... ${RESET}"
nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn "$IP" -oG "$TEMP_FILE"
# Extraer los puertos abiertos
PORTS=$(grep -oP '\d+/open' "$TEMP_FILE" | awk -F'/' '{print $1}' | tr '\n' ',' | sed 's/,$//'; echo)
rm "$TEMP_FILE"
if [ -z "$PORTS" ]; then
echo -e "${RED}[-] No se encontraron puertos abiertos.${RESET}"
exit 1
fi
echo -e "\n${GREEN}[+] Escanenado servicios en los puertos: $PORTS. ${RESET}\n"
nmap -sCV -p"$PORTS" "$IP" -oN target
echo -e "\n${GREEN}[+] Escano completado. Resultados en 'target'.${RESET}\n"
El script se lo lanza como root, ya que algunos parámetros de nmap, requieren de privilegios elevados. Esto genera un archivo target que contiene la información de los puertos abiertos dentro de la máquina.
1
sudo ./scan.sh 10.129.81.243
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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-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
| tls-alpn:
| http/1.1
| http/1.0
|_ http/0.9
|_ssl-date: TLS randomness does not represent time
|_http-title: Did not follow redirect to https://kobold.htb/
3552/tcp open http Golang net/http server
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
| fingerprint-strings:
| GenericLines:
| HTTP/1.1 400 Bad Request
| Content-Type: text/plain; charset=utf-8
| Connection: close
| Request
| GetRequest, HTTPOptions:
| HTTP/1.0 200 OK
| Accept-Ranges: bytes
| Cache-Control: no-cache, no-store, must-revalidate
| Content-Length: 2081
| Content-Type: text/html; charset=utf-8
| Expires: 0
| Pragma: no-cache
| Date: Fri, 07 Aug 2026 22:39:52 GMT
| <!doctype html>
| <html lang="%lang%">
| <head>
| <meta charset="utf-8" />
| <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
| <meta http-equiv="Pragma" content="no-cache" />
| <meta http-equiv="Expires" content="0" />
| <link rel="icon" href="/api/app-images/favicon" />
| <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover" />
| <link rel="manifest" href="/app.webmanifest" />
| <meta name="theme-color" content="oklch(1 0 0)" media="(prefers-color-scheme: light)" />
| <meta name="theme-color" content="oklch(0.141 0.005 285.823)" media="(prefers-color-scheme: dark)" />
|_ <link rel="modu
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port3552-TCP:V=7.99%I=7%D=8/7%Time=6A765ECC%P=x86_64-pc-linux-gnu%r(Gen
SF:ericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20te
SF:xt/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x2
SF:0Request")%r(GetRequest,8FF,"HTTP/1\.0\x20200\x20OK\r\nAccept-Ranges:\x
SF:20bytes\r\nCache-Control:\x20no-cache,\x20no-store,\x20must-revalidate\
SF:r\nContent-Length:\x202081\r\nContent-Type:\x20text/html;\x20charset=ut
SF:f-8\r\nExpires:\x200\r\nPragma:\x20no-cache\r\nDate:\x20Fri,\x2007\x20A
SF:ug\x202026\x2022:39:52\x20GMT\r\n\r\n<!doctype\x20html>\n<html\x20lang=
SF:\"%lang%\">\n\t<head>\n\t\t<meta\x20charset=\"utf-8\"\x20/>\n\t\t<meta\
SF:x20http-equiv=\"Cache-Control\"\x20content=\"no-cache,\x20no-store,\x20
SF:must-revalidate\"\x20/>\n\t\t<meta\x20http-equiv=\"Pragma\"\x20content=
SF:\"no-cache\"\x20/>\n\t\t<meta\x20http-equiv=\"Expires\"\x20content=\"0\
SF:"\x20/>\n\t\t<link\x20rel=\"icon\"\x20href=\"/api/app-images/favicon\"\
SF:x20/>\n\t\t<meta\x20name=\"viewport\"\x20content=\"width=device-width,\
SF:x20initial-scale=1,\x20maximum-scale=1,\x20viewport-fit=cover\"\x20/>\n
SF:\t\t<link\x20rel=\"manifest\"\x20href=\"/app\.webmanifest\"\x20/>\n\t\t
SF:<meta\x20name=\"theme-color\"\x20content=\"oklch\(1\x200\x200\)\"\x20me
SF:dia=\"\(prefers-color-scheme:\x20light\)\"\x20/>\n\t\t<meta\x20name=\"t
SF:heme-color\"\x20content=\"oklch\(0\.141\x200\.005\x20285\.823\)\"\x20me
SF:dia=\"\(prefers-color-scheme:\x20dark\)\"\x20/>\n\t\t\n\t\t<link\x20rel
SF:=\"modu")%r(HTTPOptions,8FF,"HTTP/1\.0\x20200\x20OK\r\nAccept-Ranges:\x
SF:20bytes\r\nCache-Control:\x20no-cache,\x20no-store,\x20must-revalidate\
SF:r\nContent-Length:\x202081\r\nContent-Type:\x20text/html;\x20charset=ut
SF:f-8\r\nExpires:\x200\r\nPragma:\x20no-cache\r\nDate:\x20Fri,\x2007\x20A
SF:ug\x202026\x2022:39:52\x20GMT\r\n\r\n<!doctype\x20html>\n<html\x20lang=
SF:\"%lang%\">\n\t<head>\n\t\t<meta\x20charset=\"utf-8\"\x20/>\n\t\t<meta\
SF:x20http-equiv=\"Cache-Control\"\x20content=\"no-cache,\x20no-store,\x20
SF:must-revalidate\"\x20/>\n\t\t<meta\x20http-equiv=\"Pragma\"\x20content=
SF:\"no-cache\"\x20/>\n\t\t<meta\x20http-equiv=\"Expires\"\x20content=\"0\
SF:"\x20/>\n\t\t<link\x20rel=\"icon\"\x20href=\"/api/app-images/favicon\"\
SF:x20/>\n\t\t<meta\x20name=\"viewport\"\x20content=\"width=device-width,\
SF:x20initial-scale=1,\x20maximum-scale=1,\x20viewport-fit=cover\"\x20/>\n
SF:\t\t<link\x20rel=\"manifest\"\x20href=\"/app\.webmanifest\"\x20/>\n\t\t
SF:<meta\x20name=\"theme-color\"\x20content=\"oklch\(1\x200\x200\)\"\x20me
SF:dia=\"\(prefers-color-scheme:\x20light\)\"\x20/>\n\t\t<meta\x20name=\"t
SF:heme-color\"\x20content=\"oklch\(0\.141\x200\.005\x20285\.823\)\"\x20me
SF:dia=\"\(prefers-color-scheme:\x20dark\)\"\x20/>\n\t\t\n\t\t<link\x20rel
SF:=\"modu");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Vemos que se nos refleja un dominio, así que lo agregamos al /etc/hosts, para que la máquina sepa a donde resolver.
1
2
3
echo "10.129.81.243 kobol.htb" | sudo tee -a /etc/hosts
10.129.81.243 kobol.htb
Tenemos cuatro puertos abiertos, sin embargo en 80 redirige al 443, vamos al navegador y vemos que se nos presenta.
Parece ser un sitio que dice estar en construcción. Podemos usar herramientas como ffuf para ver si se encuentran subdominios, para ello yo uso una lista con posibles rutas del repositocio de SecList
1
ffuf -c -t 100 -w $(locate n0kovo_subdomains.txt) -H "HOST: FUZZ.kobold.htb" -u https://Kobold.htb/ -fw 4
Se encontraron dos subdominio y se los agrega al /etc/hosts.
1
echo "10.129.81.243 bin.kobold.htb mcp.kobold.htb" | sudo tee -a /etc/hosts
El mcp.kobold.htb vemos que es un servicio llamado MCPJam el cual parece ser es una plataforma de desarrollo, pruebas, depuración y evaluación diseñada para servidores MCP, lo interesante es que si vamos a Settings podemos ubicar una versión del mismo.
Explotación de MCPJam (CVE-2026-23744)
Buscando un poco se encuentra un CVE asociado a esa versión, tambien se da con una prueba de concepto (POC) de tipo RCE documentada en esta web.
Como tal la vulnerabilidad se aplica en el servidor y en la respuesta no devuelve el contenido del comando realizado, podemos ver si en primer instancia se entabla una conexión por ncetat.
Vemos que efectivamente se produjo el RCE, ya dentro hacemos el tratamiento de la tty.
1
2
3
4
5
6
7
8
9
10
script /dev/null -c bash
Ctrl + z
stty raw -echo; fg
export TERM=xterm
# Para proporciones adecuadas podemos ver en otra ventana de nuestra consola el tamaño
stty size
# Luego ponemos los numeros respectivamente para la columnas y filas, ejemplo:
stty rows 46 columns 172
Una vez dentro en el directorio /home del usuario correspondiente podemos ver la primera flag.
Escalada de privilegios
Si buscamos por binarios que tengan permisos SUID hay uno que llama la atención newgrp el cual “es una herramienta estándar de Linux que se utiliza para cambiar el grupo primario actual del usuario durante la sesión activa en la terminal”.
Podemos probar agregando nos al grupo docker y vemos que es exitoso.
Podemos aprovecharnos de ello para montar el directorio el directorio root en una ruta que queramos, ello ocurre debido a que docker se esta ejecutando como el usuario con privilegios elevados.
Una vez con ello ya podemos visualizar la ultima flag del equipo.





