Привет, Хабр!

Сегодня мы поговорим о Lateral Movement (англ. горизонтальное перемещение) - тактике, используемой атакующим для продвижения по сети. Во время атак или проведения тестирований на проникновение атакующие перемещаются не вверх по привилегиям, а вбок по машинам, образно говоря "перескакивают" от одной к другой.

Как правило, одной из наиболее распространенных техник горизонтального перемещения является использование вполне стандартных протоколов удаленного подключения RDP и SSH. Но сегодня мы рассмотрим другой не менее известный и интересный способ для выполнения тактики Lateral Movement - инструмент PsExec, являющийся представителем многочисленного семейства Exec'ов куда также входят: SMBExec, DCOMExec, WMIExec и другие.

PsExec - одна из утилит, доступных в пакете Windows Sysinternals. Она предназначена для удалённого администрирования и позволяет запускать процессы, используя систему удалённого управления сервисами и передачи файлов. PsExec удобен прежде всего тем, что не требует установки: нужно всего лишь скопировать улититу в нужный каталог. Также он позволяет выполнять процессы из под SYSTEM.

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

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

Принцип работы PsExec

Механизм работы выглядит следующим образом:

  1. PsExec, используя протокол SMB, перемещает файл PsExesvc.exe (создан PsExec заранее) в сетевую папку ADMIN$ (по умолчанию);

  2. Затем посредством RPC вызывается SCM и создается служба, она, в свою очередь, и запускает PsExesvc.exe на целевом хосте;

  3. Сам файл создаёт именованный канал (далее по тексту Named Pipe/ Pipes), через который он общается с машиной-атакующим.

Рисунок 1. Механизм работы инструмента PsExec
Рисунок 1. Механизм работы инструмента PsExec

Немного теории и гипотез

Когда мы изучали работу PSExec, то рассматривали как оригинальный PsExec от Марка Русиновича, так и PsExec из набора скриптов Impacket. Последний, по понятным причинам, гораздо проще модифицировать. Учитывая это, при построении логики детектирования мы должны осуществлять только обязательные шаги, необходимые для выполнения атаки. Такие как:

  1. Передача файла на атакуемую машину;

  2. Управление сервисами через RPC интерфейс;

  3. Создание сервиса с файлом, загруженным на Рисунке 1;

Таким образом можно опираться не на конкретные специфичные для PsExec атрибуты, а на действия, которые были выполнены на устройстве.

Может возникнуть вопрос: а нужно ли нам мониторить создание и использование именованного канала как часть PsExec?

На наш взгляд, лучше иметь в виду тот факт, что Pipes могут быть заменены на другой способ коммуникации. Тогда гипотетическое правило будет срабатывать в обоих возможных случаях и позволит надёжнее предупредить о потенциальной атаке. Единственный минус, который мы приобретаем - это вероятные ложные срабатывания. Как например, если легитимный пользователь решил создать новую службу и загрузить её через SMB. Данная проблема актуальна также при изучении других инструментов тактики горизонтального перемещения. Более подробно о ней мы рассказывали в статье RPC и способы его мониторинга.

От минусов, связанных с ложными срабатываниями, можно избавиться с помощью альтернативного варианта - мониторинга удалённого запроса на управление сервисом.
В этом нам поможет событие с EventID 5145 (Detailed File Share) запроса Pipe svcctl (он отвечает за функционал управления сервисами). Но все не так просто - к этому интерфейсу можно подключиться несколькими способами: напрямую через RPC или через IPC$, поэтому придётся мониторить их оба. Однако решение данной ситуации все же есть - технология RPC Filtering, которая позволит нам логировать сразу все возможности подключения, о чем мы расскажем дальше в статье.

Итак, мы разобрались с обязательными для атаки шагами и поняли с каким сложностями детекта можно столкнуться. Дальше мы перейдем к практической части нашей статьи и попытаемся найти логи, с помощью которых можно детектировать атаку в трёх разных источниках информации: событиях журнала Windows Security, Sysmon и сетевом трафике. Также рассмотрим плюсы и минусы каждого из них, чтобы выяснить как лучше всего детектировать PsExec.

Журнал Windows Security

Просмотр журнала событий через Windows EventViewer - самый популярный способ мониторинга в Windows, поскольку он прост в настройке и управлении. Для начала давайте выясним, как действия PsExec отображаются в событиях, поскольку без них никакого возможного правила, естественно, не получится.

