Хабрахабр

[Из песочницы] Как я НЕ просканировал Белорусский интернет

Предисловие

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

выполнить пассивную разведку по IP и открытым портам ну и в довесок собрать немного другой полезной информации для формирования некой общей статистики по уровню защищенности относительно сайтов и пользователей.
У меня был скорее немного другой интерес — попробовать определить все актуальные сайты в доменной зоне BY разными методиками, определить стек используемых технологий, через сервисы вроде Shodan, VirusTotal и др.

Вводная и наш инструментарий

План в самом начале был простой — обратиться к местному регистратору за списком актуальных зарегистрированных доменов, далее все проверить на доступность и начинать изучать функционирующие сайты. В реальности всё оказалось куда сложнее — такого рода информацию естественно, никто предоставлять не захотел, за исключением официальной странички статистики актуальных зарегистрированных доменных имен в зоне BY (порядка 130 тысяч доменов). Если такой информации нет, значит придется собирать самостоятельно.

Из наиболее популярного, использовались следующие тулзы: По инструментарию на самом деле все довольно просто — смотрим в сторону open source, что-то всегда можно дописать, допилить какие-то минимальные костыли.

Начало активностей: Отправная точка

В качестве вводной как я уже говорил — в идеале подходили доменные имена, но где их взять? Стартовать нужно с чего-то попроще, в данном случае нам подойдут IP адреса, но опять же — при реверс лукапах не всегда можно словить все домены, а при сборе хостнеймов — не всегда корректный домен. На данном этапе я стал думать о возможных сценариях сбора такого рода информации, опять же — во внимание еще брался тот факт, что наш бюджет это 5$ на аренду VPS, остальное все должно быть бесплатным.

Наши потенциальные источники информации:

  • IP адреса (ip2location сайт)
  • Поиск доменов по второй части email адреса (но где их взять? Разберемся чуть ниже)
  • Некоторые регистраторы/хостинг провайдеры могут предоставить нам такую информацию в форме поддоменов
  • Сабдомены и их последующий реверс (тут могут помочь Sublist3r и Aquatone)
  • Брутфорс и ручной ввод (долго, муторно, но можно, хотя этот вариант я не использовал)

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

Переходим к делу

В предыдущих статьях информацию об IP адресах брали с IP2LOCATION сайта, я на эти статьи по понятной причине не натыкался (т.к. все действия происходили намного раньше), но тоже пришел к данному ресурсу. Правда, в моем случае подход отличался — я решил не забирать к себе локально базу и не извлекать информацию из CSV, а решил мониторить изменения непосредственно на сайте, на постоянной основе и в качестве основной базы откуда все последующие скрипты будут брать цели — сделал таблицу с IP адресами в разных форматах: CIDR, список «от» и «до», пометка страны (на всякий случай), AS Number, AS Description.

Для получения этой информации я обращался к сервису IpToASN, у них есть удобное API (с ограничениями), которое по сути надо просто к себе интегрировать. Формат не самый оптимальный, но для демки и разовой акции меня вполне устраивал, а дабы на постоянной основе не обращаться за вспомогательной информацией вроде ASN, я решил ее дополнительно логировать у себя.

Код для парсинга IP

function ipList() \.\d{1,3}\.\d{1,3}\.\d{1,3}\<\/td\>\s+\<td\>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/", $ipList, $matches); return $matches[0];
} function iprange2cidr($ipStart, $ipEnd){ if (is_string($ipStart) || is_string($ipEnd)){ $start = ip2long($ipStart); $end = ip2long($ipEnd); } else{ $start = $ipStart; $end = $ipEnd; } $result = array(); while($end >= $start){ $maxSize = 32; while ($maxSize > 0){ $mask = hexdec(iMask($maxSize - 1)); $maskBase = $start & $mask; if($maskBase != $start) break; $maxSize--; } $x = log($end - $start + 1)/log(2); $maxDiff = floor(32 - floor($x)); if($maxSize < $maxDiff){ $maxSize = $maxDiff; } $ip = long2ip($start); array_push($result, "$ip/$maxSize"); $start += pow(2, (32-$maxSize)); } return $result; } $getIpList = ipList();
foreach($getIpList as $item) { $cidr = iprange2cidr($ip[0], $ip[1]);
}

После того, как мы разобрались с IP, нам нужно прогнать всю нашу базу через сервисы reverse lookup, увы без каких либо ограничений — это невозможно, разве что, за деньги.

Из сервисов которые для этого замечательно подходят и удобны в использовании я хочу отметить целых два:

  1. VirusTotal — лимит но частоте обращений с одного API ключа
  2. Hackertarget.com (их API) — лимит по количеству обращений с одного IP

