Автоматический поиск связанных между собой сайтов по кодам отслеживания

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

Пару лет назад Лоуренс Александр опубликовал отличную статью о том, как найти связанные между собой сайты при помощи кодов Google Analytics (и других кодов). А я в прошлом году написал пост про то, как автоматизировать поиск некоторых данных при помощи программы на Python и как представить результаты поиска в наглядном виде. К сожалению, интерфейс API на Meanpath.com теперь недоступен, и этот метод больше не работает. Хорошо, что со Spyonweb.com ничего не случилось, а тут как раз один журналист из Южной Африки, Ян Кронье, затеял расследование, для которого ему нужно было найти связанные друг с другом сайты (читайте здесь – на англ.). Так у нас появилась прекрасная возможность подправить программу таким образом, чтобы она работала со SpyOnWeb, а потом отыскать связанные сайты и отобразить их в виде графика. Давайте-ка разомнем пальцы и посмотрим, как можно автоматизировать поиск связи между сайтами при помощи несложной программки.

A few years ago Lawrence Alexander published a great piece on finding connections between websites using Google Analytics (among others) codes. Last year I had published a post where I taught you how to automatically mine some of this information using Python, and then how to visualize it. Unfortunately the Meanpath API was closed down, and this technique no longer worked.Thankfully, one service that continued to work great was Spyonweb.com and it just so happened that a South African journalist, Jan Cronje, was working on digging out some connections for a story he was working on, read it here. This was a perfect opportunity to retool the previous code to use Spyonweb to find these connections, and to build some sweet graphs out of the result.Get your coding fingers warmed up, and get ready to have some fun as we explore how to automatically discover links between websites using some handcrafted Python.

Интерфейс API SpyOnWeb

Есть такой сайт SpyOnWeb.com, и занимается он тем, что постоянно прочесывает Интернет и разыскивает коды отслеживания, серверы имен и другую информацию, при помощи которой можно найти связанные друг с другом сайты. Там можно приобрести разные варианты API, от бесплатного (который вполне подходит для наших целей) до всяких платных, которые позволяют делать большое количество запросов в месяц.

Заходим на https://api.spyonweb.com/

Заводим учетную запись. На главной панели управления API (Dashboard) указан ключ доступа, который понадобится нам для дальнейшей работы:

Note that you should not share your access token with anyone else, and if you accidentally leak it just click the little button near the red arrow shown and it will regenerate your token for you.

Now that we have our SpyOnWeb token, let’s start writing the code for this post.

Prerequisites

You will need a couple of Python libraries for this blog post. To get them use pip to install:

Если в конце хотите сделать наглядную схему для отображения результатов, скачайте программный инструмент Gephi – вот тут.

Пишем код

Ну что, программисты, разминайте пальцы, запускайте свою любимую IDE (я пользуюсь WingIDE – отличная среда!) и создавайте новый файл под названием website_connections.py . Исходный код целиком можно загрузить здесь.

  • Строки 1-5: импортируем все модули Python, которые нам понадобятся.
  • Строки 7-8: определяем переменную spyonweb_access_token, в которую затем нужно будет вставить код доступа (о нем мы говорили в предыдущем разделе), и присваиваем другой переменной базовый URL-адрес для запросов API Spyonweb (8).
  • Строки 10-11: регулярные выражения, при помощи которых мы настраиваем шаблоны для Google Adsense и Google Analytics. Коды будут извлечены из доменов, которые мы укажем в программе.
  • Строки 13-20: прописываем способ разбора аргумента командной строки, чтобы можно было указать домен или файл со списком доменов, а также присвоить имя файлу с графиком.

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

