Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
Herramientas/GitHubGitHub/diegslva/cve-2010-4221-lab
Frameworks de ExploitsAnálisis de VulnerabilidadesExplotaciónIngeniería InversaPruebas de PenetraciónAprendizaje y EducaciónExplotación de BinariosLabs y Práctica
GitHubdiegslva/cve-2010-4221-lab

cve-2010-4221-lab

Del parche al RCE: exploit construido a mano para CVE-2010-4221 (desbordamiento de pila TELNET IAC en ProFTPD), con el recorrido completo impulsado por fallos documentado

Ver Repositorio
hace 12h 14mAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2010-4221 — Desbordamiento de pila TELNET IAC en ProFTPD: Del parche al RCE

Un laboratorio totalmente reproducible y un exploit escrito a mano con sockets crudos para CVE-2010-4221 — el desbordamiento de búfer en pila previo a la autenticación en pr_netio_telnet_gets() de ProFTPD — construido como ejercicio de aprendizaje en investigación de vulnerabilidades y desarrollo de exploits.

Cada fallo está documentado. El camino feliz es una mentira; los desvíos son la lección.


Aviso legal y ético — lea esto primero

Este repositorio es un artefacto educativo. Existe para que las personas que no pueden pagar un mentor o una formación puedan aprender cómo nace realmente un exploit de corrupción de memoria: desde un parche, pasando por fallos, hasta una prueba de concepto funcional dentro de un laboratorio que usted posee.

El trabajo de Red Team — la seguridad ofensiva real y profesional — se define por una palabra: autorización. Todo lo que hace un profesional ocurre dentro de un acuerdo escrito: un documento de Reglas de Compromiso firmado que nombra el alcance, los objetivos, las técnicas permitidas, la ventana de tiempo y las personas que lo aprobaron. Sin ese papel, las mismas pulsaciones de teclas no son una profesión — son un delito en prácticamente todas las jurisdicciones de la Tierra.