Самое первое событие, на которое стоит обратить внимание - доступ к именованному каналу с именем svcctl (рисунок 2). Этот интерфейс позволяет удалённо управлять сервисами на удаленном устройстве, что и требуется для PsExec. Подобное действие можно трактовать, как "желание" управлять сервисами на этой машине и его просто отследить с помощью событий EventID 5145.

Рисунок 2. Доступ к Pipe с именем svcctl
Рисунок 2. Доступ к Pipe с именем svcctl

Ниже представлен специфичный для PsExec от Impacket лог доступа к Pipe с именем srvsvc (рисунок 3). Это такой же интерфейс для удалённого выполнения функций, как и svcctl, о которой упоминалось ранее. Данный вызов требуется лишь для поиска доступных на запись общих ресурсов, поэтому такое событие мы можем смело опускать при подготовке правила детектирования. Здесь оно приведено только для информации.

Рисунок 3. Специфичный для PsExec от Impacket лог доступа к Pipe с именем srvsvc
Рисунок 3. Специфичный для PsExec от Impacket лог доступа к Pipe с именем srvsvc

Далее мы видим событие, сообщающее нам о записи файла на машину через общий ресурс (рисунок 4). Обращаем ваше внимание: как и имя файла, так и общий ресурс могут быть любыми.

Рисунок 4. Запись файла на машину через общий ресурс
Рисунок 4. Запись файла на машину через общий ресурс

После чего используется именованный канал с именем srvctl для создания и запуска сервиса. Этот лог идентичен первому и мы не будем приводить его повторно.

В то же время можно точно определить, что этот Pipe был использован для создания сервиса по другому логу EventID 4697 (A service was installed in the system). Он сообщает нам о создании новых сервисов на машине (рисунок 5):

Рисунок 5. Лог создания службы
Рисунок 5. Лог создания службы
Событие 4697 для оригинального PSExec
Рисунок 6. Создание службы при эксплуатации оригинального PsExec
Рисунок 6. Создание службы при эксплуатации оригинального PsExec

И уже из событий EventID 4688 (A new process has been created) увидим, каким образом происходит запуск указанного файла (рисунок 7):

Рисунок 7. Лог запуска файла
Рисунок 7. Лог запуска файла

На этом этапе, показано обращение к ранее несуществующим Pipes, названия которых могут быть произвольными, но всегда с уникальными именами. И их должно быть 4. Ниже приведены примеры логов запроса доступа ко всем 4-м уникальным Pipes (рисунки 8-11):

Рисунок 8. Обращение к новым Pipes
Рисунок 8. Обращение к новым Pipes
Рисунок 9. Обращение к новым Pipes
Рисунок 9. Обращение к новым Pipes
Рисунок 10. Обращение к новым Pipes
Рисунок 10. Обращение к новым Pipes
Рисунок 11. Обращение к новым Pipes
Рисунок 11. Обращение к новым Pipes

К сожалению, строить детект, основываясь только на логах EventID 5145, представленных здесь, нельзя, потому что если подключиться к svcctl напрямую через RPC, их запросто можно обойти. Чтобы решить эту проблему, воспользуемся RPC Filtering.

RPC Filtering

Интересной альтернативой событиям, поставляемым через ETW провайдеры, может стать RPC Filtering. Из плюсов - мы имеем возможность просмотра событий в привычном нам Event Viewer. Сама по себе технология логирования требует небольшой настройки. Для сбора событий нам нужно сделать отдельное правило для аудита интерфейса svcctl, который имеет UUID == 367abb81-9844-35f1-ad32-98f038001003.

rpc filter
add rule layer=um actiontype=permit audit=enable
add condition field=if_uuid matchtype=equal data=367abb81-9844-35f1-ad32-98f038001003
add filter

Сохраняем его в файл и применяем:

netsh -f rpcauditrule.txt

И теперь при использовании svcctl можно получать логи, подобные событиям с EventID 5145 (Detailed File Share), показанным на рисунке 11, но которые будут формироваться даже если пользователь подключился по RPC напрямую. Однако при локальном изменении сервисов события создаваться не будут, что нам как раз и нужно для определения использования PsExec.

