FileZilla Forensics with Python

Estimated read time 3 min read

Incident responders and cybersecurity enthusiasts, this one’s for you. If you’ve ever faced challenges in tracing data exfiltration via FileZilla, this tool will ease your pain. It dives deep into user directories, parsing and analyzing critical FileZilla-related files: filezilla.xml, recentservers.xml, and queue.sqlite3.

The filezilla.xml file stores user settings, providing insights into user-specific preferences. recentservers.xml keeps track of recently accessed servers, helping you trace connections.

Lastly, queue.sqlite3 is a gold mine containing tables that can help identify what files were exfiltrated, their destination (remote hostname and file path), and much more.

Python script to parse Filezilla for artifacts

# Windows.Forensics.FileZilla
"""
This script enumerates all user directories on a system and parses three files within a users AppData\Roaming\FileZilla directory: filezilla.xml, recentservers.xml, and queue.sqlite3

These three files provide valuable data to incident responders if data was exfiltrated using FileZilla.

- filezilla.xml - contains saved user settings
- recentservers.xml - contains recently accessed servers
- queue.sqlite3 - contains multiple tables that can be used to identify what files were exfiltrated and to where (remote hostname and file path).


Original idea from Author: Dan Kelly - @dan_kelly17
https://www.hecfblog.com/2013/09/daily-blog-93-filezilla-artifacts.html

Translated towards Python by Reza Rafati - @Cyberwarzonecom
"""

import glob
import os
import re
import sqlite3
from xml.dom.minidom import parseString

# Default settings
FileZillaGlob = '\\AppData\\Roaming\\FileZilla\\'
queueSQLQuery = '''
    SELECT local_paths.path AS PATH, files.source_file AS File, servers.host FROM files
    JOIN local_paths ON local_paths.id = files.local_path
    JOIN servers ON servers.id = files.server
'''
userRegex = '.'

# Helper function to parse xml files
def parse_xml_file(file):
    with open(file, 'r') as f:
        data = f.read()
        return parseString(data)

# Get all user directories
user_directories = [d for d in os.listdir('C:\\Users') if re.match(userRegex, d)]

# Process each user directory
for user_dir in user_directories:
    # Parse filezilla.xml
    filezilla_xml_path = f"C:\\Users\\{user_dir}{FileZillaGlob}filezilla.xml"
    if os.path.exists(filezilla_xml_path):
        print(f"Parsing {filezilla_xml_path}")
        filezilla_dom = parse_xml_file(filezilla_xml_path)
        tabs = filezilla_dom.getElementsByTagName('Tab')
        for tab in tabs:
            print(tab.toxml())
    
    # Parse recentservers.xml
    recentservers_xml_path = f"C:\\Users\\{user_dir}{FileZillaGlob}recentservers.xml"
    if os.path.exists(recentservers_xml_path):
        print(f"Parsing {recentservers_xml_path}")
        recentservers_dom = parse_xml_file(recentservers_xml_path)
        servers = recentservers_dom.getElementsByTagName('Server')
        for server in servers:
            print(server.toxml())
    
    # Parse queue.sqlite3
    queue_sqlite_path = f"C:\\Users\\{user_dir}{FileZillaGlob}queue.sqlite3"
    if os.path.exists(queue_sqlite_path):
        print(f"Parsing {queue_sqlite_path}")
        conn = sqlite3.connect(queue_sqlite_path)
        cursor = conn.cursor()
        cursor.execute(queueSQLQuery)
        rows = cursor.fetchall()
        for row in rows:
            print(row)
        conn.close()

How to use

  • Copy and paste the content and save it as a .py file
  • Run with python [filename].py

Based on the tool by Dan Kelly.

Reza Rafati https://cyberwarzone.com

Reza Rafati, based in the Netherlands, is the founder of Cyberwarzone.com. An industry professional providing insightful commentary on infosec, cybercrime, cyberwar, and threat intelligence, Reza dedicates his work to bolster digital defenses and promote cyber awareness.

You May Also Like

More From Author