Отлично! Теперь пропишем первую функцию для извлечения кодов отслеживания непосредственно из интересующих нас доменов. Печатаем следующий фрагмент кода:

  • Строка 38: присваиваем функции extract_tracking_codes в качестве аргумента список доменов, из которых будем извлекать коды.
  • Строки 43-57: проходим список доменов (43) и составляем URL-адрес (50-51), затем направляем запрос к соответствующему домену (53). Если получить доступ к сайту не удалось, то просто переходим к следующему домену (57).
  • Строки 62-64: если доступ к сайту получен, создаем пустой список, в который будем вносить найденные коды (62). Мы попытаемся найти все коды Google Adsense при помощи регулярного выражения (63), а потом сделаем то же самое для кодов Google Analytics (64).
  • Строки 67-79: проходим список извлеченных кодов (67) и по очереди приводим в порядок каждый из них при помощи функции clean_tracking_code (70). Проверяем, не попадался ли нам этот код раньше (72), и если нет, то добавляем его в словарь connections, чтобы его потом можно было найти по домену, к которому мы отправили соответствующий запрос.
  • Строка 82: возвращаем словарь connections, чтобы обработать результаты позднее.

Теперь настроим функцию для отправки запросов к API Spyonweb. Продолжаем с того места, где закончили:

  • Строка 87: присваиваем функции spyonweb_request в качестве аргумента data – данные, которые могут представлять собой доменное имя, код отслеживания или любую другую информацию, которую принимает Spyonweb. Настраиваем параметр request_type, который будет отвечать за часть URL-адреса, чтобы тот соответствовал формату Spyonweb.
  • Строки 89-90: создаем словарь params, в котором будет находиться access_token – наш ключ доступа к API Spyonweb. Этот словарь также будет передаваться в запросе HTTP к Spyonweb.
  • Строка 92: отправляем запрос к Spyonweb, используя составленный ранее URL-адрес, а также передаем словарь params.
  • Строки 94-102: проверяем, удалось ли нам получить ответ (94), и если все сработало, разбираем JSON (96). Проверяем ответ по словарю (98), чтобы узнать, получены ли результаты запроса к Spyonweb, и если результаты есть, возвращаем весь словарь полностью. Если результатов нет, печатаем «None» («Нет») (102).

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

  • Строка 107: функция spyonweb_analytics_codes принимает в качестве аргумента параметр connections – словарь, где указаны коды отслеживания и их связь с соответствующими доменами.
  • Строки 111-120: проходим ключи connections (которые представляют собой коды отслеживания) (111) и проверяем, какого типа этот код – Adsense (114) или Analytics (118). Определив тип кода, настраиваем request_type соответствующим образом.
  • Строка 124: направляем запрос к API Spyonweb, чтобы найти другие домены, связанные с текущим кодом отслеживания.
  • Строки 126-134: если запрос к Spyonweb дал результаты (126), проходим каждый домен (128) и добавляем его в список доменов, связанных с текущим кодом отслеживания (132). После этого возвращаем обновленный словарь connections (134).

Теперь добавим функцию, которая позволит нам извлекать информацию о доменах с сайта Spyonweb. Она может содержать данные о дополнительных кодах AdSense или Analytics, связанных с определенным доменом, а также, в некоторых случаях, выводить на другие связанные домены, представляющие интерес для нашего расследования.

  • Строка 139: присваиваем функции spyonweb_domain_reports в качестве аргумента параметр connections (наш основной словарь, которым мы пользовались до настоящего момента).
  • Строки 142-143: создаем новый список, чтобы заносить в него домены, которые уже были проверены (142), и включаем в него все коды отслеживания (143).
  • Строки 145-155: проходим список кодов (145) и каждый домен, связанный с определенным кодом (147). Если домен еще не был проверен (149), добавляем его в список tested-domains (151) и направляем запрос к Spyonweb, чтобы получить информацию об этом домене (155).
  • Строки 157-170: если запрос к Spyonweb дает результат (157), проверяем наличие кодов Adsense (160). Если они есть (162), прорабатываем все найденные коды Adsense (164), приводим их в надлежащий вид (166), и если этих кодов еще нет в словаре connections (168), добавляем их в качестве новых ключей (170).
  • Строки 172-178: прорабатываем домены, связанные с кодом Adsense (172), и если домен еще не был проверен (174), добавляем его в словарь connections рядом с текущим кодом отслеживания.

