В подозрительном проекте найден сетевой адрес. В журнале есть обращение к похожему домену. Возникает соблазн сразу написать: «Загрузчик связался с командным сервером и похитил данные».
Но между этими предложениями спрятано несколько неподтверждённых переходов. Последняя статья цикла посвящена тому, как собрать связное объяснение из сетевых и системных следов, не приписывая им больше, чем они показывают.
Что сообщает каждый источник
DNS-журнал может показать запрос имени и ответ резолвера. Сам по себе он не устанавливает успешное HTTP-соединение, получение полезной нагрузки или исполнение ответа. Процесс мог запросить имя и завершиться с ошибкой; запрос мог выполнить другой компонент.
Сетевой поток показывает соединение и, в зависимости от источника, адреса, время и объём передачи. Для HTTPS путь URL, заголовки и тело запроса защищены TLS. Обычный пассивный захват без ключей расшифрования не позволяет искать в них x-secret-header. Такие сведения могут быть доступны в журнале приложения, на узле завершения TLS или в разрешённой системе инспекции. [1]
Имя из SNI иногда помогает, но его наблюдаемость нельзя считать обязательной: ECH предназначен для шифрования внутреннего ClientHello, включая целевое имя. При его использовании наблюдаемое внешнее имя может относиться к общей инфраструктуре, а не к целевому сайту. При этом ECH сам по себе не скрывает IP-адрес назначения и открытые DNS-запросы. [2]
Журнал процессов связывает событие с программой, аргументами и родительским процессом. Для корреляции желательно иметь не только PID, но и время создания либо устойчивый идентификатор процесса: один числовой PID может использоваться повторно. Точный состав полей зависит от средства сбора.
Собираем цепочку
Для учебной задачи полезна следующая схема:
| |
Это план проверки, а не описание обязательной атаки. Следующая стадия может исполняться в памяти, сеть может не сработать, а сохранённый файл может оказаться безобидным. Каждая стрелка требует собственного свидетельства.
Хорошая корреляция использует один компьютер, согласованное время, устойчивую связь процессов и содержание артефактов. Совпадение «где-то запущен Node.js» и «кто-то обратился к облачному сервису» слишком широко для вывода о вредоносном поведении.
Учебный журнал
Файлы для самостоятельного разбора доступны в синтетическом практикуме.
Ниже синтетические данные одного компьютера за один день; время приведено в UTC. Имя delivery.invalid и идентификаторы придуманы для упражнения; обращаться к ним не нужно. Поле entity обозначает устойчивый идентификатор экземпляра процесса, а status=connected в этом условном формате — успешно установленное TLS-соединение.
| |
Сформулируйте подтверждённые события и укажите, каких данных не хватает для вывода о доставке кода и краже секретов.
Показать разбор журнала
Что подтверждено при условии достоверности журнала? Процесс p17 запущен с необычным аргументом, ему сопоставлены сетевые события и запись файла. Затем зарегистрирован дочерний процесс Node.js с путём к этому файлу в аргументах.
Чего не хватает? В событии TLS нет адреса назначения или идентификатора, связывающего его с DNS-ответом: даже один и тот же процесс может параллельно обращаться к разным серверам. Без содержимого сетевого ответа нельзя утверждать, что файл целиком получен именно из этого соединения. Для связи записанного файла с исполненным также нужны сведения о его содержимом и изменениях между событиями: одно совпадение пути не устанавливает тождество байтов. Без содержимого stage.js и дальнейших следов неизвестно, выполнилась ли кража данных. Даже успешный запуск интерпретатора не доказывает, что программа дошла до нужной исследователю ветви.
Итоговая запись может звучать так: «Зафиксирована последовательность запуска, сети, записи файла и запуска дочернего процесса; предполагаемая доставка следующей стадии требует подтверждения содержимым артефактов».
Как использовать индикаторы
Индикатор полезен вместе с происхождением: из какого файла или события он получен, когда наблюдался, что предположительно обозначает и насколько точен.
Хэш идентифицирует конкретные байты. Путь может совпасть у постороннего файла. Домен со временем может сменить содержимое или владельца. Поэтому старый адрес из исходного кода — историческая зацепка, а не доказательство сегодняшней активности.
Для публичного текста подозрительные адреса удобно обезвреживать записью вида hxxps://host[.]example/path. Это защита от случайного перехода, не способ изменить смысл индикатора. Для машинного использования исходное значение хранят отдельно, с контролем доступа и отметкой источника.
Особенно осторожно следует обращаться с общей инфраструктурой. Наблюдение одного подозрительного поддомена не делает вредоносными весь vercel.app, все соседние проекты или общий IP-адрес. Блокировка должна соответствовать доказанному объекту и учитывать сопутствующий ущерб.
MITRE ATT&CK описывает действия, а не заменяет доказательства
Если установлен контекст атаки, исполнение JavaScript можно соотнести с T1059.007, а подтверждённую доставку дополнительного инструмента или файла в скомпрометированную среду — с T1105. Обычные загрузки и запуск легитимного JavaScript сами по себе не становятся техниками атакующего. Но запрос имени ещё не доказывает передачу, а наличие кода загрузки показывает возможность, а не обязательно наблюдённое действие на конкретном компьютере. [3][4]
Аналогично нельзя добавлять в отчёт закрепление или эксфильтрацию только потому, что загрузчик теоретически способен запустить произвольную программу. Для этих выводов нужны отдельные следы.
Совпадающие адреса, имена файлов и шаблоны кода могут поддерживать гипотезу о связи образцов. Они не устанавливают автора, страну происхождения и принадлежность к известной группе без дополнительных данных.
Задача: уберите лишнее из заключения
Исследователь пишет: «В архиве найден URL. Компьютер обращался к этому домену. Значит, пароль от облака украден».
Показать разбор
Разбор. Первая часть описывает содержимое архива. Вторая — сетевое событие, которое ещё нужно связать с нужным процессом. Третья не следует из первых двух. Для неё требуются сведения о доступе к секрету, передаче данных или последующем использовании учётной записи. При этом защитные действия могут быть оправданы до окончательного подтверждения утечки.
Завершение цикла
Начинали мы с настройки редактора, а пришли к проверке доказательств. Во всех статьях работал один приём: найти переход, сформулировать гипотезу и выяснить, какие данные её подтверждают.
Проверить файл — не то же самое, что проверить его расширение. Найти загрузчик — не то же самое, что установить его исполнение. Зафиксировать соединение — не то же самое, что доказать утечку. Умение удерживать эти различия делает технический разбор полезным и для решения CTF-задачи, и для реального расследования.
Источники
[1] RFC 8446: TLS 1.3.
[2] RFC 9849: TLS Encrypted Client Hello.