расследования, открытые для каждого

Что можно найти в открытых источниках при помощи электронных адресов, извлеченных из базы данных Skype

23.11.16

Justin Seitz

Язык: English

Эта статья была впервые опубликована в блоге AutomatingOSINT.com.

Надо признаться, я плохо владею компьютерно-технической экспертизой по сравнению с большинством профессиональных судебных экспертов. Это же просто невероятно, какое количество данных они извлекают из найденных доказательств: адреса электронной почты, номера телефонов, имена пользователей, профили в социальных сетях, изображения – и это еще не все! Мне пришла в голову мысль, что было бы здорово поискать все эти данные в открытых источниках информации, чтобы больше узнать об анализируемом устройстве и его владельце. В итоге я обратился к нескольким гуру судебной экспертизы (спасибо вам, Шафик Пунджа и Жак Буше!) и расспросил их о надежных источниках на жестком диске, данные из которых можно было бы использовать в запросах к онлайн-сервисам, чтобы таким образом получить дополнительные полезные сведения. Жак рассказал мне, что Skype хранит информацию о пользователе в базе SQLite и что это – настоящий кладезь достоверных данных.

Итак, перед нами стоят две задачи: написать скрипт на Python, который поможет нам экспортировать адреса электронной почты из любой базы данных в формате SQLite, а также освоить Full Contact API, чтобы произвести поиск по найденным адресам в Интернете. В итоге мы получим список всех профилей в социальных сетях, которые связаны с определенным адресом, извлеченным из базы SQLite. За дело!

Python и SQLite

База данных SQLite обладает такими же замечательными характеристиками, как и большинство серверных баз данных, но при этом умещается в одном компактном файле. В Python есть встроенная поддержка SQLite, благодаря которой мы сможем быстро организовать взаимодействие с любым выбранным файлом этого формата. Мы напишем программу для работы с любыми базами данных, которая будет систематически проходить по каждой найденной таблице и проверять каждый столбец на предмет наличия адресов электронной почты, то есть у вас будет возможность искать информацию не только в Skype.

В SQLite есть таблица под названием SQLITE_MASTER, которая определяет схему базы данных. Мы сделаем запрос к этой таблице, чтобы извлечь все таблицы, содержащиеся в базе данных. Затем мы пройдем по каждой таблице и выберем из них все элементы при помощи команды SQL SELECT. Полученные результаты будут представлены в виде столбцов – мы последовательно пройдем по каждому из них, чтобы извлечь адреса электронной почты. Для начала создадим новый файл Python под названием sqlite_parser.py и введем в него следующий код (исходный код можно загрузить здесь):

Screen Shot 2016-05-02 at 6.08.38 AM
  • Строки 1-3: импортируем библиотеки, которые нужны нам для разбора базы данных и получения интересующей нас информации.
  • Строки 8-10: определяем способ разбора аргументов командной строки, указываем расположение файла базы данных, которую мы будем разбирать.
  • Строка 9: создаем пустой список, куда будут сохраняться все совпадения из базы данных.
  • Строка 10: указываем регулярное выражение для поиска адресов электронной почты. Набор не исчерпывающий, но все равно работает. Удобно то, что его можно подстроить под поиск в базе данных SQLite IP-адресов (этим мы займемся во второй части) и информации любого другого типа.

Теперь подключимся к базе данных SQLite, чтобы найти все имеющиеся в ней таблицы:

Screen Shot 2016-05-02 at 6.09.28 AM

Приведу некоторые пояснения:

  • Строка 13: подключаемся к базе данных SQLite, указывая путь к соответствующему файлу. Путь получаем из введенного аргумента командной строки.
  • Строка 14: подключившись, создаем для SQLite объект курсор, при помощи которого мы будем передавать команды.
  • Строка 16: создаем запрос для экспорта всех таблиц из таблицы sqlite_master. Таким образом мы получим список таблиц, которые впоследствии будем проходить по одной.
  • Строка 18: используем функцию fetchall() для возврата результатов запроса из строки 16. В итоге мы получаем список, который мы затем будем прорабатывать и к которому будем делать последующие запросы.

Теперь мы пройдем по каждой таблице, сделаем запрос ко всем содержащимся в ней данным и проработаем каждый столбец, используя регулярное выражение, чтобы извлечь адреса электронной почты. Это относительно длинный фрагмент кода:

