![](https://habrastorage.org/getpro/habr/upload_files/99f/d8e/5c5/99fd8e5c54615e19b0564b12013ba295.jpg)
Привет, Хабр!
Сегодня мы поговорим о Lateral Movement (англ. горизонтальное перемещение) - тактике, используемой атакующим для продвижения по сети. Во время атак или проведения тестирований на проникновение атакующие перемещаются не вверх по привилегиям, а вбок по машинам, образно говоря "перескакивают" от одной к другой.
Как правило, одной из наиболее распространенных техник горизонтального перемещения является использование вполне стандартных протоколов удаленного подключения RDP и SSH. Но сегодня мы рассмотрим другой не менее известный и интересный способ для выполнения тактики Lateral Movement - инструмент PsExec, являющийся представителем многочисленного семейства Exec'ов куда также входят: SMBExec, DCOMExec, WMIExec и другие.
PsExec - одна из утилит, доступных в пакете Windows Sysinternals. Она предназначена для удалённого администрирования и позволяет запускать процессы, используя систему удалённого управления сервисами и передачи файлов. PsExec удобен прежде всего тем, что не требует установки: нужно всего лишь скопировать улититу в нужный каталог. Также он позволяет выполнять процессы из под SYSTEM.
В этой статье мы проведем анализ возможных источников событий, на которых впоследствии построим один из вероятных вариантов детектирования использования PsExec.
Для этого сперва кратко изучим принципы работы данного инструмента.
Принцип работы PsExec
Механизм работы выглядит следующим образом:
PsExec, используя протокол SMB, перемещает файл PsExesvc.exe (создан PsExec заранее) в сетевую папку ADMIN$ (по умолчанию);
Затем посредством RPC вызывается SCM и создается служба, она, в свою очередь, и запускает PsExesvc.exe на целевом хосте;
Сам файл создаёт именованный канал (далее по тексту Named Pipe/ Pipes), через который он общается с машиной-атакующим.
![Рисунок 1. Механизм работы инструмента PsExec Рисунок 1. Механизм работы инструмента PsExec](https://habrastorage.org/getpro/habr/upload_files/ffd/472/ead/ffd472eada7880e350b98689466dcff5.png)
Немного теории и гипотез
Когда мы изучали работу PSExec, то рассматривали как оригинальный PsExec от Марка Русиновича, так и PsExec из набора скриптов Impacket. Последний, по понятным причинам, гораздо проще модифицировать. Учитывая это, при построении логики детектирования мы должны осуществлять только обязательные шаги, необходимые для выполнения атаки. Такие как:
Передача файла на атакуемую машину;
Управление сервисами через RPC интерфейс;
Создание сервиса с файлом, загруженным на Рисунке 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](https://habrastorage.org/getpro/habr/upload_files/bc7/430/c70/bc7430c70d0e73385c17a8ecad48d7a9.png)
Ниже представлен специфичный для PsExec от Impacket лог доступа к Pipe с именем srvsvc (рисунок 3). Это такой же интерфейс для удалённого выполнения функций, как и svcctl, о которой упоминалось ранее. Данный вызов требуется лишь для поиска доступных на запись общих ресурсов, поэтому такое событие мы можем смело опускать при подготовке правила детектирования. Здесь оно приведено только для информации.
![Рисунок 3. Специфичный для PsExec от Impacket лог доступа к Pipe с именем srvsvc Рисунок 3. Специфичный для PsExec от Impacket лог доступа к Pipe с именем srvsvc](https://habrastorage.org/getpro/habr/upload_files/159/1f8/2d5/1591f82d55d0c52e4a9acea8254fcdff.png)
Далее мы видим событие, сообщающее нам о записи файла на машину через общий ресурс (рисунок 4). Обращаем ваше внимание: как и имя файла, так и общий ресурс могут быть любыми.
![Рисунок 4. Запись файла на машину через общий ресурс Рисунок 4. Запись файла на машину через общий ресурс](https://habrastorage.org/getpro/habr/upload_files/2a4/33a/f3b/2a433af3bb5e97d2479138ac399694de.png)
После чего используется именованный канал с именем srvctl для создания и запуска сервиса. Этот лог идентичен первому и мы не будем приводить его повторно.
В то же время можно точно определить, что этот Pipe был использован для создания сервиса по другому логу EventID 4697 (A service was installed in the system). Он сообщает нам о создании новых сервисов на машине (рисунок 5):
![Рисунок 5. Лог создания службы Рисунок 5. Лог создания службы](https://habrastorage.org/getpro/habr/upload_files/75b/51e/e8c/75b51ee8c772847d82a9250ca1139cc7.png)
Событие 4697 для оригинального PSExec
![Рисунок 6. Создание службы при эксплуатации оригинального PsExec Рисунок 6. Создание службы при эксплуатации оригинального PsExec](https://habrastorage.org/getpro/habr/upload_files/7b9/217/65a/7b921765ae670fc572e0fb2427954f1a.png)
И уже из событий EventID 4688 (A new process has been created) увидим, каким образом происходит запуск указанного файла (рисунок 7):
![Рисунок 7. Лог запуска файла Рисунок 7. Лог запуска файла](https://habrastorage.org/getpro/habr/upload_files/926/91f/f29/92691ff294d9122a225c274971ff95e3.png)
На этом этапе, показано обращение к ранее несуществующим Pipes, названия которых могут быть произвольными, но всегда с уникальными именами. И их должно быть 4. Ниже приведены примеры логов запроса доступа ко всем 4-м уникальным Pipes (рисунки 8-11):
![Рисунок 8. Обращение к новым Pipes Рисунок 8. Обращение к новым Pipes](https://habrastorage.org/getpro/habr/upload_files/a30/320/3ac/a303203ac732f521435ead652c1df226.png)
![Рисунок 9. Обращение к новым Pipes Рисунок 9. Обращение к новым Pipes](https://habrastorage.org/getpro/habr/upload_files/6c3/420/d67/6c3420d670d98748d0b455069782c81a.png)
![Рисунок 10. Обращение к новым Pipes Рисунок 10. Обращение к новым Pipes](https://habrastorage.org/getpro/habr/upload_files/f59/967/214/f599672149e5d4e3114e9f26d7579e7d.png)
![Рисунок 11. Обращение к новым Pipes Рисунок 11. Обращение к новым Pipes](https://habrastorage.org/getpro/habr/upload_files/b80/a64/67e/b80a6467e20cbe10fb259aadcba7c722.png)
К сожалению, строить детект, основываясь только на логах 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](https://habrastorage.org/getpro/habr/upload_files/10e/5aa/e10/10e5aae101bc988960529b935a766af9.png)
В событии 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](https://habrastorage.org/getpro/habr/upload_files/afa/7a2/413/afa7a2413b26292b443ec54304328f33.png)
Далее фиксируется событие подключения к Pipe EventID 18 (Pipe connected), он показан на рисунке 13:
![Рисунок 13. Подключение к Pipe RemCom_communication Рисунок 13. Подключение к Pipe RemCom_communication](https://habrastorage.org/getpro/habr/upload_files/21a/e7d/1be/21ae7d1be08827a46fd52401642f9bfe.png)
Как мы видим, к сожалению, в данном случае Sysmon не сказал нам ничего интересного об управлении сервисами или использовании SMB. Это значит, что применять его как единственный источник для подготовки правила детектирования мы не сможем и будем рассматривать только как дополнительный.
Теперь посмотрим, получится ли у нас узнать какую-либо полезную информацию через мониторинг сетевого трафика.
Сетевой уровень
Сетевой трафик содержит информацию, зачастую отсутствующую, как у Sysmon, так и у Windows EventLog. Например, вызовы PRC функций.
Примечание о SMB3
Важно заметить, что по умолчанию все скрипты Impacket будут использовать SMB3 и шифровать все запросы к SMB и RPC, что делает детект на основе сетевого трафика проблематичным.
Сразу после аутентификации можно заметить обращение к Pipes svcctl и srvsvc с помощью RPC вызовов (рисунок 14).
![Рисунок 14. Обращение к svcctl Рисунок 14. Обращение к svcctl](https://habrastorage.org/getpro/habr/upload_files/e86/d3a/18d/e86d3a18d865596a2eb7e4bef1c96392.png)
Тогда как svcctl нужен для создания и запуска сервиса на удалённой машине,а srvsvc в свою очередь требуется только для функции NetShareEnumAll, которая покажет атакующему доступные общие ресурсы, что отображено на рисунке 15:
![Рисунок 15. Обращение к srvsvc Рисунок 15. Обращение к srvsvc](https://habrastorage.org/getpro/habr/upload_files/637/2d4/26a/6372d426aadf5f8db51ac72300a2a989.png)
После чего, как мы видим на рисунке 16, происходит передача зловредного файла через ресурс ADMIN$ на удалённую машину.
![Рисунок 16. Передача "сервиса" на удалённую машину Рисунок 16. Передача "сервиса" на удалённую машину](https://habrastorage.org/getpro/habr/upload_files/de7/0f3/453/de70f3453712095865edf8a696ed5733.png)
Потом вызываются функции для создания и запуска сервиса через RPC (рисунок 17).
![Рисунок 17. Создание и запуск сервиса с точки зрения трафика Рисунок 17. Создание и запуск сервиса с точки зрения трафика](https://habrastorage.org/getpro/habr/upload_files/852/cd2/1f7/852cd21f7454f5d20384df402861aa05.png)
А далее мы увидим функции коммуникации через Pipes (рисунок 18). Основная "труба" имеет название RemCom_communication.
![Рисунок 18. Создание "трубы" Рисунок 18. Создание "трубы"](https://habrastorage.org/getpro/habr/upload_files/3e2/96a/0dc/3e296a0dce16c03363fd42579b9aa416.png)
Это название пришло из открытого проекта, призванного заменить оригинальный PsExec и на основе которого был построен PsExec из набора Impacket, но, конечно, название может быть изменено.
Дальнейшая коммуникация происходит полностью с помощью Pipes с названиями:
RemCom_stdinIvDN20384;
RemCom_stdoutIvDN20384;
RemCom_stderrIvDN20384;
Здесь важно отметить, что вся последняя часть названий Pipes является рандомными символами. Это наглядно видно на рисунке 19:
![Рисунок 19. Обращение к Pipes Рисунок 19. Обращение к Pipes](https://habrastorage.org/getpro/habr/upload_files/ef1/896/645/ef1896645f0522fe58f82bde09a3afcd.png)
Итак, с помощью сетевого трафика можно отследить вызовы 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), младший аналитик-исследователь киберугроз.