По обходу лимитов получились следующие варианты:

  • В первом случае один из сценариев это выдерживать таймауты в 15 секунд, итого у нас будет 4 обращения в минуту, что сильно может сказаться на нашей скорости и в данной ситуации будет кстати использование 2-3 таких ключей, при этом я бы рекомендовал так же прибегнуть к proxy и менять user-agent.
  • Во втором случае, я писал скрипт для автоматического парсинга базы proxy на основании публично доступной информации, их валидации и последующего использования (но позже от этого варианта отошел т.к. хватало по сути и VirusTotal)

Идем далее и плавно переходим к email адресам. Они так же могут быть источником полезной информации, но где же их собирать? Решение не пришлось искать долго, т.к. в нашем сегменте персональных сайтов пользователи держат мало, а в основной массе это организации — то нам подойдут профильные сайты вроде каталогов интернет магазинов, форумов, условных маркетплейсов.

К примеру беглый осмотр одной из таких вот площадок показал, что очень много пользователей добавляют свои email прямо к себе в публичный профиль и соответственно — это дело можно аккуратно спарсить для последующего использования.

Один из парсеров

#!/usr/bin/env python3 import sys, threading, time, os, urllib, re, requests, pymysql
from html.parser import HTMLParser
from urllib import request
from bs4 import BeautifulSoup # HEADERS CONFIG
headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11.9; rv:42.0) Gecko/20200202 Firefox/41.0' } file = open('dat.html', 'w') def parseMails(uid): page = 'https://profile.onliner.by/user/'+str(uid)+'' cookie = {'onl_session': 'YOUR_SESSION_COOOKIE_HERE'} r = requests.get(page, headers = headers, cookies = cookie) data = BeautifulSoup(r.text) userinfo = data.find_all('dl', {'class': 'uprofile-info'}) find_email = [] for item in userinfo: find_email += str(item.find('a')) get_mail = ''.join(find_email) detect_email = re.compile(".+?>(.+@.+?)</a>").search(get_mail) file.write("<li>('"+detect_email.group(1)+"'),</li>") for uid in range(1, 10000): t = threading.Thread(target=parseMails, args=(uid,)) t.start() time.sleep(0.3)

В подробности парсинга каждой из площадок вдаваться не буду, где-то удобнее угадывать ID пользователя методом перебора, где-то проще распарсить карту сайта, получить из нее информацию о страницах компаний и далее уже собирать адреса из них. После сбора адресов, нам остается выполнить несколько простых операций сразу отсортировав по доменной зоне, сохранив для себя «хвостики» и прогнать для исключения дубликатов по имеющейся базе.

Разведка как мы уже знаем, может быть двух видов — активной и пассивной, в нашем случае — наиболее актуальным будет пассивный подход. На этом этапе я считаю, что с формированием скоупа мы можем заканчивать и переходить к разведке. Наш интерес — это ответы сервера на единственный запрос, в некоторых случаях запросов может быть два (перенаправление с http на https), в более редких — целых три (когда используется www). Но опять же, просто обращение к сайту на 80 или 443 порт без вредоносной нагрузки и эксплуатации уязвимостей — вполне себе легитимное действие.

Разведка

Оперируя такой информацией как домен, мы можем собрать следующие данные:

  • Записи DNS (NS, MX, TXT)
  • Заголовки ответов
  • Определить используемый стек технологий
  • Понять по какому протоколу работает сайт
  • Попробовать определить открытые порты (по базе Shodan / Censys) без прямого сканирования
  • Попробовать определить уязвимости исходя из корреляции информации из Shodan / Censys с базой Vulners
  • Находится ли он в базе вредоносных Google Safe Browsing
  • По домену собрать email адреса, а так же сопоставить уже найденные и проверить по Have I Been Pwned, в дополнение — привязку к социальным сетям
  • Домен — это в некоторых случаях не только лицо компании, но и продукт ее деятельности, email адреса для регистрации на сервисах и т.п., соответственно — можно поискать информацию которая с ними ассоциируется на ресурсах вроде GitHub, Pastebin, Google Dorks (Google CSE)

Всегда можно пойти напролом и воспользоваться как вариант masscan или nmap, zmap, настроив их предварительно через Tor с запуском в рандомное время или даже с нескольких инстансов, но у нас другие цели и из названия следует, что таки прямых сканирований я не делал.

Собираем DNS записи, проверяем возможность амплификации запросов и ошибки конфигурации вроде AXFR:

Пример сбора записей NS серверов