Screen Shot 2016-05-02 at 6.18.33 AM
  • Строки 20-27: начинаем прорабатывать (20) список таблиц, выводим сообщение (22), чтобы знать, что происходит, а затем при помощи команды SELECT (25) извлекаем из таблицы все данные. Снова применяем функцию fetchall() (27), чтобы извлечь все записи из запроса SELECT.
  • Строки 29-31: проходим каждую строку (29), а затем – каждый столбец по каждой полученной строке (31).
  • Строки 33-36: применяем регулярное выражение для поиска адресов электронной почты (34), и если ничего не было найдено (36), программа возвращается к строке 33 и производит поиск в следующем столбце.
  • Строки 38-42: проверяем общий список результатов, найденных при помощи регулярного выражения (38), и если данного результата еще нет в этом списке (40), добавляем его туда (42), прежде чем продолжить.

Последние штрихи: закрываем курсор базы данных и выводим все результаты поиска. Добавляем в скрипт следующий фрагмент кода:

Screen Shot 2016-05-02 at 6.19.08 AM
  • Строки 43-44: закрываем курсор (43) и прерываем связь с файлом SQLite (44).
  • Строки 48-49: по очереди проходим и выводим все найденные совпадения.

Отлично! Пришла пора проверить, работает ли наш скрипт. Жак рассказал мне, как найти файлы базы данных SQLite Skype:

Для Mac OS X:

/Users/<your_mac_username>/Library/Application\ Support/Skype/<your_skype_username>/main.db

Для Windows:

%appdata%\Skype\main.db


Погнали!

Запустим программу и посмотрим, что у нас получится. В моем примере файл main.db имеет такое же расположение, как и скрипт Python:

Justins-MacBook-Pro:Desktop justin$ python sqlite_osint.py -d main.db

[*] Сканирование таблицы…DbMeta
[*] Сканирование таблицы…AppSchemaVersion
[*] Сканирование таблицы…Contacts
[*] Сканирование таблицы…LegacyMessages
[*] Сканирование таблицы…Calls
[*] Сканирование таблицы…Accounts
[*] Сканирование таблицы…Transfers

…см. другие сканируемые таблицы

[*] Найдено 68 совпадений.

justin.seitz@gmail.com

… см. 67 других совпадений.

Если вы получили такие же результаты, как описано выше, значит, все работает. Теперь подключим Full Contact API, чтобы поискать извлеченные адреса электронной почты в открытых источниках информации.


Подключаем FullContact

Теперь мы можем экспортировать адреса электронной почты из любой базы данных SQLite. Чтобы извлечь из них как можно больше пользы, мы постараемся найти связанные с ними учетные записи в социальных сетях или другой вид присутствия в Интернете, что поможет нам собрать дополнительную информацию об интересующем нас лице. Мы применим FullContact (агрегатор данных), чтобы произвести поиск по найденным адресам. Информацию обо всех аккаунтах, которые нам удастся найти, будем сохранять в файл CSV, чтобы впоследствии ее можно было проанализировать при помощи Excel или сервиса Fusion Tables Google (данные из CSV можно быстро и просто экспортировать в различные инструменты). Для начала регистрируемся, чтобы получить ключ FullContact API. Затем сохраним наш скрипт sqlite_parser.py как sqlite_fullcontact.py (можно загрузить здесь) и внесем некоторые изменения. Сразу после строки import sqlite3 введем следующий код:

Screen Shot 2016-05-02 at 6.19.48 AM

Здесь мы просто добавляем дополнительные модули и определяем переменную для ключа FullContact API. Если у вас нет библиотеки requests, установите ее при помощи системы управления пакетами pip (см. инструкции в этом видео). Теперь допишем еще один фрагмент кода, начиная со строки 53. Вот этот фрагмент:

Screen Shot 2016-05-02 at 6.20.23 AM

  • Строка 54: создаем дескриптор для файла CSV, в который будем сохранять найденную информацию.
  • Строка 55: указываем наименования ячеек, которые будут присвоены столбцам в таблице с результатами поиска.
  • Строка 56: используем класс DictWriter модуля csv, указывая дескриптор файла, созданный в строке 54, и наименования для шапки таблицы, созданные в строке 55. При помощи класса DictWriter мы сможем заполнять строки таблицы, используя словарь.
  • Строка 57: заполняем верхнюю строку (header) таблицы, присваивая каждому столбцу имя, чтобы было понятно, что к чему.

Теперь наша задача – пройти список результатов, полученный в ходе разбора SQLite, и передать каждый адрес электронной почты в FullContact API, чтобы посмотреть, что удастся найти при помощи этого инструмента. В этом нам поможет следующий код:

