Pythonデジタルネットワークフォレンジック-I

この章では、Pythonを使用してネットワークフォレンジックを実行する際の基本事項について説明します。

ネットワークフォレンジックを理解する

ネットワークフォレンジックは、情報収集、証拠収集、または侵入検知を目的として、ローカルとWAN(ワイドエリアネットワーク)の両方のコンピュータネットワークトラフィックの監視と分析を扱うデジタルフォレンジックのブランチです。ネットワークフォレンジックは、知的財産の盗難や情報漏えいなどのデジタル犯罪の調査において重要な役割を果たします。ネットワーク通信の写真は、調査員が次のようにいくつかの重要な質問を解決するのに役立ちます-

  • どのWebサイトにアクセスしましたか?

  • 私たちのネットワークにはどのようなコンテンツがアップロードされていますか?

  • 私たちのネットワークからどのようなコンテンツがダウンロードされましたか?

  • どのサーバーにアクセスしていますか?

  • 誰かが会社のファイアウォールの外に機密情報を送信していますか?

インターネットエビデンスファインダー(IEF)

IEFは、コンピューター、スマートフォン、タブレットなどのさまざまなデジタルメディアで見つかったデジタル証拠を検索、分析、提示するためのデジタルフォレンジックツールです。非常に人気があり、何千人ものフォレンジック専門家によって使用されています。

IEFの使用

その人気のために、IEFは法医学の専門家によって大いに使用されています。IEFの用途のいくつかは次のとおりです-

  • その強力な検索機能により、複数のファイルまたはデータメディアを同時に検索するために使用されます。

  • また、新しいカービング技術を通じて、RAMの未割り当て領域から削除されたデータを回復するためにも使用されます。

  • 調査員がWebページを開いた日に元の形式で再構築したい場合は、IEFを使用できます。

  • また、論理または物理ディスクボリュームの検索にも使用されます。

Pythonを使用してIEFからCSVにレポートをダンプする

IEFはデータをSQLiteデータベースに保存し、次のPythonスクリプトはIEFデータベース内の結果テーブルを動的に識別し、それぞれのCSVファイルにダンプします。

このプロセスは、以下に示す手順で実行されます。

  • まず、拡張子が.dbのSQLiteデータベースファイルとなるIEF結果データベースを生成します。

  • 次に、そのデータベースにクエリを実行して、すべてのテーブルを識別します。

  • 最後に、この結果テーブルを個々のCSVファイルに書き込みます。

Pythonコード

この目的のためにPythonコードを使用する方法を見てみましょう-

Pythonスクリプトの場合、必要なライブラリを次のようにインポートします-

from __future__ import print_function

import argparse
import csv
import os
import sqlite3
import sys

ここで、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()

ここで、IEFデータベースの存在を次のように確認します。

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)

ここで、以前のスクリプトで行ったように、次のようにSQLiteデータベースに接続して、カーソルを介してクエリを実行します-

def main(database, out_directory):
   print("[+] Connecting to SQLite database")
   conn = sqlite3.connect(database)
   c = conn.cursor()

次のコード行は、データベースからテーブルの名前をフェッチします-

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')]

次に、テーブルからすべてのデータを選択します。 fetchall() カーソルオブジェクトのメソッドは、テーブルのデータ全体を含むタプルのリストを変数に格納します-

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()

さて、 CSV_Writer() 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)

上記のスクリプトは、IEFデータベースのテーブルからすべてのデータをフェッチし、選択したCSVファイルにコンテンツを書き込みます。

キャッシュされたデータの操作

IEF結果データベースから、IEF自体で必ずしもサポートされていないより多くの情報を取得できます。IEF結果データベースを使用して、Yahoo、Googleなどの電子メールサービスプロバイダーから、情報の副産物であるキャッシュデータを取得できます。

以下は、IEFデータベースを使用して、GoogleChromeでアクセスされるYahooメールからキャッシュされたデータ情報にアクセスするためのPythonスクリプトです。手順は、最後のPythonスクリプトで実行した手順とほぼ同じであることに注意してください。

まず、Pythonに必要なライブラリを次のようにインポートします-

from __future__ import print_function
import argparse
import csv
import os
import sqlite3
import sys
import json

ここで、IEFデータベースファイルへのパスと、最後のスクリプトで行ったようにコマンドラインハンドラーによって受け入れられる2つの位置引数を指定します。

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()

ここで、IEFデータベースの存在を次のように確認します-

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)

ここで、次のようにSQLiteデータベースに接続して、カーソルを介してクエリを実行します-

def main(database, out_csv):
   print("[+] Connecting to SQLite database")
   conn = sqlite3.connect(database)
   c = conn.cursor()

次のコード行を使用して、Yahooメールの連絡先キャッシュレコードのインスタンスをフェッチできます-

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)

ここで、上記のクエリから返されたタプルのリストは、次のように変数に保存されます。

contact_cache = c.fetchall()
contact_data = process_contacts(contact_cache)
write_csv(contact_data, out_csv)

ここでは、2つの方法を使用することに注意してください。 process_contacts() 結果リストを設定し、各連絡先キャッシュレコードを反復処理します。 json.loads() テーブルから抽出されたJSONデータを変数に保存してさらに操作する-

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"]])

会社、タイトル、メモの場合、getメソッドは次のように使用されます-

company = c.get("company", "")
title = c.get("jobTitle", "")
notes = c.get("notes", "")

ここで、メタデータと抽出されたデータ要素のリストを次のように結果リストに追加しましょう。

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

さて、 CSV_Writer() メソッド、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)

上記のスクリプトの助けを借りて、IEFデータベースを使用してYahooメールからキャッシュされたデータを処理できます。