Ir al contenido

FTP

Última actualización

FTP permite autenticar usuarios, recorrer directorios y transferir archivos mediante dos conexiones separadas. Esa arquitectura explica gran parte de sus fallos de conectividad y de lo que debe enumerarse. TFTP comparte el objetivo general de transferir archivos, pero utiliza UDP, carece de autenticación estándar y no ofrece listing de directorios. No son variantes intercambiables.

Los ejemplos utilizan TARGET_IP, FQDN, KNOWN_FILE y LOCAL_FILE como placeholders. La referencia de Nmap es el prerrequisito para sus opciones de scanning.

La conexión de control suele llegar a 21/tcp. Por ella viajan los comandos, las credenciales y los códigos de respuesta. Cada listing o transferencia abre además una conexión de datos.

control: cliente:any ───────────────> servidor:21/tcp
datos: se abre otra conexión para LIST, RETR o STOR

En modo activo, el cliente anuncia con PORT o EPRT la dirección y el puerto donde escuchará. El servidor inicia la conexión de datos hacia el cliente. FTP clásico utiliza 20/tcp como puerto de origen del servidor, aunque la implementación y la configuración pueden variar.

En modo pasivo, el cliente pide PASV o EPSV. El servidor abre un puerto y el cliente inicia también la conexión de datos. EPSV devuelve solo el puerto y reutiliza la dirección de la conexión de control, lo que evita varios problemas con NAT e IPv6.

Modo Quién abre la conexión de datos Fallo típico
Activo Servidor hacia cliente El firewall o NAT del cliente bloquea la conexión entrante.
Pasivo Cliente hacia servidor El rango pasivo no está publicado, permitido o anunciado correctamente.

Si el login funciona pero ls o una descarga quedan esperando, el problema suele estar en la conexión de datos, no en el canal de control.

Los comandos FTP se envían como texto sobre la conexión de control:

Comando Función
USER, PASS Autenticación.
SYST Tipo de sistema informado por el servidor.
FEAT Extensiones soportadas, como UTF8, MLSD o AUTH TLS.
PWD, CWD Consultar o cambiar el directorio actual.
LIST, MLSD Listar recursos. MLSD ofrece un formato estructurado.
TYPE Seleccionar transferencia ASCII o binaria.
PASV, EPSV Preparar una conexión de datos pasiva.
PORT, EPRT Anunciar el endpoint de datos en modo activo.
RETR Descargar un archivo.
STOR Subir o reemplazar un archivo.
DELE, RMD Borrar archivos o directorios.
STAT Solicitar estado del servidor o de un recurso.

El primer dígito del código resume el resultado:

Rango Significado
1xx Acción iniciada, pendiente de otra respuesta.
2xx Operación completada.
3xx Falta información, normalmente credenciales.
4xx Fallo temporal. La operación podría repetirse.
5xx Fallo permanente, comando no soportado o acceso denegado.

Durante una transferencia es normal recibir un 150 antes de los datos y un 226 al completarla. Un 230 confirma el login. Un 530 indica que la sesión no está autenticada o que las credenciales fueron rechazadas.

En Nmap, -p 21 limita el scan al puerto TCP 21 y -sV activa version detection, que abre una conexión y compara la respuesta con sus firmas:

Identificar FTP y su implementación
nmap -sV -p 21 TARGET_IP

El banner puede revelar producto, versión, hostname o sistema operativo. También puede estar oculto o modificado. Confirma el protocolo con una sesión real y conserva por separado lo que el servidor anuncia y lo que la herramienta infiere.

El cliente se inicia con el destino. Algunas implementaciones aceptan también el puerto como segundo argumento:

Conectar con el cliente FTP
ftp TARGET_IP

Empieza con help para conocer los comandos del cliente local. No todos los clientes implementan debug, trace, passive o status de la misma manera.

Una sesión anonymous suele utilizar anonymous o ftp como usuario. Históricamente se emplea una dirección de email como password, aunque muchos servidores aceptan cualquier valor o no solicitan uno:

Login anonymous
Name: anonymous
Password: anonymous@example.com

Después del login, comprueba el contexto antes de descargar nada:

Comandos dentro del cliente FTP
status
system
pwd
ls -la

status describe el estado del cliente. system suele enviar SYST. pwd confirma el directorio remoto y ls -la solicita un listing detallado. Los argumentos de LIST, como -la o -R, no forman parte de un formato portable y algunos servidores los ignoran o rechazan. Si existe MLSD, ofrece datos más fáciles de interpretar.