Рисунок 11. Обращение к svcctl
Рисунок 11. Обращение к svcctl

В событии EventID 5712 (A Remote Procedure Call (RPC) was attempted) видно пользователя, который подключается к интерфейсу. Сравнивая его с другими логами, станет понятно, что это тот же пользователь, который создал сервис и загрузил бинарник.

Таким образом мы узнали, какую полезную информацию можно получить из событий журнала Windows Security. Далее посмотрим, удастся ли нам найти что-то интересное в логах Sysmon.

События Sysmon

Одной из особенностей Sysmon является то, что сервис логирует не просто использование именованных каналов, но ещё и их создание, а также указывает путь к программе-создателю. Это бывает полезным, если у нас существует ПО, которое часто создаёт/использует "пайпы", так как мы можем коррелировать этот конкретный бинарник с тем, что был загружен с помощью SMB и как сервис.

На рисунке 12 как раз приведён пример события, сообщающего нам о создании именованного канала, - EventID 17 (Pipe created). И здесь показан процесс, его создающий.

Рисунок 12. Создание Pipe RemCom_communication
Рисунок 12. Создание Pipe RemCom_communication

Далее фиксируется событие подключения к Pipe EventID 18 (Pipe connected), он показан на рисунке 13:

Рисунок 13. Подключение к Pipe RemCom_communication
Рисунок 13. Подключение к Pipe RemCom_communication

Как мы видим, к сожалению, в данном случае Sysmon не сказал нам ничего интересного об управлении сервисами или использовании SMB. Это значит, что применять его как единственный источник для подготовки правила детектирования мы не сможем и будем рассматривать только как дополнительный.

Теперь посмотрим, получится ли у нас узнать какую-либо полезную информацию через мониторинг сетевого трафика.

Сетевой уровень

Сетевой трафик содержит информацию, зачастую отсутствующую, как у Sysmon, так и у Windows EventLog. Например, вызовы PRC функций.

Примечание о SMB3

Важно заметить, что по умолчанию все скрипты Impacket будут использовать SMB3 и шифровать все запросы к SMB и RPC, что делает детект на основе сетевого трафика проблематичным.

Сразу после аутентификации можно заметить обращение к Pipes svcctl и srvsvc с помощью RPC вызовов (рисунок 14).

Рисунок 14. Обращение к svcctl
Рисунок 14. Обращение к svcctl

Тогда как svcctl нужен для создания и запуска сервиса на удалённой машине,а srvsvc в свою очередь требуется только для функции NetShareEnumAll, которая покажет атакующему доступные общие ресурсы, что отображено на рисунке 15:

Рисунок 15. Обращение к srvsvc
Рисунок 15. Обращение к srvsvc

После чего, как мы видим на рисунке 16, происходит передача зловредного файла через ресурс ADMIN$ на удалённую машину.

Рисунок 16. Передача "сервиса" на удалённую машину
Рисунок 16. Передача "сервиса" на удалённую машину

Потом вызываются функции для создания и запуска сервиса через RPC (рисунок 17).

Рисунок 17. Создание и запуск сервиса с точки зрения трафика
Рисунок 17. Создание и запуск сервиса с точки зрения трафика

А далее мы увидим функции коммуникации через Pipes (рисунок 18). Основная "труба" имеет название RemCom_communication.

Рисунок 18. Создание "трубы"
Рисунок 18. Создание "трубы"

Это название пришло из открытого проекта, призванного заменить оригинальный PsExec и на основе которого был построен PsExec из набора Impacket, но, конечно, название может быть изменено.

Дальнейшая коммуникация происходит полностью с помощью Pipes с названиями:

  • RemCom_stdinIvDN20384;

  • RemCom_stdoutIvDN20384;

  • RemCom_stderrIvDN20384;

Здесь важно отметить, что вся последняя часть названий Pipes является рандомными символами. Это наглядно видно на рисунке 19:

Рисунок 19. Обращение к Pipes
Рисунок 19. Обращение к Pipes

Итак, с помощью сетевого трафика можно отследить вызовы RPC для обращения к Pipes, а также для создания и запуска службы. Однако в случае PsExec от Impacket запросы к SMB и RPC будут шифроваться, поэтому строить детект, основываясь исключительно на трафике, мы не можем.

Перейдем к выводам.