Así que este es el contrato para este repositorio, no negociable:

  • Ejecute esto solo contra el laboratorio Docker incluido o sistemas que usted posea.
  • Nunca contra nada sin autorización explícita y por escrito.
  • Si está aprendiendo: bienvenido, esto fue construido para usted.
  • Si busca un arma para usar contra otros: cierre esta pestaña. Este fallo es de 2010; no le dará nada más que un antecedente penal.
  • El oficio merece la pena aprenderse. El oficio solo vale algo con la disciplina que lo acompaña.


    El fallo

    ProFTPD habla secuencias de escape TELNET en el canal de control FTP. En TELNET, 0xFF (IAC, "Interpret As Command") es el byte de escape; un 0xFF literal se envía como 0xFF 0xFF.

    pr_netio_telnet_gets() copia los bytes del cliente en un búfer de pila (char buf[PR_DEFAULT_CMD_BUFSZ+1] de pr_cmd_read, 4104 bytes con MAXPATHLEN=4096 de glibc), rastreando el espacio restante en buflen — un size_t, sin signo.

    La ruta vulnerable (1.3.3a, netio.c):

    root@kitploit:~
    case TELNET_IAC:
      switch (cp) {
        ...
        default:
          *bp++ = TELNET_IAC;   // escritura #1
          buflen--;             // decremento #1
          telnet_mode = 0;
          break;
      }
      break;
    ...
    *bp++ = cp;                 // escritura #2
    buflen--;                   // decremento #2  <-- sin comprobación entre ambos
    

    Dos escrituras, dos decrementos, sin comprobación de cero entre ellos. Cuando buflen es exactamente 1, el par lo decrementa a 0, y luego se desborda a SIZE_MAX (18 quintillones). El bucle ahora cree que el búfer es infinito y sigue escribiendo bytes controlados por el atacante hacia arriba en la pila — sobre los registros guardados, el RBP guardado y la dirección de retorno.

    PrevIO a la autenticación. La función se ejecuta antes de que USER/PASS se procesen jamás.

    El parche

    La corrección (commit 3cc69b8388, "Bug#3521 - Telnet IAC processing stack overflow", publicada en 1.3.3c) son doce líneas. Toda la frontera de seguridad es:

    root@kitploit:~
    if (buflen == 0) {
      break;
    }
    

    Vea patch.diff. Leer el parche le dice dónde estaba la herida — esa es la habilidad.

    El laboratorio

    El Dockerfile compila ProFTPD 1.3.3a desde el código fuente histórico de la instantánea de Debian, deliberadamente inseguro (así se veía 2010):

    • -fno-stack-protector — sin canario
    • -z execstack — pila ejecutable (sin NX)
    • -no-pie — direcciones binarias fijas
    • ejecutado bajo gdb, que desactiva ASLR por defecto → pila determinista
    root@kitploit:~
    docker build -t proftpd-133a .
    docker rm -f lab133 2>/dev/null
    docker run -d --name lab133 --cap-add SYS_PTRACE \
      --security-opt seccomp=unconfined -p 127.0.0.1:2122:21 \
      proftpd-133a sh -c 'gdb -batch -ex "set follow-fork-mode child" \
      -ex "run" -ex "continue" --args /usr/local/sbin/proftpd -n -d1 \
      > /tmp/gdb.txt 2>&1; sleep 600'
    python3 exploit.py
    

    Salida esperada:

    root@kitploit:~
    [S] 220 ProFTPD 1.3.3a Server (lab-iac) ...
    [S] THE SERVER SAID: b'PWNED!!PWNED!!'
    

    (El shellcode escribe en los fds 0, 1 y 2 porque no quisimos depender de saber cuál transporta el canal de control — dos de ellos responden.)

    La arquitectura del exploit

    root@kitploit:~
    "SITE " + trineo NOP + shellcode + [inundación \xff\xff] + relleno + [ret] + "\n"
     ^^^^^^^^^^^^^^^^^^^^                             ^^^^
     el shellcode vive DENTRO del búfer                la cola del desbordamiento solo
     de comando — la región que nadie toca             entrega UNA dirección
    
    1. "SITE " mantiene vivo el analizador FTP — el comando se procesa limpiamente.
    2. El shellcode es el contenido del comando. El búfer es el lugar más seguro en la pila: después de la lectura, solo se toca buf[4102] (NUL de truncamiento). Todo lo que está debajo de las variables locales vivas del marco está en calma.
    3. La inundación IAC lleva buflen al desbordamiento (vea "El viaje" para el problema de paridad).
    4. La ranura ret (buf + 4152) recibe la dirección del medio del trineo NOP. Cuando pr_cmd_read llega a return 0 después de analizar, la CPU aterriza en el trineo y se desliza hacia el shellcode.

    Esta arquitectura invertida — payload primero, inundación después, dirección al final — fue validada contra el módulo canónico de Metasploit (proftp_telnet_iac), que usa la misma disposición. Sus objetivos tenían NX, por lo que necesitaban una cadena ROP con un "doble desreferenciado cuádruple" del puntero res; nuestro laboratorio tiene una pila ejecutable, por lo que un solo retorno directo basta.

    El viaje (el punto real de este repositorio)

    El exploit final son 60 líneas. Lo que costó:

    1. Inundación ciega de \xff → nada. El servidor cerró cortésmente la sesión. Causa raíz: buflen comienza en 4102 (PAR) y cada par IAC decrementa en 2 — aterriza en 0 limpiamente, nunca en 1. El desbordamiento necesita romper la paridad. Lección: leer la máquina de estados vence a rociar.

    2. Tamaño de búfer incorrecto. El primer intento calibrado asumió un búfer de 1024 bytes. El real es MAXPATHLEN+8 = 4104 en Linux/glibc. La inundación se detuvo 3KB antes del objetivo. Lección: mida el objetivo, no asuma el objetivo.

    3. Primer SIGSEGV. El patrón cíclico de Bruijn (Aa0Aa1...) colocó la ranura de retorno en buf+4152, validado de forma cruzada dos veces (matemática del marco + desplazamiento del patrón). Lección: el patrón cíclico es una cinta métrica, no un exploit.

    4. Control de RIP. Establecer la ranura en 0x4141414141414141 bloqueó la propia instrucción ret — x86-64 rechaza direcciones no canónicas, y el fallo ocurre en ret, con nuestro valor esperando en el backtrace. Lección: un bloqueo en ret con su valor en el marco = control.

    5. Shellcode por encima de la ranura ret → destruido. 8 bytes sobrescritos por un puntero de heap (0x4d7838 — identificado más tarde como la asignación del pool cmd_rec). Los marcos de pila por encima de la ranura pertenecen a funciones que aún están trabajando entre el aterrizaje y el secuestro. Lección: el desbordamiento no es la última escritura; el programa sigue viviendo en la pila que acaba de vandalizar.

    6. "Zona muerta" debajo de la ranura → también garabateada. Las propias variables locales de pr_cmd_read (cmd, buflen, cp) viven justo allí y siguen almacenándose durante el análisis.

    7. Forensica con puntos de interrupción de hardware. watch *(long*)ADDR en gdb convirtió el misterio en una cámara: cada escritura en la dirección destruida, con backtrace, en orden. Lección: cuando la pregunta es "¿quién escribió esta memoria?", la respuesta está a un comando de gdb de distancia.

    8. Lea la referencia, luego entiéndala. El módulo canónico confirmó la arquitectura invertida. Leer otro exploit después de construir su propio modelo mental es estudio; antes, es copiar.

    Lecciones aprendidas

    • size_t nunca se vuelve negativo — se vuelve gigantesco. El desbordamiento de enteros en un contador de espacio restante es un desbordamiento de pila con pasos extra.
    • La paridad es un arma. Cuando una primitiva decrementa de 2 en 2, usted controla el desbordamiento controlando par/impar, no solo el tamaño.
    • Los caracteres malos son una cuestión de protocolo. Nuestro shellcode evita \x0a (termina la lectura) y sobrevive a \xff (escape TELNET) por diseño.
    • Los servidores prefork perdonan los bloqueos. El hijo muere, el padre sigue aceptando: intentos infinitos. La ingeniería de fiabilidad es parte del exploit.
    • Mida y explote el mismo artefacto. Una diferencia de 11 bytes en argv[0] (binario del árbol de compilación vs binario instalado) desplazó toda la pila en 0x40 e invalidó silenciosamente un exploit perfecto.
    • El manejador de señales confiesa. ProFTPD captura SIGSEGV y registra "terminating (signal 11)" — el objetivo le dice que murió, incluso cuando el kernel permanece en silencio.

    Referencias

    • Commit de corrección: https://github.com/proftpd/proftpd/commit/3cc69b8388
    • CVE: https://nvd.nist.gov/vuln/detail/CVE-2010-4221
    • Módulo canónico: modules/exploits/linux/ftp/proftp_telnet_iac.rb (rapid7/metasploit-framework)
    • Laboratorio hermano (fallo lógico, mismo demonio): CVE-2015-3306 mod_copy

    Autor

    Construido por diegslva, aprendiendo en público — desde "nunca escribí un exploit" hasta RCE previo a la autenticación con shellcode hecho a mano, en un día documentado. Si este repositorio le enseñó algo, páselo adelante.

    Descargar herramienta