Activa debug para ver comandos y respuestas del canal de control. trace añade el flujo de llamadas del cliente en implementaciones que lo soportan. El tráfico puede incluir el password en claro cuando no se negocia TLS.

Antes de una transferencia usa binary para evitar conversiones de final de línea o representación sobre ejecutables, archives e imágenes. lcd cambia el directorio local donde se guardan o leen los archivos:

Preparar la transferencia
binary
lcd /tmp/ftp-review

get descarga un archivo. mget descarga varios y puede pedir confirmación por cada uno. El comando prompt activa o desactiva esa confirmación en muchos clientes:

Descargar recursos
get KNOWN_FILE
prompt
mget *.conf

El patrón *.conf selecciona los nombres que terminan en .conf dentro del directorio remoto actual.

put y mput suben archivos. Una transferencia correcta no demuestra que el archivo sea accesible desde otro servicio ni que conserve el mismo nombre, owner o permisos:

Comprobar escritura con un archivo identificable
put LOCAL_FILE
ls -la

La escritura crea o modifica estado en el servidor. Registra directorio, nombre remoto, hash, owner, permisos y hora. Si la prueba usa un archivo temporal, esa información permite comprobar su efecto y retirarlo después sin confundirlo con datos previos.

Para una descarga recursiva mediante Wget, -m activa mirroring y --no-host-directories evita crear una carpeta adicional con el hostname. La URL incluye las credenciales y puede quedar en el history o en la lista de procesos:

Replicar un árbol FTP accesible
wget -m --no-host-directories \
'ftp://anonymous:anonymous%40example.com@TARGET_IP/'

En la URL, %40 representa el carácter @ del password. Así no se confunde con el @ que separa las credenciales del hostname.

El mirroring puede transferir muchos datos. Revisa primero el listing, el tamaño y el espacio local. Un filesystem grande o con enlaces inesperados puede convertir una comprobación pequeña en una descarga extensa.

NSE permite automatizar preguntas concretas. --script selecciona scripts por nombre. ftp-anon prueba el login anonymous, lista el directorio raíz y marca entradas escribibles. ftp-syst envía SYST y STAT. Se reutilizan -sV y -p 21, ya explicados al identificar el servicio:

Comprobar acceso anonymous y estado del servidor
nmap -sV -p 21 --script ftp-anon,ftp-syst TARGET_IP

ftp-anon limita por defecto el listing. --script-args ftp-anon.maxlist=-1 pasa al script el valor -1, que elimina ese límite:

Solicitar el listing completo con ftp-anon
nmap -sV -p 21 --script ftp-anon \
--script-args ftp-anon.maxlist=-1 TARGET_IP

El script confirma lo que su código prueba. Una entrada marcada como escribible sigue necesitando una validación efectiva si esa propiedad cambia la investigación. Usa --script-help ftp-anon y revisa la documentación antes de depender del output.

FTP transmite comandos, usernames, passwords y datos sin cifrar. FTPS añade TLS al protocolo FTP. En FTPS explícito, la sesión comienza en el puerto FTP y negocia AUTH TLS. En FTPS implícito, el handshake TLS ocurre al conectar, a menudo en 990/tcp. SFTP pertenece a SSH y no utiliza FTP.

openssl s_client puede negociar FTPS explícito. -connect FQDN:21 selecciona el endpoint, -starttls ftp envía la negociación propia de FTP y -servername FQDN establece SNI:

Negociar FTPS explícito e inspeccionar el certificado
openssl s_client -connect FQDN:21 -starttls ftp -servername FQDN

El certificado puede revelar SAN, emisor, fechas y nombres adicionales. También permite comprobar si el canal de control acepta TLS. La protección del canal de datos se negocia por separado mediante comandos como PBSZ y PROT, por lo que un login cifrado no demuestra automáticamente que las transferencias también lo estén.

Con acceso local, la configuración explica comportamientos que desde la red solo podían inferirse. vsftpd utiliza normalmente /etc/vsftpd.conf, aunque el proceso puede recibir otra ruta.

grep -E activa expresiones regulares extendidas. -v invierte la selección. El patrón descarta líneas vacías y comentarios, de modo que el output contiene las directivas activas:

Mostrar directivas activas de vsftpd
grep -Ev '^[[:space:]]*(#|$)' /etc/vsftpd.conf

Las opciones relevantes se interpretan en conjunto:

