Привет, Хабр!
Меня зовут Валерия Мавлютова, я младший аналитик-исследователь киберугроз в компании R-Vision. Эта статья является продолжением серии материалов об инструментах для горизонтального перемещения и посвящена достаточно объемному с точки зрения используемых методов — инструменту DCOMExec. Ранее мы уже подробно разобрали такие инструменты, как PsExec, SMBExec и AtExec.
Как обычно, сегодня мы посмотрим на чем строится работа данного инструмента, проанализируем потенциальные источники полезной информации для построения возможного способа детектирования и предложим свой вариант обнаружения его эксплуатации.
Ну что же, начнем!
Общее представление DCOMExec
Инструмент DCOMExec — еще один скрипт из набора Impacket, который использует технологию вызова функций COM-интерфейсов удалённо. Технология называется DCOM (Distributed COM) и работает, как и многое в Windows, через протокол RPC, подробнее про нее мы расскажем чуть позже, но напомним читателю про еще одну нашу статью: RPC и способы его мониторинга.
Инструмент DCOMExec может использовать как минимум три COM-объекта для взаимодействия с удалённой машиной, это:
ShellBrowserWindow.
Каждый из этих объектов имеет функции для запуска произвольного процесса. Собственно, удалённый вызов этих функций можно использовать для горизонтального перемещения.
Для детектирования удаленного вызова функций нам нужно уметь фиксировать две вещи:
1. Сам запрос на использование технологии COM по сети.
2. Какой именно COM-объект был использован.
Все эти данные и немного больше, мы можем получить, проведя анализ трафика. В данном случае он будет полезным источником для понимания того, что происходит во время атаки, так как общение происходит с помощью протокола RPC поверх TCP, поэтому будут видны вызываемые DCOM функции и аргументы к ним.
Таким образом, предлагаем разобраться, как в целом работает DCOM именно на примере сетевого трафика.
Принцип работы DCOM
Алгоритм работы технологии DCOM следующий:
вначале происходит классический Bind запрос, где клиент сообщает серверу о желании запустить DCOM;
затем клиент вызывает ISystemActivator. ISystemActivator (GUID: {000001a0-0000-0000-c000-000000000046}) — это запрос, посредством которого говорится серверу «я хочу использовать именно этот COM интерфейс». Сервер его понимает и загружает в память нужный COM интерфейс, чтобы клиент мог им пользоваться. Затем сервер возвращает ответ, что его интерфейс загружен и им можно пользоваться.
далее клиент делает другой Bind запрос на другой интерфейс (так как для каждого RPC интерфейса нужен отдельный Bind запрос). И теперь клиент сообщает о желании «общаться» c главным интерфейсом DCOM — IDispatcher (GUID: {00020400-0000-0000-C000-000000000046}).
Пример DCOM трафика показан на рисунке 1:
Чтобы понять, почему IDispatcher главный, нужно взглянуть на классический COM без буквы D в начале. Подробно о СОМ можно прочитать в нашем цикле статей Тайная жизнь COM: часть 1, часть 2, часть 3.
COM работает так, что клиент не общается напрямую с COM, а просто говорит определенному COM интерфейсу — IUnknown, что именно он хочет сделать. Можно сравнить с тимлидом, к которому нужно идти, чтобы попробовать протолкнуть какую-нибудь фичу.
Так вот, в мире DCOM IDispatch является аналогом IUnknown, который расширяет его функционал и позволяет управлять созданными COM интерфейсами, вызывая его методы и передавая аргументы.
Чтобы заставить COM объект что-то сделать, нам нужно найти функцию, которую мы хотим, чтобы он выполнил. Как нам её найти? Также, как в папках на компьютере — открыть родительскую папку и искать, пока не найдём нужную функцию.
У IDispatcher есть 2 функции, которые клиенту всегда нужно использовать, это:
GetIDsOfNames, которая конвертирует имя функции в число, называемое DISPID, загружает объект в память итд;
Invoke, запускающая функцию. Но для запуска ей передается как раз не имя функции, а число, которое отдаёт GetIDsOfNames. То есть, получается, чтобы вызвать какую-то функцию, нам нужно вызвать эти две по очереди.
Для применения определённого COM метода через DCOM необходимо до него «дойти», так как он может принадлежать атрибуту COM объекта, и чтобы обратиться к методу, нужно сначала обратиться к атрибуту. Эту цепь можно сравнить с вложенностью формата JSON.
Например, чтобы использовать метод ExecuteShellCommand, который входит в состав COM объекта MMC20.Application, нужно обратиться сначала к объекту Document, потом к дочернему атрибуту ActiveView и затем к методу ExecuteShellCommand. Каждый из этих объектов/атрибутов должен быть вызван с помощью ISystemActivator и IDispatch, как и любой другой метод.
Поэтому в трафике будет хорошо видна последовательность вызовов, из которой можно составить путь до COM метода и просмотреть аргументы, с которыми этот метод вызывается.
Предлагаем посмотреть трафик при вызове COM объектов, которые использует инструмент DCOMExec, а также посмотреть, чем они отличаются.
Объект MMC20.Application
MMC20.Application — это COM-объект, позволяющий создавать сценарии для компонентов оснастки MMC. DCOMExec использует метод с именем ExecuteShellCommand в Document.ActiveView для удаленного выполнения команд.
На рисунке 2 показан трафик при вызове данного объекта инструментом DCOMExec:
В трафике можно увидеть все вызовы, которые мы рассматривали ранее. Алгоритм вызова методов, следующий:
Document;
ActiveView;
ExecuteShellCommand;
Также в трафике можно увидеть аргументы к вызову метода, в нашем случае это C:\Windows\system32\cmd (рисунок 3):
Теперь рассмотрим еще один COM-объект, который использует DCOMExec, и это ShellWindows.
Объект ShellWindows
Объект ShellWindows представляет коллекцию открытых окон оболочки (Shell). Чтобы добиться фактического взаимодействия с удаленным хостом, необходимо получить доступ к методу WindowsShell. Item, который вернет нам объект, представляющий окно оболочки Windows. А с помощью метода с именем ShellExecute мы можем удаленно выполнить нужные команды.
На рисунке 4 показан трафик при вызове данного объекта инструментом DCOMExec:
В случае с ShellWindows порядок вызова методов такой:
Item;
Document;
Application;
ShellExecute;
Точно также в трафике можно увидеть аргументы к вызову метода, в нашем случае это C:\Windows\system32\cmd.
Объект ShellBrowserWindow
Как и в случае с объектом ShellWindow, при использовании объекта ShellBrowserWindows с помощью метода ShellExecute можно удаленно выполнить нужные команды (рисунок 6), однако нужно отметить, что данный объект не существует в Windows 7, и он напрямую взаимодействует с оболочкой Windows, поэтому в этом случае вызов WindowsShell.Item будет отсутствовать.
В случае с ShellBrowserWindow порядок вызова методов, следующий:
Document;
Application;
ShellExecute;
Также как и с другими объектами в трафике, можно посмотреть аргументы метода (рисунок 7):
Теперь, когда мы разобрали порядок вызова методов в рассматриваемых объектах и как они вызываются при эксплуатации DCOMExec в трафике, посмотрим, как можно отследить эксплуатацию данного инструмента по событиям журнала Windows.
Журнал Windows EventLog
И сначала посмотрим, по каким событиям журнала Security можно обнаружить факт эксплуатации DCOMExec в случае использования COM объекта MMC20.Application.
События при использовании объекта MMC20.Application
Первым делом нужно понимать, что COM объект был вызван по сети.
Сначала эксплоит делает RPC вызовы, которые передаются сервису RPCSS (Или RPC Service Subsystem отвечает за серверную обработку RPC функций), тот в последствии передаёт их DCOM сервису, имеющему следующие параметры при запуске экземпляра сервиса:
C:\Windows\system32\svchost.exe -k DcomLaunch -p
Конкретно в случае MMC20 сервис запускает mmc.exe с флагом -Embedding (EventID 4688) (рисунок 8).
Так как из событий журнала Windows Security сложно понять, какой именно сервис скрывается под процессом svchost.exe, можно ориентироваться только на параметры запуска mmc.exe, при тестах не было найдено ни одного другого процесса, который запускает mmc.exe с таким параметром.
На этом моменте мы уже знаем, что запрос пришел извне, так как задействован DCOM сервис. Но мы пока не знаем, что именно будет делать mmc.exe. Будем это исправлять.
При исследовании выяснилось, что mmc.exe при вызове COM интерфейса смотрит в реестр вот по такому пути HKCU\Software\Classes\CLSID\{49B2791A-B1AE-4C90-9B8E-E860BA07F889}
, где указан CLSID COM интерфейса MMC20.Application, который применяется для запуска произвольной команды (EventID 4663 - An attempt was made to access an object) (рисунок 9). Таким образом, можно понять, что mmc.exe вызывает этот конкретный COM объект, и этот способ мы будем использовать в дальнейшем для всех COM интерфейсов, которые могут быть применены для горизонтального перемещения.
После этого mmc. exe запустит произвольный исполняемый файл с переданными ему параметрами. На этом моменте мы точно знаем, что произошла DCOM «атака».
События при использовании объекта ShellWindows
В этом методе используется COM объект ShellWindows, который имеет возможность запуска произвольного исполняемого файла из-под explorer.exe.
В отличии от MMC20, при детекте этого метода довольно сложно понять, что COM объект был вызван по сети, так как explorer.exe всегда запущен в Windows, и нельзя проверить родительский процесс и его флаги, чтобы убедиться в удалённом характере этого вызова.
Самый первый маркер атаки — это запрос от имени explorer. exe ветки реестра нужного COM объекта, который не используется при «обычной», ежедневной работе Windows (рисунок 11).
Второй шаг, он же финальный и не такой «яркий» — событие запуска произвольного исполняемого файла от имени explorer. exe (рисунок 12). Не такой он по причине «нормальности» такой ситуации, ведь пользователь чаще всего запустит приложение двойным нажатием, и оно запустится как дочерний процесс explorer. exe.
События при использовании объекта ShellBrowserWindow
Этот метод аналогичен предыдущему, но с использованием COM-объекта ShellBrowserWindow, отличия только в его CLSID. Тут также имеется возможность запуска произвольного бинарника из-под explorer. exe, а также есть сложности с пониманием откуда был вызван COM объект.
Самый первый маркер атаки — это запрос от имени explorer. exe ветки реестра нужного COM объекта, который так же не используется при «обычной» работе Windows (рисунок 13).
И также, как и в случае с ShellWindows, мы наблюдаем за дочерним процессом explorer.exe.
Смотря на эти события, у нас фактически существует только одна проблема - нужно логировать факт удалённого вызова ShellWindows & ShellBrowserWindow.
Поэтому в дополнение к вышеописанным событиям можно также добавить следующее:
EventID 4624 - An account was successfully logged on.
Данное событие однозначно не говорит об удаленном вызове ShellWindows & ShellBrowserWindow, однако указывает на то, что в систему залогинились удаленно. Соответственно, при удаленной эксплуатации DCOMExec в журнале присутствует событие логона EventID 4624 c LogonType 3 и не пустым полем SourceNetworkAddress. Так мы можем узнать ip-адрес хоста атакующего и поступление данного события одновременно с событиями 4663 и 4688, где будет фигурировать один и тот же пользователь, будет говорить об удаленной эксплуатации DCOMExec.
Посмотрим дополнительные источники событий, которые, возможно, тоже указывают эксплуатацию DCOM-exec, а именно на удаленный вызов методов ShellWindows & ShellBrowserWindow.
Event Tracing for Windows (ETW)
При работе с RPC и ETW сразу приходят мысли на выуживание информации из Microsoft-Windows-RPC провайдера, который покажет, какой объект с каким методом был вызван. Конкретно в этой атаке не стоит использовать ETW как полностью самостоятельный источник информации, так как он даёт лишь общую информацию о факте использования DCOM, но ничего о том, какой именно COM интерфейс использовался.
Попробуем посмотреть, как в ETW логах отображается DCOM lateral movement в хронологическом порядке.
Стоит сразу обозначить какой OpNum какой метод означает:
OpNum 4 == RemoteCreateInstance. COM интерфейс ISystemActivator
OpNum 5 == GetIDsOfNames. COM интерфейс IDispatch
OpNum 6 == Invoke. COM интерфейс IDispatch
Сначала мы можем увидеть подключение к ISystemActivator. Это определяется по GUID интерфейса и OpNum == 4 (рисунок 16).
Далее идёт IDispatch, использующий метод GetIDsOfNames для загрузки необходимого COM объекта в память (рисунок 17).
После этого вызывается метод Invoke интерфейса IDispatch, который служит уже для вызова метода определённого COM объекта (рисунок 18).
К сожалению, эти события не говорят ни о чём, кроме факта использования DCOM и вызова неизвестного COM объекта. Без информации о том, какой именно интерфейс был вызван, будет сложно связать эту деятельность с атакой. Ведь любой пользователь может вызывать DCOM и при этом не быть атакующим.
CombaseTraceLoggingProvider
Можно использовать CombaseTraceLoggingProvider для определения, какой именно COM объект был вызван на стороне сервера, то есть на атакуемой машине. Пример лога, который показывает вызов COM-объекта MMC20.Application (49B2791A-B1AE-4C90-9B8E-E860BA07F889
) представлен ниже:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="CombaseTraceLoggingProvider" Guid="{1aff6089-e863-4d36-bdfd-3581f07440be}" />
<EventID>3484</EventID>
<Version>0</Version>
<Level>5</Level>
<Task>0</Task>
<Opcode>0</Opcode>
<Keywords>0x400000000000</Keywords>
<TimeCreated SystemTime="2022-07-05T15:01:31.447239200+02:59" />
<Correlation ActivityID="{5193d10e-4434-4bce-a7f0-bc5db7292044}" />
<Execution ProcessID="852" ThreadID="188" ProcessorID="0" KernelTime="0" UserTime="0" />
<Channel />
<Computer />
</System>
<EventData>
<Data Name="CLSID">{49B2791A-B1AE-4C90-9B8E-E860BA07F889}</Data>
<Data Name="ACID"></Data>
<Data Name="ExecutionPackageName"></Data>
<Data Name="ClientPID"> 0</Data>
<Data Name="AAMActivationID">0</Data>
<Data Name="ClientPackageName"></Data>
</EventData>
<RenderingInfo Culture="en-US">
<Task>COMOutOfProcessServerLaunchStart</Task>
</RenderingInfo>
</Event>
Мы также можем увидеть, что вызывающий этот COM объект процесс имеет PID == 0 в строке ClientPID, и, соответственно, можно предположить, что вызывающий процесс на самом деле на удалённой машине и у провайдера CombaseTraceLoggingProvider нет способов узнать, кто на самом деле клиент этого COM объекта, поэтому PID == 0.
Если лог лишь указывает на факт вызова объекта и то, что вызван он был с удалённой машины, то мы можем совместить его с логами из EventLog и решить проблему с ShellWindows & ShellBrowserWindow. Однако, данный провайдер "эфемерен" и есть не во всех версиях ОС, поэтому в основное правило детекта мы его не включили.
Теперь, рассмотрев возможные источники полезных для детекта логов, попробуем составить возможные правила детектирования эксплуатации DCOMExec.
Возможные правила детектирования
ShellWindows и ShellBrowserWindow
При использовании COM-объектов ShellWindows и ShellBrowserWindows можно выделить следующие моменты, которые помогут нам в построение логики детектирования.
В один и тот же момент времени происходит:
Запрос от Explorer.exe ветки реестра COM объектов ShellWindows и ShellBrowserWindow.
Запуск cmd.exe с определенными параметрами.
Фиксируется событие сетевого входа в систему.
Все действия происходят из-под одного и того же пользователя.
Пример псевдо-правила:
SELECT (host, TargetUserName)
FROM EventCode = 4688
WHERE
(Process_Command_Line="\"C:\\Windows\\System32\\cmd.exe\" /Q /c*") AND
(process_command_line_arguments="*1> \\\\127.0.0.1\\ADMIN$\\__16893 2>&1") AND
(process_exec="cmd.exe")
(ParentProcessName="explorer.exe")
IN
(
SELECT (host, TargetUserName)
FROM EventCode = 4663
WHERE ObjectName IN ("\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\CLSID\\{c08afd90-f2a1-11d1-8455-00a0c91f3880}", "\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\CLSID\\{9BA05972-F6A8-11CF-A442-00A0C90A8F39}") AND
ProcessName="C:\\Windows\\explorer.exe"
SELECT (host, TargetUserName)
FROM EventCode = 4624
WHERE IpAddress!="-" AND
LogonType!="3"
)
MMC20.Application
При использовании COM-объекта MMC20.Application можно выделить:
Запуск mmc.exe с параметром "- Embedding".
Запрос от имени mmc.exe ветки реестра COM объекта MMC20.Application.
Все действия происходят из-под одного и того же пользователя.
Пример псевдо-правила:
SELECT (host, TargetUserName)
FROM EventCode = 4688
WHERE
(Process_Command_Line="C:\\Windows\\system32\\mmc.exe -Embedding") IN
(
SELECT (host, TargetUserName)
FROM EventCode = 4663
WHERE ObjectName="\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\CLSID\\{49B2791A-B1AE-4C90-9B8E-E860BA07F889}" AND
ProcessName="*mmc.exe"
)
Заключение
Сегодня мы рассказали об еще одном инструменте из набора скриптов Impacket, который применяют злоумышленники при горизонтальном перемещении, а именно DCOMExec.
В статье на примере сетевого трафика мы разобрали работу технологии DCOM, ведь на ней и строится работа инструмента DCOMExec. Рассмотрели теоретические аспекты обнаружения и на практике разобрали возможные источники логов для построения псевдо-правил. В качестве итога на основе журнала EventViewer были представлены варианты псевдо-правил для обнаружения эксплуатации DCOMExec в случае использования всех трех COM-объектов.
Оставляйте ваши комментарии ниже и пишите вопросы. Надеемся, статья оказалась вам полезной!