Screen Shot 2016-05-02 at 6.21.08 AM
  • Строка 59: этот блок программы будет повторяться, пока мы не дойдем до конца списка адресов электронной почты.
  • Строки 62-63: чтобы зайти в FullContact API, указываем заголовок HTTP XFullContactAPIKey. Для этого мы создаем словарь headers (62), указываем нужный заголовок и значение ключа API (63).
  • Строки 65-68: берем из нашего списка один адрес (65), выводим его (67) и создаем URL, чтобы передать этот адрес в FullContact API (68).
  • Строки 70-72: делаем запрос к FullContact API, подставляя заголовки HTTP в функцию headers (70), выдерживаем паузу в две секунды (72), чтобы соблюсти ограничение скорости передачи, установленное серверами FullContact.

Итак, мы сделали запрос, а теперь пришла пора проверить, что из этого получилось. В случае возврата результатов нам нужно сохранить их в файл CSV. Для этого нам понадобится следующий фрагмент кода:

Screen Shot 2016-05-02 at 6.21.40 AM
  • Строка 74: если FullContact API удалось что-то найти, мы готовы провести проверку на совпадение.
  • Строка 76: при помощи библиотеки requests разбираем JSON с сервера и сохраняем результаты в переменную contact_object .
  • Строка 78: проверяем contact_object (который теперь представляет собой словарь) ключом socialProfiles, чтобы узнать, были ли найдены профили из социальных сетей.
  • Строка 80: на один адрес электронной почты может быть зарегистрировано несколько профилей в разных социальных сетях, они сохраняются в список по ключу socialProfiles. Мы проходим все профили и сохраняем каждый из них в переменную profile.
  • Строки 82-87: создаем пустой словарь под названием record (82) и начинаем заполнять его данными, полученными из FullContact API. Функция get() постарается извлечь все указанные значения (вид сети, ID, имя пользователя, URL), а если искомое значение отсутствует, автоматически возвратит «N/A» («нет данных»).
  • Строка 89: записываем словарь record в файл CSV в качестве новой строки.
  • Строки 91-96: выводим информацию, которую удалось найти, чтобы можно было следить за процессом по мере выполнения скрипта.

Теперь нам нужно предусмотреть дополнительную проверку, чтобы узнать, требуется ли сделать паузу перед тем, как FullContact API вернет результат. Это случается иногда, если честно, я не знаю почему. Мы проверим значение кода возврата HTTP 202 вместо 200, а затем повторно добавим текущий адрес электронной почты в список matches, чтобы не оказалось так, что он не будет сохранен. Обратите внимание на структурирование текста – оно должно быть таким же, как при проверке кода состояния 200:

Screen Shot 2016-05-02 at 6.22.28 AM

Точно так, как показано на картинке. Мы делаем проверку по коду 202, и если он найден, снова добавляем адрес в список адресов электронной почты (на тот случай, если он там не сохранился), а затем делаем паузу 30 секунд. В последней строчке мы просто закрываем дескриптор для файла CSV. Что ж, пришла пора опробовать наш код!


Погнали!

Этот скрипт работает так же, как предыдущий, только результаты поиска будут другим – при условии, что FullContact API что-нибудь найдет:

Justins-MacBook-Pro:Desktop justin$ python sqlite_osint_fullcontact.py -d main.db

[*] Сканирование таблицы…DbMeta
[*] Сканирование таблицы…AppSchemaVersion
[*] Сканирование таблицы…Contacts

[*] Поиск по justin.seitz@gmail.com

Сеть: twitter
Имя пользователя: jms_dot_py
URL: https://twitter.com/jms_dot_py
ID: 817668451

Конечно, совпадений было больше, не только адрес моей электронной почты, но вы и так уже убедились в том, какое множество полезной информации можно получить этим методом, если у вас есть база данных SQLite. В следующей статье я расскажу, как создать карту найденных IP-адресов, чтобы показать вам, насколько гибким является разбор SQLite и как быстро и просто можно адаптировать такие скрипты в зависимости от ситуации. Может, у вас есть какая-нибудь интересная база данных SQLite, из которой можно извлечь кучу полезной информации, как из Skype? Тогда дайте мне знать по электронке – очень хочу опробовать свой метод на такой базе. Спасибо за интерес к этой статье!

Justin Seitz

Джастин Сейц – консультант по безопасности из Канады, автор двух книг для хакеров, выпущенных издательством No Starch Press. Ведет блог на сайте AutomatingOSINT.com. Аккаунт Джастина в Twitter: @jms_dot_py.

Подписаться на рассылку Беллингкэт

Введите адрес электронной почты, чтобы получать еженедельный дайджест статей Беллингкэт, ссылки на другие открытые исследования и многое другое.

Поддержать Беллингкэт

Вы можете оказать поддержку Беллингкэт отправив пожертвование через данную ссылку:

Ответить

  • (будет скрыто)