Directiva Efecto
anonymous_enable Acepta los usuarios anonymous y ftp.
local_enable Permite logins de cuentas locales.
write_enable Habilita globalmente comandos que modifican el filesystem.
anon_upload_enable Permite uploads anonymous si también existen permisos Unix.
anon_mkdir_write_enable Permite crear directorios anonymous con los demás requisitos.
anon_other_write_enable Permite otras operaciones como rename o delete.
anon_root Fija el directorio raíz para la sesión anonymous.
download_enable Habilita o deshabilita descargas.
hide_ids Sustituye owners y groups por ftp en los listings.
chroot_local_user Sitúa por defecto a usuarios locales en un chroot.
userlist_enable, userlist_deny, userlist_file Controlan la lista de cuentas aceptadas o denegadas.
ssl_enable, implicit_ssl Activan TLS explícito o implícito.
force_local_logins_ssl, force_local_data_ssl Exigen TLS para control y datos de usuarios locales.
pasv_min_port, pasv_max_port, pasv_address Definen rango y dirección anunciados para modo pasivo.

write_enable=YES no basta para subir archivos. El usuario efectivo necesita permisos sobre el directorio y las opciones específicas de anonymous deben permitir la operación. Del mismo modo, hide_ids=YES cambia el listing, no los owners reales del filesystem.

/etc/ftpusers suele contener cuentas a las que el stack de autenticación deniega FTP. No es una lista de usuarios válidos ni una prueba de que cada cuenta exista:

En sed, -n desactiva la impresión automática y 1,200p imprime las primeras 200 líneas:

Revisar cuentas excluidas de FTP
sed -n '1,200p' /etc/ftpusers

Los logs, la unidad de servicio y la línea de comandos del proceso ayudan a confirmar qué archivo de configuración está realmente cargado.

El comando PORT permite pedir al servidor FTP que abra la conexión de datos hacia una dirección distinta. Los servidores actuales suelen impedirlo, pero una implementación vulnerable puede convertirse en punto de observación para alcanzar otros hosts y puertos desde su red.

El script ftp-bounce comprueba si el servidor acepta esa operación. Para realizar un bounce scan, Nmap ofrece el scan type -b. Su argumento describe las credenciales y el servidor FTP intermediario. El target final aparece al final del comando:

Port scan a través de un servidor FTP bounce
nmap -b USER:PASSWORD@FTP_SERVER:21 BOUNCE_TARGET

El scanner se autentica en FTP_SERVER y utiliza respuestas a PORT y transferencias para inferir el estado de puertos en BOUNCE_TARGET. El host final observa conexiones procedentes del servidor FTP, no de la máquina que ejecuta Nmap. El servidor intermediario registra la sesión y las peticiones. Incluir el password en el argumento puede exponerlo en shell history y process listings.

La técnica depende de que el servidor permita proxy FTP hacia el destino y los puertos elegidos. Muchos bloquean direcciones externas, puertos bajos o cualquier dirección distinta de la conexión de control.

TFTP utiliza 69/udp para la petición inicial. La transferencia continúa mediante UDP entre identificadores de transferencia elegidos por cliente y servidor. Solo define operaciones de lectura y escritura de archivos. No incluye autenticación, navegación ni listing.

Con el cliente interactivo, get KNOWN_FILE solicita un nombre conocido y put LOCAL_FILE intenta escribirlo:

Solicitar un archivo conocido por TFTP
tftp TARGET_IP
tftp> get KNOWN_FILE

La ausencia de listing obliga a obtener nombres de configuración, documentación, logs o convenciones del dispositivo. El script tftp-enum prueba una wordlist de nombres. -sU selecciona UDP, -p 69 limita el scan al puerto 69 y --script tftp-enum ejecuta ese script:

Probar nombres comunes en un servicio TFTP
nmap -sU -p 69 --script tftp-enum TARGET_IP

tftp-enum pertenece a las categorías discovery e intrusive porque genera múltiples solicitudes de archivo. --script-args tftp-enum.filelist=FILE permite sustituir la wordlist por nombres derivados del entorno.

Síntoma Comprobación
Conecta a 21 pero no aparece banner Enviar FEAT o SYST, comprobar TLS explícito y revisar version detection.
Login correcto, listing bloqueado Cambiar entre activo y pasivo, revisar 227/229, NAT y rango pasivo.
550 al descargar Path, directorio actual, permisos efectivos y download_enable.
Upload aceptado pero archivo no visible Nombre remoto, chroot, umask, owner, directorio real y backend.
El hash cambia tras descargar Confirmar modo binary, transferencia completa y tipo de archivo.
TFTP no encuentra un archivo TFTP no lista. Verificar nombre exacto, root del servicio y logs.