Боевой OSINT s01e01 - OSINT & RDP
MoodyЭто первая часть цикла туториалов по боевому OSINT'у, которая охватывает подготовку (техническую и интеллектуальную) и рассказывает как настроить мониторинг уязвимости Bluekeep в больницах с использованием баз данных Shodan и Elasticsearch.
Вступление
Эти учебные пособия дадут вам представление о методах OSINT, используемых киберпреступниками для поиска различных организаций и людей с целью мошенничества и взлома. Это не очередная статья, ведущая на другой сайт с кучей ссылок и описанием того, что они делают, а скорее технические сведения для профессиональных аналитиков безопасности, обладающих хотя бы некоторыми навыками программирования и аналитическим складом ума. Я хотел бы показать каждую область OSINT - социальные сети, Dark Web, утечки, промышленный / корпоративный шпионаж и тому подобное.
Первая статья серии посвящена правильной подготовке, то есть настройке среды, комбинированию нескольких инструментов и установке базы данных. Каждая представленная методика будет поддерживаться исследованиями, и в этой части мы рассмотрим открытые протоколы удаленных рабочих столов с уязвимостью Bluekeep и акцентом на медицинские и финансовые учреждения.
В дополнение к статье я покажу некоторые приемы OSINT & RDP, чтобы найти машины для конкретных шпионских целей, используя Credential Stuffing и обратный поиск по изображениям, так что давайте начнем.
Подготовка
Я чувствую, что о психологической подготовке к OSINT-расследованиям и о том, что вы должны иметь аналитический ум, уметь документировать сведения и строить отношения между ними, уже все было сказано. Конечно, каждое задание в ходе его решения требует своего рода разного мышления, но в момент планирования мы каждый раз должны использовать какой - то общий подход. Лично для меня лучше всего подходит нисходящий подход - исходя из общей идеи, разделить основную цель на более мелкие задачи и сосредоточиться на деталях в конце.
В нашем случае основная цель состоит в том, чтобы найти уязвимые RDP службы в медицинских / финансовых учреждениях, которые могут содержать конфиденциальную информацию, не найденную никем ранее. Чтобы достичь этой цели, нам нужно разбить ее на более мелкие задачи:
- Получить информацию об открытых RDP
- Сохранить эту информацию
- Периодически проверять наличие свежей информации
- Сравнивать полученные данные с уже имеющимися
Вычленение небольших задач позволяет выбрать конкретные технологии для исследования, а также источники данных. Сейчас мы можем подумать о технических аспектах, таких как тип базы данных (облачная / локальная), язык программирования (включая IDE), сервисы и предпочитаемая операционная система. Давайте трансформируем наши цели в технические требования:
- Использовать Python и Shodan API для загрузки информации о незащищенных RDP
- Установить Elasticsearch для хранения данных
- Использовать Cron для выполнения задач по расписанию
- Опять же, использовать Python для сравнения новых результатов с уже имеющимися в базе данных
Конечно, есть нечто большее, следующий шаг - определить лучший запрос в Shodan, определить идеальное время проверки и настроить Elasticsearch. Это всего лишь пример, но я использовал этот подход много раз во время исследований или разработки инструментов, и он меня ни разу не подвел.
Мы все разобрали и теперь можем перейти к техническому аспекту.
Техническая подготовка
Эта часть требует базовых навыков работы с терминалом Linux и Python, но если вы их не имеете, не спешите закрывать статью - я все прокомментирую. Давайте начнем с настройки собственной базы данных.
Elasticsearch - это инструмент с открытым исходным кодом для поиска и анализа различных типов данных, включая текстовые, числовые, геопространственные, структурированные и неструктурированные.
Документация делает процесс установки очень простым; сначала нам нужно скачать и установить публичный ключ репозитория
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
Установить https-transport:
sudo apt-get install apt-transport-https
Создать файл с информацией о репозитории:
echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-7.x.list
Обновить кэш и устанавить ElasticSearch:
sudo apt-get update && sudo apt-get install elasticsearch
Запустить немедленно Unit elasticsearch.service:
sudo systemctl enable elasticsearch.service –now
Для проверки работоспособности открыть:
http://localhost:9200
Конфигурацию и дальнейший менеджмент вы можете найти здесь.
Python является одним из лучших языков программирования для решения такого рода задач-сценариев, и хорошая IDE может ускорить весь процесс разработки, сделав нашу жизнь намного проще. Я не хочу сказать, что люди пишущие в блокноте неэффективны, но IDE помогает свободно перемещаться по коду и быстро управлять репозиторием. Моя любимая IDE - Pycharm, она создает отдельную виртуальную среду для каждого проекта, поддерживает кастомизацию, несколько терминалов, локальную историю и множество других функций.
Что вы должны знать об этой IDE, так это горячие клавиши. Иногда, когда я работаю с Pycharm, я часами не касаюсь своей мыши - хоткеи ускоряют работу и делает работу чрезвычайно простой. Вот парочка наиболее полезных
2x shift – быстрый поиск по всему проекту Ctrl + / - закомментировать/раскомментировать текущую строку Ctrl + Shift + / - закомментировать/раскомментировать выделенный код Shift + f10 – выполнить код Shift + f9 – режим отладки Ctrl + r – замена в тексте Ctrl + h – история Alt + f12 – открыть терминал
Вы можете найти их все на сайте Jetbrains.
OSINT & Bluekeep
Импортируем необходимые пакеты в наш проект
from elasticsearch import Elasticsearch import requests import json import email.message import smtplib
Создадим индекс под названием rdp-monitoring, где мы будем хранить все данные.
es.indices.create(index='rdp-monitoring', ignore=400)
Теперь можно перейти к получению машин с открытым RDP в Shodan.
Несколько переменных, которые мы должны определить
SHODAN_API_KEY = "" query = "port:3389 org:hospital" endpoint = "https://api.shodan.io/shodan/host/search?key="+SHODAN_API_KEY+"&query="+query+"&page=" cve = "CVE-2019-0708" fresh = []
Fresh - это пустой список, который будет содержать новые (свежие) IP-адреса.
И код для извлечения хостов, уязвимых для Bluekeep
try: shodan_request = requests.get(endpoint) shodan_json = json.loads(shodan_request.text) for result in shodan_json['matches']: if not exists(result['ip_str']): check_each_host = requests.get("https://api.shodan.io/shodan/host/" + result['ip_str'] + "?key=" + SHODAN_API_KEY) check_each_host_json = json.loads(check_each_host.content) if 'vulns' in check_each_host_json: if cve in check_each_host_json['vulns']: fresh.append(result['ip_str']) print("New IP:" + result['ip_str']) es.index(index="rdp-monitoring", id=check_each_host_json['ip_str'], body={"organization": check_each_host_json['org']}) else: print("IP exists") if fresh: send_notification(fresh) except Exception as e: print(e)
Он отправляет API-запрос в Shodan с текстом «port: 3389 org: hospital» (я не нашел дорки для Bluekeep), перебирает результаты в цикле, а затем делает еще один запрос для проверки каждого хоста на наличие CVE-2019-0708. Shodan не всегда возвращает vulns в общих результатах поиска, поэтому мы должны проверять каждый IP отдельно (check_each_host).
После этого мы проверяем, есть ли какие-либо уязвимости, если да - то содержит ли полученный список наш CVE-2019-0708. Содержит - добавляем его в Elasticsearch.
es.index(index="rdp-monitoring", id=check_each_host_json['ip_str'], body={"organization": check_each_host_json['org']})
Я использую IP-адрес в качестве поля идентификатора для упрощения поиска без использования фильтрации источников.
Скрипт проверяет только первую страницу, на которой около 70 результатов, - вы можете дописать код использующий пагинацию для получения дополнительных результатов.
Итак, мы сохранили IP-адреса и связанные с ними организации в Elasticsearch, но если скрипт будет запущен в следующий раз, он будет должен распознать, какие записи еще не находятся в базе данных. Для этого мы можем написать дополнительную функцию «exists»
def exists(ip): try: es.get(index='rdp-monitoring', id=ip) return True except: return False
Он просто пытается получить документ на основе индекса и идентификатора, который в нашем случае является IP-адресом. Если запись не существует, происходит ошибка, которую мы обрабатываем и возвращаем False.
Последняя часть состоит в том, чтобы всегда быть в курсе событий и получать сообщения на почту каждый раз, когда скрипт находит новые машины. Для этого нам нужно написать еще одну функцию, которая использует учетную будет использовать учетную запись Gmail и отправлять сообщения
def send_notification(ips): body = "<h1>New IPs in hospitals with Bluekeep</h1><br>" ips_text = "" for ip in ips: ips_text = ips_text + "https://beta.shodan.io/host/" + ip + "<br>" msg = email.message.Message() msg['Subject'] = 'RDP Monitoring' msg['From'] = "@gmail.com" msg['To'] = "@gmail.com" msg.add_header('Content-Type', 'text/html') msg.set_payload(body + ips_text) gmail_user = "@gmail.com" gmail_password = "" try: server = smtplib.SMTP_SSL('smtp.gmail.com', 465) server.ehlo() server.login(gmail_user, gmail_password) server.sendmail(msg['From'], [msg['To']], msg.as_string()) server.close() print('Email sent!') except Exception as e: print(e) print('Something went wrong...') pass
Это самый простой код, найденный где-то в сети и модифицированный для поддержки text/html контента. По сути, мы просто создаем информационный текст с нашими свежими IP-адресами (сохраненными в новом списке) и отправляем его на заданный адрес электронной почты. Чтобы скрипт корректно работал, вы также должны ввести свой адрес электронной почты и пароль в коде, а также войти в свою учетную запись Gmail в браузере с того же компьютера.
После его запуска, новые записи появятся в Elasticsearch
Вы можете добавить скрипт в Cron или скомбинировать его с другим инструментами в вашем арсенале.
Не только больницы являются интересной целью, запрос «port: 3389 org: bank» вернет вам все машины с открытым RDP в финансовых учреждениях, в названиях которых фигурирует слово «bank». Если пойти еще дальше, то использование свободного текстового поиска и таких слов, как «scada», покажет потенциальные системы промышленного контроля, компрометация которых бесценна.
Credential stuffing & RDP
Единожды скомпрометировав учетные данные пользователя на одном сайте, Credential stuffing предполагает доступ к прочим сервисам, на которых была зарегистрирована жертва, под теми же данными. В большинстве случаев после создания дампа, киберпреступники проверяют пары имя_пользователя/почта:пароль на других популярных платформах, таких как Facebook, Spotify, Netflix и т. д. Это тема была предметом моего исследования в прошлом году, вы можете прочитать больше тут.
Протокол для подключения к удаленному рабочему столу не является исключением, - если пользователь везде использует один и тот же пароль, он должен знать, что единоразовый слив его учетных данных на одном сайте, может привести к компрометации даже его личного ПК. Shodan использует OCR (оптическое распознавание символов) для извлечения текста из изображений и в некоторых случаях распознанный текст с экрана входа включает имена пользователей и версию Windows.
Когда вы ищете RDP для конкретной компании, не забывайте использовать метод свободного текстового поиска, - компьютер может находиться в облаке и отображать имя организации в поле имени пользователя или в предупреждении о безопасности.
APT используют две тактики для получения доступа к сети - концентрация на персонале без технических знаний и знаний в области безопасности (HR'ы, например), выполнение скрытой вредоносной нагрузки без обнаружения и, в самом конце, повышение привилегий.
Ориентация на высокопоставленных лиц (CEO, CISO, старшее руководство) для почти что автоматического получения доступа к конфиденциальным данным зависит от полномочий жертв. Часто киберпреступники отправляют фишинговые электронные письма высшему руководству, например старшим аналитикам и инженерам, которые работают в критических отраслях - в медицине, правительстве, образовании.
HaveIBeenPwned & RDP
Чтобы убедиться в том, стоит ли взламывать какой-либо RDP, основываясь на открытом имени пользователя, нам нужно задействовать OSINT и навыки работы с электронной почтой.
Во-первых, давайте найдем RDP с электронной почтой, используемой в качестве логина для входа в учетную запись. Для этого можно использовать запрос „port:3389 has_screenshot:true 'gmail'”, изменяя gmail на любого другого провайдера электронной почты или компанию. К сожалению, по неизвестным мне причинам, Shodan не может использовать поиск с символом «@», который бы точно указывал на то, что мы ищем именно электронную почту.
Следующий код извлекает адреса электронной почты Gmail из открытых RDP
query = "port:3389 has_screenshot:true gmail" endpoint = "https://api.shodan.io/shodan/host/search?key="+SHODAN_API_KEY+"&query="+query+"&page=" req = requests.get(endpoint) req_json = json.loads(req.text) for match in req_json['matches']: text = match['opts']['screenshot']['text'].split("\n") for line in text: if "@" in line: print(line)
Быстрый поиск одного из адресов электронной почты (полученных при выполнении того кода, что я указал выше), показывает нам, что он был скомпрометирован в 7 различных утечках.
Это много, и даже если пароль на каждом сайте уникален, при этом он не был сгенерирован случайным образом, можно найти схему, по которой владелец учетки придумывает пароли на каждый сайт, и угадать его пароль от RDP.
Но стоит ли эксплуатировать эту машину для получения конфиденциальных данных? Нам нужно выяснить, кто является владельцем адреса электронной почты. Быстрый поиск в Google показывает, что это [УДАЛЕНО] инженер, окончивший [УДАЛЕНО].
Это один из способов, как вы можете найти владельца или данные от его учетной записи от RDP, он не автоматизирован и завязан на ручном поиске по нескольким причинам - OCR не всегда все корректно распознает и иногда содержит странные символы, электронная почта может включать «...» вместо домена верхнего уровня, потому что RDP предпочитает не показывать полное имя пользователя, если оно неактивно. В конце концов, результаты должны быть проверены вручную, чтобы определить конечные цели.
Reverse Image search & RDP
Это также необычная техника, о которой я никогда не слышал, - она непременно утомительна, но может окупиться, подтвердив окончательные сомнения. Если на машине не обнаружен какой-либо адрес электронной почты и она не связана с какой-либо организацией, изображение профиля пользователя может помочь вам определить владельца машины и потенциальную ценность с точки зрения наличия секретных документов.
Нам нужно вырезать изображение профиля из скриншота с RDP и попытаться его найти на одном из сервисов обратного поиска по изображениям.
В данном случае мне пришлось проверить фотография сразу на нескольких сервисах для получения нужных результатов. Люди, как и пароли, часто используют одну и ту же свою фотографию на разных сайтах, в особенности на LinkedIn.
Имена пользователей RDP в формате имени и фамилии легче исследовать, - вы должны искать учетные записи в социальных сетях и упоминания в Интернете искомого человека, однако они не всегда уникальны, поэтому такой поиск лучше комбинировать с поиском по изображению. В моем случае, изображения были повторно использованы во многих социальных сетях, поэтому было легко определить, кто является старшим владельцем продукта и генеральным директором финансовой компании.
Заключение
OSINT широко используется не только правоохранительными органами и исследователями, но и киберпреступниками. Под киберпреступниками я подразумеваю актеров, которые нацелены на конкретных людей и компании, чтобы получить как можно большую прибыль - конфиденциальные документы, данные клиентов, интеллектуальную собственность или просто деньги. Зная их методы, вы можете защитить себя и не стать легкой мишенью.
Для исследователей мониторинг незащищенных машин Bluekeep позволяет взглянуть на потенциальные компании, которые в скором времени скопроментируют и предсказать новостные заголовки.
Предоставляя учебные пособия и делясь знаниями, я надеюсь частично покрыть свои медицинские счета. Если вам нравится моя работа и вы используете мои инструменты, пожалуйста, помогите мне, сделав пожертвование на Paypal.
Прочитать оригинал этого материала на английском можно здесь.