dig ns +short $domain | sed 's/\.$//g' | awk '{print $1}'

Пример сбора записей MX (см. в NS, просто заменить 'ns' на 'mx'

Проверка на AXFR (тут солюшенов существует много, вот еще один костыльный, но не секьюрный, использовал для просмотра аутпутов)

$digNs = trim(shell_exec("dig ns +short $domain | sed 's/\.$//g' | awk '{print $1}'")); $ns = explode("\n", $digNs); foreach($ns as $target) { $axfr = trim(shell_exec("dig -t axfr $domain @$target | awk '{print $1}' | sed 's/\.$//g'")); $axfr = preg_replace("/\;/", "", $axfr); if(!empty(trim($axfr))) { $axfr = preg_replace("/\;/", "", $axfr); $res = json_encode(explode("\n", trim($axfr)));

Проверка на DNS Amplification

dig +short test.openresolver.com TXT @$dns

В моем случае NS сервера брались из БД, по тому на конце переменная, туда можно подставить просто любой сервер по сути. По поводу корректности результатов данного сервиса — не могу быть уверен, что там прям на 100% все ровно работает и результаты всегда валидны, но, надеюсь, что большинство результатов — реальны.

Если нам для каких либо целей нужно сохранять у себя полноценный конечный URL к сайту, для этого я воспользовался cURL:

curl -I -L $target | awk '/Location/{print $2}'

Он сам перейдет по всем редиректом и выведет финальный, т.е. актуальный URL сайта. В моем случае это было крайне полезно при последующем использовании такой тулы как WhatWeb.

Дабы определить используемую OS, веб-сервер, CMS сайта, какие-то заголовки, дополнительные модули вроде JS / HTML библиотек/фреймворков, а так же тайтл сайта по которому впоследствии можно попробовать отфильтровать к тому же и по сфере деятельности. Для чего нам использовать его?

Очень удобным вариантом в данном случае будет экспорт результатов работы тула в формате XML для последующего разбора и импорта в БД если есть цель это все в последствии обрабатывать.

whatweb --no-errors https://www.mywebsite.com --log-xml=results.xml

Для себя я на выходе делал по итогу JSON и его уже складывал в БД.

К слову о заголовках, можно почти тоже самое выполнять и обычным cURL выполняя запрос вида:

curl -I https://www.mywebsite.com

В заголовках отлавливать самостоятельно информацию о CMS и веб-серверах с помощью регулярных выражений к примеру.

Конечно же, с точностью при таком раскладе могут быть проблемы, все же это не прямое сканирование с ручной валидацией, а банальное «жонглирование» данными из сторонних источников, но лучше хотя бы так чем совсем ничего. Кроме стека из полезного, мы так же можем выделить возможность сбора информации об открытых портах с помощью Shodan и далее уже используя полученные данные — выполнить проверку по базе Vulners с помощью их API (ссылки на сервисы приведены в шапке).

PHP функция для Shodan

function shodanHost($host) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://api.shodan.io/shodan/host/".$host."?key=<YOUR_API_KEY>"); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $shodanResponse = curl_exec($ch); curl_close ($ch); return json_decode($shodanResponse);
}

Пример такого сравнительного анализа #1

Пример #2

Да, раз уж заговорили за API, то у Vulners есть ограничения и наиболее оптимальным решением будет — использование их скрипта на Python, там без кручений-верчений все будет отлично работать, в случае с PHP столкнулся с некоторыми небольшими трудностями (опять же — доп. таймауты спасли ситуацию).

При тестировании этой замечательной тулы заметил одну интересность, не всегда с первого раза получалось определить тип используемого файрвола. Одним из последних тестов — будем изучать информацию по используемым firewall с помощью такого скрипта как «wafw00f».

Чтобы посмотреть какие типы файрволов потенциально может определить wafw00f можно ввести следующую команду:

wafw00f -l

Для определения типа файрвола — wafw00f анализирует заголовки ответа сервера после отправки стандартного запроса к сайту, в случае если данной попытки не достаточно, он формирует дополнительный простой тестовый запрос ну и если этого в очередной раз не достаточно — то третья методика оперирует данными после первых двух попыток.

нам для статистики по сути весь ответ не нужен, то все лишнее мы обрезаем регулярным выражением и оставляем лишь название firewall: Т.к.

/is\sbehind\sa\s(.+?)\n/

Ну и как я ранее писал — кроме информации о домене и сайте, так же в пассивном режиме актуализировалась информация о email адресах и социальных сетях:

Статистика по email определенных на базе домена

Пример определения привязки социальных сетей к email адресу

Самым простым было разобраться с валидацией адресов в Twitter (2 способа), с Facebook (1 способ) в этом плане оказалось немного сложнее из-за чуть более замысловатой системы генерации сессии реального пользователя.

Перейдем к сухой статистике

Статистика по DNS

Провайдер — сколько сайтов
ns1.tutby.com: 10899
ns2.tutby.com: 10899
ns1.neolocation.com: 4877
ns2.neolocation.com: 4873
ns3.neolocation.com: 4572
ns1.activeby.net: 4231
ns2.activeby.net: 4229
u1.hoster.by: 3382
u2.hoster.by: 3378

Уникальных DNS обнаружено: 2462
Уникальных MX (почтовых) серверов: 9175 (кроме популярных сервисов, есть достаточное количество администраторов которые используют собственные почтовые службы)
Подвержены DNS Zone Transfer: 1011
Подвержены DNS Amplification: 531
Немного любителей CloudFlare: 375 (основываясь на используемых записях NS)

Статистика по CMS

CMS — Количество
WordPress: 5118
Joomla: 2722
Bitrix: 1757
Drupal: 898
OpenCart: 235
DataLife: 133
Magento: 32

  • Потенциально уязвимых установок WordPress: 2977
  • Потенциально уязвимых установок Joomla: 212
  • При помощи сервиса Google SafeBrowsing получилось выявить потенциально опасных или зараженных сайтов: около 10.0000 (в разное время, кто-то фиксил, кого-то видимо ломали, статистика не совсем объективная)
  • Про HTTP и HTTPS — последним пользуется менее половины сайтов от найденного объема, но с учетом того, что моя база не полная, а являешься лишь 40% от всего количества, то вполне возможно, что большая часть сайтов из второй половины могут и общаются по HTTPS.

Статистика по Firewall:

Firewall — Количество
ModSecurity: 4354
IBM Web App Security: 126
Better WP Security: 110
CloudFlare: 104
Imperva SecureSphere: 45
Juniper WebApp Secure: 45

Статистика по веб серверам

Веб-сервер — Количество
Nginx: 31752
Apache: 4042
IIS: 959

Устаревших и потенциально уязвимых установок Nginx: 20966
Устаревших и потенциально уязвимых установок Apache: 995

Несмотря на то, что лидером по к примеру доменам и хостингу в целом у нас является hoster.by, отличится смогли и Открытый контакт, но правда по количеству сайтов на одном IP:

84. IP — Сайтов
93. 243: 556
93. 119. 99. 125. 232. 83: 399
193. 25: 386 92.

По email детальную статистику совсем уж решил не дергать, по доменной зоне не сортировать, скорее интерес был посмотреть расположение пользователей к конкретным вендорам:

  • На сервисе TUT.BY: 38282
  • На сервисе Yandex(by|ru): 28127
  • На сервисе Gmail: 33452
  • Привязаны к Facebook: 866
  • Привязаны к Twitter: 652
  • Фигурировали в утечках по информации HIBP: 7844
  • Пассивная разведка помогла выявить более 13 тысяч email адресов

Как видим, в целом картинка довольно позитивная, особенно порадовало активное использование nginx со стороны хостинг провайдеров. Возможно, это в большей степени связано с популярным среди рядовых пользователей — shared типом хостинга.

Тут конечно же, больше света на ситуацию смог бы пролить ресерч с активной фазой, но на данный момент в силу нашего законодательства это как мне кажется — невозможно, а записываться ради таких дел в ряды вредителей не особо и хотелось бы. Из того, что не очень понравилось — есть достаточное количество хостинг провайдеров средней руки, у которых были замечены ошибки вроде AXFR, использовались устаревшие версии SSH и Apache ну и некоторые другие мелкие проблемки.

Ах да, там где указан провайдер TUT. Картина по email в целом довольно радужная, если это можно так назвать. данный сервис работает на базе Яндекса. BY — это имелось ввиду использование домена, т.к.

Заключение

В качестве заключения могу сказать одно — даже с имеющимися результатами, можно быстро понять, что существует большой объем работ для специалистов которые занимаются очисткой сайтов от вирусов, настройкой WAF и конфигурацией/допиливанием разных CMS.

оперируя публично доступной информацией для сбора которой особых навыков и не требуется. Ну, а если серьезно — то как и в предыдущих двух статьях мы видим, что проблемы существуют абсолютно на разных уровнях в абсолютно всех сегментах сети интернет и странах, и всплывают некоторые из них даже при отдаленном изучении вопроса, без использования offensive методик, т.е.

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»