Python Digital Network Forensics-I
Este capítulo explicará los fundamentos involucrados en la realización de análisis forense de redes usando Python.
Comprensión del análisis forense de redes
El análisis forense de redes es una rama del análisis forense digital que se ocupa del seguimiento y análisis del tráfico de redes informáticas, tanto local como WAN (red de área amplia), con el fin de recopilar información, recopilar pruebas o detectar intrusiones. El análisis forense de redes juega un papel fundamental en la investigación de delitos digitales, como el robo de propiedad intelectual o la filtración de información. Una imagen de las comunicaciones de red ayuda a un investigador a resolver algunas preguntas cruciales de la siguiente manera:
¿A qué sitios web se ha accedido?
¿Qué tipo de contenido se ha subido a nuestra red?
¿Qué tipo de contenido se ha descargado de nuestra red?
¿A qué servidores se accede?
¿Alguien envía información confidencial fuera de los firewalls de la empresa?
Buscador de pruebas de Internet (IEF)
IEF es una herramienta forense digital para encontrar, analizar y presentar evidencia digital encontrada en diferentes medios digitales como computadoras, teléfonos inteligentes, tabletas, etc. Es muy popular y utilizada por miles de profesionales forenses.
Uso de IEF
Debido a su popularidad, IEF es utilizado en gran medida por profesionales forenses. Algunos de los usos de IEF son los siguientes:
Debido a sus poderosas capacidades de búsqueda, se utiliza para buscar múltiples archivos o medios de datos simultáneamente.
También se utiliza para recuperar datos eliminados del espacio no asignado de RAM a través de nuevas técnicas de tallado.
Si los investigadores desean reconstruir las páginas web en su formato original en la fecha en que se abrieron, pueden usar IEF.
También se utiliza para buscar volúmenes de discos físicos o lógicos.
Volcado de informes de IEF a CSV usando Python
IEF almacena datos en una base de datos SQLite y el siguiente script de Python identificará dinámicamente las tablas de resultados dentro de la base de datos IEF y las volcará a los archivos CSV respectivos.
Este proceso se realiza en los pasos que se muestran a continuación
Primero, genere la base de datos de resultados IEF que será un archivo de base de datos SQLite que terminará con la extensión .db.
Luego, consulta esa base de datos para identificar todas las tablas.
Por último, escriba estas tablas de resultados en un archivo CSV individual.
Código Python
Veamos cómo usar el código Python para este propósito:
Para la secuencia de comandos de Python, importe las bibliotecas necesarias de la siguiente manera:
from __future__ import print_function
import argparse
import csv
import os
import sqlite3
import sys
Ahora, debemos proporcionar la ruta al archivo de base de datos IEF:
if __name__ == '__main__':
parser = argparse.ArgumentParser('IEF to CSV')
parser.add_argument("IEF_DATABASE", help="Input IEF database")
parser.add_argument("OUTPUT_DIR", help="Output DIR")
args = parser.parse_args()
Ahora, confirmaremos la existencia de la base de datos IEF de la siguiente manera:
if not os.path.exists(args.OUTPUT_DIR):
os.makedirs(args.OUTPUT_DIR)
if os.path.exists(args.IEF_DATABASE) and \ os.path.isfile(args.IEF_DATABASE):
main(args.IEF_DATABASE, args.OUTPUT_DIR)
else:
print("[-] Supplied input file {} does not exist or is not a " "file".format(args.IEF_DATABASE))
sys.exit(1)
Ahora, como hicimos en scripts anteriores, realice la conexión con la base de datos SQLite de la siguiente manera para ejecutar las consultas a través del cursor:
def main(database, out_directory):
print("[+] Connecting to SQLite database")
conn = sqlite3.connect(database)
c = conn.cursor()
Las siguientes líneas de código obtendrán los nombres de las tablas de la base de datos:
print("List of all tables to extract")
c.execute("select * from sqlite_master where type = 'table'")
tables = [x[2] for x in c.fetchall() if not x[2].startswith('_') and not x[2].endswith('_DATA')]
Ahora, seleccionaremos todos los datos de la tabla y usando fetchall() en el objeto cursor almacenaremos la lista de tuplas que contienen los datos de la tabla en su totalidad en una variable -
print("Dumping {} tables to CSV files in {}".format(len(tables), out_directory))
for table in tables:
c.execute("pragma table_info('{}')".format(table))
table_columns = [x[1] for x in c.fetchall()]
c.execute("select * from '{}'".format(table))
table_data = c.fetchall()
Ahora, usando CSV_Writer() método escribiremos el contenido en un archivo CSV -
csv_name = table + '.csv'
csv_path = os.path.join(out_directory, csv_name)
print('[+] Writing {} table to {} CSV file'.format(table,csv_name))
with open(csv_path, "w", newline = "") as csvfile:
csv_writer = csv.writer(csvfile)
csv_writer.writerow(table_columns)
csv_writer.writerows(table_data)
El script anterior obtendrá todos los datos de las tablas de la base de datos IEF y escribirá el contenido en el archivo CSV de nuestra elección.
Trabajar con datos en caché
De la base de datos de resultados de IEF, podemos obtener más información que no es necesariamente compatible con IEF. Podemos obtener los datos almacenados en caché, un producto bi para información, de proveedores de servicios de correo electrónico como Yahoo, Google, etc., utilizando la base de datos de resultados IEF.
El siguiente es el script de Python para acceder a la información de datos en caché del correo de Yahoo, al que se accede en Google Chrome, mediante la base de datos IEF. Tenga en cuenta que los pasos serían más o menos los mismos que se siguieron en el último script de Python.
Primero, importe las bibliotecas necesarias para Python de la siguiente manera:
from __future__ import print_function
import argparse
import csv
import os
import sqlite3
import sys
import json
Ahora, proporcione la ruta al archivo de base de datos IEF junto con dos argumentos posicionales que acepta el controlador de línea de comandos como se hizo en el último script:
if __name__ == '__main__':
parser = argparse.ArgumentParser('IEF to CSV')
parser.add_argument("IEF_DATABASE", help="Input IEF database")
parser.add_argument("OUTPUT_DIR", help="Output DIR")
args = parser.parse_args()
Ahora, confirme la existencia de la base de datos IEF de la siguiente manera:
directory = os.path.dirname(args.OUTPUT_CSV)
if not os.path.exists(directory):os.makedirs(directory)
if os.path.exists(args.IEF_DATABASE) and \ os.path.isfile(args.IEF_DATABASE):
main(args.IEF_DATABASE, args.OUTPUT_CSV)
else: print("Supplied input file {} does not exist or is not a " "file".format(args.IEF_DATABASE))
sys.exit(1)
Ahora, realice la conexión con la base de datos SQLite de la siguiente manera para ejecutar las consultas a través del cursor:
def main(database, out_csv):
print("[+] Connecting to SQLite database")
conn = sqlite3.connect(database)
c = conn.cursor()
Puede utilizar las siguientes líneas de código para obtener las instancias del registro de caché de contactos de Yahoo Mail:
print("Querying IEF database for Yahoo Contact Fragments from " "the Chrome Cache Records Table")
try:
c.execute("select * from 'Chrome Cache Records' where URL like " "'https://data.mail.yahoo.com" "/classicab/v2/contacts/?format=json%'")
except sqlite3.OperationalError:
print("Received an error querying the database -- database may be" "corrupt or not have a Chrome Cache Records table")
sys.exit(2)
Ahora, la lista de tuplas devuelta por la consulta anterior se guardará en una variable de la siguiente manera:
contact_cache = c.fetchall()
contact_data = process_contacts(contact_cache)
write_csv(contact_data, out_csv)
Tenga en cuenta que aquí utilizaremos dos métodos a saber process_contacts() para configurar la lista de resultados, así como para iterar a través de cada registro de caché de contacto y json.loads() para almacenar los datos JSON extraídos de la tabla en una variable para su posterior manipulación -
def process_contacts(contact_cache):
print("[+] Processing {} cache files matching Yahoo contact cache " " data".format(len(contact_cache)))
results = []
for contact in contact_cache:
url = contact[0]
first_visit = contact[1]
last_visit = contact[2]
last_sync = contact[3]
loc = contact[8]
contact_json = json.loads(contact[7].decode())
total_contacts = contact_json["total"]
total_count = contact_json["count"]
if "contacts" not in contact_json:
continue
for c in contact_json["contacts"]:
name, anni, bday, emails, phones, links = ("", "", "", "", "", "")
if "name" in c:
name = c["name"]["givenName"] + " " + \ c["name"]["middleName"] + " " + c["name"]["familyName"]
if "anniversary" in c:
anni = c["anniversary"]["month"] + \"/" + c["anniversary"]["day"] + "/" + \c["anniversary"]["year"]
if "birthday" in c:
bday = c["birthday"]["month"] + "/" + \c["birthday"]["day"] + "/" + c["birthday"]["year"]
if "emails" in c:
emails = ', '.join([x["ep"] for x in c["emails"]])
if "phones" in c:
phones = ', '.join([x["ep"] for x in c["phones"]])
if "links" in c:
links = ', '.join([x["ep"] for x in c["links"]])
Ahora, para la empresa, el título y las notas, el método de obtención se utiliza como se muestra a continuación:
company = c.get("company", "")
title = c.get("jobTitle", "")
notes = c.get("notes", "")
Ahora, agreguemos la lista de metadatos y elementos de datos extraídos a la lista de resultados de la siguiente manera:
results.append([url, first_visit, last_visit, last_sync, loc, name, bday,anni, emails, phones, links, company, title, notes,total_contacts, total_count])
return results
Ahora, usando CSV_Writer() método, escribiremos el contenido en un archivo CSV -
def write_csv(data, output):
print("[+] Writing {} contacts to {}".format(len(data), output))
with open(output, "w", newline="") as csvfile:
csv_writer = csv.writer(csvfile)
csv_writer.writerow([
"URL", "First Visit (UTC)", "Last Visit (UTC)",
"Last Sync (UTC)", "Location", "Contact Name", "Bday",
"Anniversary", "Emails", "Phones", "Links", "Company", "Title",
"Notes", "Total Contacts", "Count of Contacts in Cache"])
csv_writer.writerows(data)
Con la ayuda del script anterior, podemos procesar los datos almacenados en caché del correo de Yahoo utilizando la base de datos IEF.