Каждый написанный мной, прочитанный или унаследованный план действий при компрометации учетных данных содержит один и тот же шаг в начале: отозвать токены. Сбросить пароль, завершить сеансы, аннулировать токены обновления, а затем начать поиск. Это правильный инстинкт. Против фишинга с подменой посредника, где вся добыча — украденный файл cookie сеанса, отзыв токенов — это действие, которое прекращает инцидент.
Затем я провел несколько дней, разбирая бэкдор, где этот шаг ничего не дает. Причина кроется в одной функции, и это последнее место, где большинство из нас подумало бы искать.
Образец — GraphWorm, пользовательский имплант, связанный с APT-группой Webworm, имеющей китайские корни. Одна из найденных мной деталей изменила строку в моей собственной процедуре реагирования на инциденты, и я считаю, что она должна быть и в вашей.
Канал управления и контроля — чей-то OneDrive
У GraphWorm нет домена управления и контроля (C2), нет маяка на арендованном VPS, нет жестко закодированного адреса для блокировки. Он аутентифицируется в Microsoft Graph как OAuth-приложение и использует учетную запись OneDrive в качестве тайника.
Структура достаточно проста, чтобы набросать ее на салфетке. Оператор записывает зашифрованный файл задачи в папку заданий. Имплант опрашивает эту папку, выполняет задачу, а затем загружает зашифрованный результат в папку результатов. Файл пульса получает свежую временную метку каждый интервал, а файл отпечатка несет детали системы жертвы. Набор команд охватывает выполнение команд оболочки, загрузку и скачивание файлов, сон, завершение работы и пару обмена ключами, которая обновляет ключ развертывания до ключей для каждого сеанса.
Все это передается через graph.microsoft.com по TLS с хоста, который и так весь день общается с Microsoft 365. Нет необычного назначения для блокировки брандмауэром, нет недавно зарегистрированного домена для наказания движком репутации, нет странного порта. Сетевой уровень не имеет значения. Это цель дизайна, и это тот же сдвиг, о котором я писал ранее, когда операторы перестают строить свою собственную инфраструктуру и начинают использовать чужую.
Учетные данные находятся в бинарном файле в открытом виде: идентификатор клиента, секрет клиента, идентификатор клиента и токен обновления длиной более 1300 символов. Оператор также предоставил отладочную сборку с полным путем PDB.
Еще одна деталь важна для тех, кто планирует реагирование. Имплант не идентифицирует своих жертв по имени хоста или адресу. Он создает идентификатор, хешируя аппаратный адрес сетевого адаптера вместе с серийными номерами процессора и диска, полученными через WMI. Переименуйте машину, переместите ее в другую подсеть или поместите за новый исходящий адрес, и оператор все равно узнает ее как ту же самую машину. Любой план сдерживания, который опирается на изменение сетевой идентификации жертвы, решает проблему, которой у этого импланта нет.
До сих пор это хорошая, но знакомая история. Облачное управление и контроль не ново. Часть, которую я не ожидал, была в обработчике задач.
Функция, которая ломает план действий
Среди команд, которые принимает имплант, есть одна под названием upgrade (обновить). Поток короткий, и его стоит пройти.
Обработчик анализирует конфигурационный блок из входящей задачи. Затем он уничтожает все пять строк учетных данных, хранящихся в объекте маяка, копирует пять новых, перестраивает структуру области OAuth, тестирует соединение с новой учетной записью OneDrive, записывает замену конфигурации на диск и меняет активный экземпляр API.
Одна задача. Полностью замененная личность.
Подумайте о последствиях на секунду. Ваше расследование доходит до точки, где вы идентифицировали приложение, вы подаете заявку на платформу, и токены отзываются. Следующий опрос импланта завершается неудачей. Если оператор наблюдает, а оператор, записывающий файл пульса каждый интервал, наблюдает, он ставит в очередь задачу обновления, указывающую на вторую учетную запись OneDrive, которую он зарегистрировал месяцы назад. Имплант получает ее, ротирует и возобновляет работу. На конечной точке ничего не изменилось. Никакого нового бинарного файла, никакого нового механизма постоянства, никакого нового процесса. Тот же файл на диске, другая личность за ним.
Отзыв удалил учетные данные. Он не удалил доступ.
Это не отражено в общедоступных отчетах о семействе, что не является критикой. Отчеты поставщиков ограничены наблюдаемой кампанией, и это та деталь, которую вы видите только при открытии декомпилятора в функции, которую никто не считал приоритетной. Я подтвердил это дважды, прежде чем был готов записать это: один раз по извлеченным строкам, а другой раз по самой декомпилированной функции. Смещения полей учетных данных, которые я получил из строк, должны были совпадать со смещениями, которые конструктор фактически читает, и они совпали, что является разницей между находкой и догадкой.
Что я изменил после этого
Из этого вытекают три вещи, которые я бы включил в процедуру реагирования на компрометацию учетных данных завтра же.
- Рассматривайте отзыв как задержку, а не как выселение всякий раз, когда C2 использует идентификатор приложения. Долговечным объектом является регистрация, а не токены, которые она выдает. Токены — это листья, регистрация — корень, а сдерживание, которое останавливается на отзыве, запускает таймер вместо закрытия двери. Если регистрация находится в управляемом вами клиенте, приостановка означает подачу отчета и ожидание в очереди кого-то другого, поэтому подавайте заявку раньше, а не в качестве последнего шага.
- Предполагайте, что у оператора есть запасной вариант. Ротация учетных данных почти ничего не стоит злоумышленнику и стоит вам полного цикла реагирования. Эта асимметрия должна определять последовательность: устраните способность конечной точки достигать канала одновременно с уничтожением учетных данных, а не после. Изоляция хоста или блокировка этого конкретного приложения от аутентификации в вашем собственном клиенте — это действия, которые не требуют ничьего сотрудничества.
- Ищите на плоскости идентификации, потому что сетевая плоскость здесь слепа. Обнаружения, которые фактически срабатывают для этого семейства, — это вовсе не сетевые сигнатуры. Это запросы облачной телеметрии: идентификатор приложения оператора, появляющийся в ваших событиях входа, аутентификация против незнакомого клиента, пользовательский агент HTTP-библиотеки, отличный от браузера, обращающийся к OneDrive, имена файлов маяка и отпечатка, появляющиеся в телеметрии файлов. Идентификатор приложения — это фиксированная строка; он не принадлежит никому законному, и один запрос по вашей телеметрии входа отвечает на вопрос, запрашивал ли он когда-либо токен у вашего клиента.
Ничто из этого не требует нового инструментария. Это требует, чтобы регистрация приложения рассматривалась как то, что вы пытаетесь уничтожить.
Более широкая картина — вот что осталось со мной. Мы провели десятилетие, учась выслеживать инфраструктуру, а противники ответили отсутствием таковой. Когда каналом является папка в облачном клиенте, а личность, стоящая за этой папкой, может быть заменена удаленной командой, артефакты, которые мы обучены преследовать, — это именно те, которые оператор может заменить дешевле всего. Что они не могут заменить дешево — это код, находящийся на конечной точке, и поведение этого кода в вашей телеметрии.
Поэтому теперь я проверяю предположение. Прежде чем считать инцидент с компрометацией учетных данных завершенным, я спрашиваю, что именно я уничтожил и может ли противник выдать себе замену, даже не прикасаясь к машине жертвы. В этом образце ответ был да, и для доказательства этого потребовалась одна функция.
Полный разбор и контент для обнаружения на основе этого анализа опубликованы на GitHub.
Всегда имейте в виду, что редакции могут придерживаться предвзятых взглядов в освещении новостей.
Автор – Yanky Wilson




