
Estudio técnico de la vulnerabilidad CVE-2025-5548
En este trabajo se analiza la vulnerabilidad CVE-2025-5548, asociada a un desbordamiento de búfer en la pila presente en FreeFloat FTP Server v1.0. El objetivo principal del laboratorio es entender cómo se comporta una aplicación vulnerable ante entradas manipuladas y observar, en un entorno controlado, cómo un fallo de validación puede terminar afectando al flujo de ejecución del programa.
El desarrollo del repositorio no se limita a mostrar el resultado final, sino que recoge el proceso completo de investigación: preparación del entorno, selección de herramientas, observación del fallo, análisis de memoria y validación del impacto real de la vulnerabilidad.
El trabajo está planteado en dos bloques diferenciados.
En este apartado se explica cómo se ha montado el entorno de práctica, qué sistema operativo se ha utilizado, cuál es la aplicación vulnerable y qué herramientas se han considerado necesarias para llevar a cabo el análisis.
La segunda parte se centra en la parte práctica. Aquí se describe el proceso seguido para detectar el fallo, confirmar la corrupción de memoria, estudiar la sobrescritura de registros y comprobar cómo puede aprovecharse la vulnerabilidad.
La práctica se ha realizado sobre una máquina virtual con Windows 11 Pro 25H2 (Build 26200.6584). El software vulnerable seleccionado ha sido FreeFloat FTP Server v1.0, una aplicación antigua que resulta adecuada para este tipo de ejercicios por carecer de muchas de las protecciones habituales en programas actuales.
La red de la máquina virtual se configuró en modo NAT, lo que permitió acceso a Internet para instalar dependencias, descargar herramientas y mantener la conectividad básica del laboratorio.
Para cubrir todas las fases del análisis fue necesario apoyarse en varias utilidades. Algunas se utilizaron para preparar el entorno, otras para revisar el binario y otras para observar el comportamiento del proceso cuando se producía el fallo.
Se empleó para descargar repositorios, mantener organizados determinados recursos y facilitar la gestión del material utilizado durante la investigación.
Se utilizó como apoyo para verificar conectividad, identificar el servicio expuesto y comprobar que el objetivo estaba respondiendo correctamente en el puerto esperado.
Se instaló para disponer de bibliotecas, cabeceras y herramientas útiles en tareas de depuración y análisis a bajo nivel dentro del sistema Windows.
Se utilizó para ediciones rápidas, revisión de scripts y manipulación sencilla de cadenas o datos de prueba.
Sirvió como entorno cómodo para escribir scripts, probar automatizaciones y trabajar con código de forma más ordenada.
Fue útil especialmente cuando hubo que revisar scripts más largos o depurar lógica relacionada con la construcción de cargas.
Se contemplaron dos versiones:
Fue necesario para ejecutar Ghidra, ya que esta herramienta está desarrollada sobre Java.
Se utilizó para observar el estado del programa durante la ejecución, comprobar registros, revisar memoria y analizar el punto exacto en el que se produce el fallo.
Se empleó en la fase de análisis estático para revisar el binario y localizar funciones que resultaban sospechosas desde el punto de vista de la seguridad.
Se usó como apoyo para decompilar y entender mejor la lógica interna del programa vulnerable.
Este complemento facilitó tareas como la creación de patrones, el cálculo del offset y la identificación de caracteres problemáticos en la carga.
El componente principal del laboratorio fue FreeFloat FTP Server v1.0, que actúa como sistema objetivo dentro de la prueba de concepto. Su interés reside en que incorpora una vulnerabilidad clásica de desbordamiento en la pila, lo que lo convierte en un caso muy apropiado para análisis formativo.
Aunque existen máquinas virtuales ya preparadas para este tipo de ejercicios, en este caso se optó por documentar el entorno y justificar las herramientas utilizadas. Esto permite comprender mejor por qué cada aplicación forma parte del laboratorio y qué papel desempeña durante el análisis.
El primer paso consistió en comprobar que el servicio FTP estuviera accesible y funcionando correctamente. Una vez confirmada la conectividad, se revisó el binario mediante herramientas de análisis estático para localizar posibles puntos débiles relacionados con la gestión de cadenas.
Durante esta revisión aparecieron funciones inseguras como strcpy y strcat, lo que reforzó la sospecha de que el servicio podía ser vulnerable a entradas excesivamente largas. También se examinaron varias órdenes del protocolo FTP susceptibles de recibir datos controlados por el usuario, seleccionando una de ellas como candidato principal para las pruebas.
Con esta base, el proceso se cargó en un depurador para observar su comportamiento durante la ejecución.
La siguiente fase consistió en enviar cadenas cada vez más largas para comprobar si el programa dejaba de responder correctamente. Este procedimiento permitió verificar que, a partir de cierto tamaño, el servicio fallaba y acababa provocando una alteración en memoria.
Ese comportamiento confirmó que no se trataba de un simple error de validación superficial, sino de una corrupción real que afectaba al flujo del proceso.
Tras provocar el fallo, fue necesario calcular con precisión cuántos bytes hacían falta para alcanzar la dirección de retorno. Para ello se utilizó una secuencia no repetitiva, de modo que el valor reflejado en EIP en el momento del crash pudiera relacionarse con una posición exacta dentro de la entrada enviada.
Gracias a este procedimiento se obtuvo el desplazamiento concreto necesario para sobrescribir el registro de control.
Con el offset ya conocido, se preparó una nueva prueba en la que la dirección de retorno fue sustituida por un valor fácilmente reconocible. El objetivo era comprobar si el programa permitía modificar EIP de forma controlada.
La prueba fue satisfactoria, ya que el depurador mostró que el registro contenía exactamente el valor introducido. Esto demostraba que era posible alterar el flujo de ejecución y redirigirlo hacia una dirección elegida.
Una vez alcanzado ese punto, se analizó qué bytes podían interferir con la carga útil. En este tipo de vulnerabilidades es habitual que ciertos caracteres provoquen truncados, cambios inesperados o finalización prematura de la cadena.
Mediante comparaciones sucesivas en memoria se identificaron varios bad characters, entre ellos:
\x00\x0a\x0dDetectarlos fue importante para construir una carga final estable y compatible con el comportamiento del programa vulnerable.
El siguiente paso consistió en encontrar una dirección adecuada que permitiera redirigir la ejecución hacia la zona de memoria donde se alojaría la carga. Este análisis debía hacerse teniendo en cuenta el sistema operativo y las protecciones activas, ya que algunas direcciones no son estables entre ejecuciones.
Dentro del laboratorio se localizó una referencia válida que permitía enlazar la sobrescritura del flujo con la entrada controlada por el atacante.
Con el control del flujo ya validado, se construyó una shellcode compatible con las restricciones descubiertas previamente. Además, se añadió una zona previa de instrucciones neutras para facilitar que la CPU llegara de forma segura al inicio de la carga incluso si existía una ligera desviación en la posición esperada.
Este paso fue importante para aumentar la fiabilidad de la ejecución.
En la última fase se lanzó la carga completa contra el servicio vulnerable mientras se mantenía a la escucha un listener en la máquina atacante. El resultado fue el establecimiento de una conexión remota con el sistema objetivo, lo que confirmó que la vulnerabilidad no solo permite causar una caída del programa, sino también obtener ejecución controlada.
Esto demuestra el impacto real del fallo y justifica su relevancia desde el punto de vista de la seguridad ofensiva y defensiva.
El estudio de CVE-2025-5548 muestra con claridad cómo una aplicación antigua, sin mecanismos modernos de protección, puede ser vulnerable a técnicas clásicas de explotación basadas en corrupción de memoria.
A lo largo del laboratorio se han recorrido varias etapas fundamentales: la preparación del entorno, la observación inicial del fallo, la validación del desbordamiento, el control del registro de ejecución, la depuración de la carga y la verificación del resultado final.
Más allá de la prueba técnica, este caso sirve para entender por qué el uso de funciones inseguras y la ausencia de medidas de protección siguen siendo un riesgo importante en software heredado. Por ello, este tipo de ejercicios resulta especialmente útil para afianzar conocimientos de reversing, análisis de vulnerabilidades y explotación en entornos controlados.