Следующая часть кода очень похожа на отрезки 157–170 и 172–178 – мы делаем все то же самое, только на этот раз для кодов Google Analytics. Пуристы, конечно, начнут жаловаться, что мы повторяемся, печатая тот же самый код, но что поделать.

Пришло время добавить в нашу программу последнюю функцию, которая поможет нам наглядно представить связь между доменными именами и кодами отслеживания, так, чтобы можно открыть графический файл в Gephi (или другом схожем редакторе) и полюбоваться на результат.

  • Строка 205: функции graph_connections в качестве аргумента присваиваем словарь connections, над которым мы отлично поработали и который привели в надлежащий вид, и список исходных доменов domains, а также указываем имя, которое хотим присвоить файлу с графиком.
  • Строка 207: создаем новый объект networkx Graph.
  • Строки 209-212: проходим по очереди каждый ключ – код отслеживания в словаре connections (209) и добавляем каждый код в график в качестве центрального узла, а атрибутам задаем тип type, который обозначается как tracking_code. Нам это понадобится позже для того, чтобы раскрасить график в Gephi в разные цвета.
  • Строки 214-227: прорабатываем каждый домен, связанный с текущим кодом отслеживания (214), смотрим, является ли он одним из исходных доменов (217), и если да, то добавляем его в график в качестве узла и указываем тип source_domain. Если домен не входит в число исходных (221), добавляем его в график в качестве обычного домена domain (224). Последнее, что нужно сделать – добавить линию между кодом отслеживания и доменом (227).
  • Строка 230: мы внесли в график все коды и домены и соединили их линиями, а теперь сохраняем график в файл при помощи функции write_gexf.

Добавим последние отрезки кода, связывающие все функции вместе. Мы почти закончили!

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

  • Строка 249: для начала вызываем функцию extract_tracking_codes, которая запустит наш любимый словарь connections.
  • Строки 251-260: при обнаружении кодов отслеживания (251) ищем их на Spyonweb (254) и запрашиваем у Spyonweb данные о домене (257). И, наконец, вызываем функцию graph_connections, чтобы создать графический файл (260).

Вот и все! Давайте введем в программу реальные данные и проверим, как она работает.

Погнали!

Запустим программу вот с такими аргументами командной строки:

[*] Checking southafricabuzz.co.za for tracking codes (Поиск кодов отслеживания на southafricabuzz.co.za).
[*] Discovered (Обнаружено): pub-8264869885899896
[*] Discovered (Обнаружено): pub-8264869885899896
[*] Discovered (Обнаружено): ua-101199457-1
[*] Trying code: UA-101199457 on Spyonweb (Поиск кода UA-101199457 на Spyonweb).
[*] Trying code: pub-8264869885899896 on Spyonweb (Поиск кода pub-8264869885899896 на Spyonweb).
[*] Found additional domain (Обнаружен дополнительный домен): www.indiatravelmantra.com
[*] Found additional domain (Обнаружен дополнительный домен): www.societyindia.com

[*] Discovered new domain (Обнаружен новый домен): 022office.com
[*] Getting domain report for (Запрос данных о домене): indiayatraa.com
[*] Getting domain report for (Запрос данных о домене): www.mantraa.com
[*] Wrote out graph to southafrica.gexf (График сохранен в файл southafrica.gexf)
[*] Готово! Откройте файл southafrica.gexf в Gephi и полюбуйтесь на результат работы!

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

Для закрепления пройденного материала добавьте пару вещей, чтобы сделать программу еще лучше. Например, запрограммируйте запрос к ресурсу Wayback Machine, чтобы найти все коды отслеживания, которые когда-либо были у определенного сайта (см. вот этот пост), или создайте рекурсивную функцию, которая будет запрашивать у Spyonweb данные по каждому новому домену, который вам удастся найти. В результате может получиться довольно большой график, но зато и зона охвата увеличится.

Вопросы? Комментарии? Пишите мне на электронку! justin@automatingosint.com