Итоги по событиям

Лучший, по нашему мнению, способ детектирования будет строиться на основе событий журнала Windows Security со включенным правилом RPC Filtering. Таким образом мы сможем надёжно детектировать использование PsExec и при этом не подвергать себя ненужным ложным срабатываниям.

Возможное правило детекта

Исходя из приведённых событий выше, характеризующих каждый из обязательных шагов к эксплуатации, можно написать псевдо-правило для разных вариаций PsExec, которые различаются лишь названиями каналов, файлов и служб.

SELECT *
FROM (EventCode=4697)
WHERE (Service_File_Name) IN
(
    SELECT Relative_Target_Name
    FROM (EventCode=5145)
	WHERE Share_Name!="\\\\*\\IPC$" && Relative_Target_Name!="\\" 
)
AND source_address!=127.0.0.1

Дополнительно к этому правилу есть возможность добавить отсеивание событий на создание пайпов и их использование, но, конечно, существует вероятность наткнуться на злоумышленника, который Pipes не использует вовсе. Также в правиле не используется доступ к svcctl, поскольку получить доступ к менеджеру сервисов можно не только через Pipes. При этом детектировать множество возможностей для подключения проблематично (но вероятно), поэтому в правиле мы это опускаем .

И еще один возможный вариант детектирования

Другой вариант детектирования PsExec - с учетом логов Sysmon. Как было сказано ранее, особенностью Sysmon является то, что он позволяет логировать не просто использование Pipes, но ещё и их создание, а также указывает путь к программе-создателю. Поэтому ниже мы представим небольшой Python скрипт, реализующий ту же логику, что и в предыдущем правиле, но с учетом включенного RPC Filter и с добавлением мониторинга Pipes через Sysmon.

detectionTable = {
	"doesSRVCTLtouched": False,
	"doesServiceCreated": False,
	"executableFileName": 0,
	"userName": 0,
	"isSvcctlTouched": False
}

pipesTempStorage = []

def convertListToJSON(list):
	js = {}

	for element in list:
		js[element["_Name"]] = element["__text"]

	return js

for log in logs:

	if "EventCode" in log:
		if log["EventCode"] == 5145 and \
		log["Share Information"]["Share Name"] != "\\\\*\\IPC$":
			# Make semi-absolute path to binary
			folder = log["Share Information"]["Share Path"]
			folder = folder[folder.index(':') + 1:] + "\\"

			detectionTable["executableFileName"] = folder + log["Share Information"]["Relative Target Name"]

		if log["EventCode"] == 4697 \
		and (detectionTable["executableFileName"] in log["Service Information"]["Service File Name"]):
			detectionTable["doesServiceCreated"] = True
			detectionTable["userName"] = log["Subject"]["Account Name"]

		if log["EventCode"] == 5712 \
		and (detectionTable["userName"] == log["Subject"]["Name"]):
			detectionTable["isSvcctlTouched"] = True

	else:
		SysmonData = convertListToJSON(log["Event"]["EventData"]["Data"])

		if SysmonData["EventType"] == "CreatePipe" \
		and (detectionTable["executableFileName"] in SysmonData["Image"]) \
		and (SysmonData["PipeName"] not in pipesTempStorage):
			pipesTempStorage.append(SysmonData["PipeName"])

	if detectionTable["isSvcctlTouched"] \
	and (len(pipesTempStorage) >= 4):
		print("Attack!")

Заключение

В этой статье мы рассказали о самом известном и популярном инструменте, который используется в тактике Lateral Movement - PsExec. При анализе возможного варианта детектирования нами были рассмотрены теоретические аспекты обнаружения, а также на практике разобраны возможные источники логов для его построения. Таким образом, мы определили, что самым лучшим, с точки зрения информативности, будет способ детектирования, основанный на событиях журнала Windows Security со включенным RPC Filtering правилом. В качестве альтернативы также представили небольшое Python-правило, учитывающее также логи создания Pipes в Sysmon.

Оставляйте ваши комментарии ниже и пишите вопросы. Надеемся, статья оказалась вам полезной!

Авторы:
- Черных Кирилл (@Ruucker), аналитик-исследователь киберугроз;
- Мавлютова Валерия (@Iceflipper), младший аналитик-исследователь киберугроз.

Комментарии (7)