Всем привет!
Сегодня речь пойдёт о распределенном обратном прокси-сервере ngrok и эксплуатации его возможностей атакующими.Несмотря на то что изначально ngrok создавался как легитимный инструмент для удалённого доступа и тестирования веб-приложений, он часто становится частью атак, помогая обходить сетевые фильтры и скрывать реальное расположение атакующей инфраструктуры.
По данным MITRE ATT&CK, инструмент используется различными APT-группировками, в том числе в атаках, направленных на компании в России и странах СНГ, что упоминается в Ландшафте киберугроз от команды Kaspersky Cyber Threat Intelligence и в Большом ежегодном исследовании ландшафта киберугроз в России и СНГ от команды BI.ZONE.
Цель этой статьи — показать на реальных примерах, как ngrok применяется в операционных системах Windows и Linux, и определить ключевые маркеры, по которым можно выявить его использование. Материал будет полезен специалистам по кибербезопасности, SOC-аналитикам и администраторам, которые хотят своевременно обнаруживать и предотвращать подобные угрозы в своей инфраструктуре.
Что такое ngrok и почему он опасен
ngrok — это платформа, которая с помощью клиентского приложения на хосте позволяет организовать удалённый доступ к запущенным внутренним ресурсам клиента. Доступ организуется через созданный при запуске ngrok безопасный туннель. Хост при этом может находиться за NAT’ом и не иметь статического белого IP-адреса. ngrok
поддерживает HTTP, TLS или TCP соединения. На схеме ниже представлена упрощенная схема подключения с использованием ngrok
. На этой схеме при помощи клиента ngrok
организуется tcp-туннель с сервером ngrok
, далее клиент транслирует пакеты на порт 22 SSH "жертвы". При этом при подключении с третьего узла к серверу ngrok
такое соединение транслируется на порт 22 SSH хоста с установленным ngrok
. Благодаря такому подключению можно получить доступ к удалённому шеллу без прямой сетевой связности.
В данной схеме клиент ngrok
используется только на стороне "жертвы", атакующему для организации не требуется установка и запуск дополнительного программного обеспечения на своем хосте.

Использование ngrok
Для использования ngrok
требуется токен, который можно получить бесплатно зарегистрировавшись на сайте ngrok.

Для использования агента требуется добавить authtoken
, полученный в личном кабинете.
Для добавления можно воспользоваться командой:
ngrok config add-authtoken
Запустить ngrok
с использованием стандартной конфигурации можно одной из команд:
## Туннелирование http соединения по 80 порту
ngrok http 80
Туннелирование tcp соединения по 3389 порту RDP
ngrok tcp 3389
Туннелирование tcp соединения по 22 порту ssh
ngrok tcp 22
Анализ артефактов
Для удобства фильтрации и поиска событий мы будем использовать R-Vision SIEM. Одной из функций продукта является централизованное управление событиями в информационных системах. Для начала рассмотрим события связанные с запуском ngrok.
События создания процесса
При создании процесса ngrok
в операционной системе семейства Windows генерируется событие c EventID 4688 (A new process has been created) журнала Security
и событие с EventID 1 (Process creation) журнала Sysmon/Operational
. В событиях отражаются аргументы, указанные при создании процесса, которые при нормализации записываются в поле cmd
события в SIEM.

В системе линукс событие запуска фиксируется в журнале auditd с системным вызовом execve:

На основе событий запуска процесса можно отслеживать характерные для ngrok
параметры запуска. Ниже приведены различные варианты запуска процесса ngrok
. Параметры запуска совпадают для операционных систем Windows и Linux.
# Создание туннеля для RDP
ngrok tcp 3389
# Создание туннеля для HTTP
ngrok http 8080
# добавление токкена
ngrok config add-authtoken {TOKEN}
# добавление для управления api ngrok
ngrok config add-api-key {API_KEY}
# добавление URL адреса сервера ngrok
ngrok config add-server-addr {SERVER_ADDR}
# использование статичного туннеля
ngrok http 8080 --domain jumpy-red-mollusk.ngrok-free.app
# проверка конфигурации
ngrok config check
#применение конфигурации
ngrok http --config config1.yml
# создание всех туннелей указанных в конфигурационном файоле
ngrok start --all
На этих признаках основано правило sigma от исследователя Florian Roth.
Данный критерий только косвенно может подсветить об использовании клиента ngrok
, так как имя процесса можно изменить, а параметры с которыми запускается процесс, могут быть характерны для другого инструмента.
Вторым маркером ngrok
, который мы рассмотрим, будет создание и изменение файла конфигурации ngrok.yaml
.
Изменения файла конфигурации
ngrok
использует файл конфигурации для хранения различных параметров, таких как ключ авторизации, адрес сервера и других. По умолчанию файл конфигурации размещается по пути:
Для операционных систем семейства Microsoft:
%UserProfile%\AppData\Local\ngrok\ngrok.yml
;Для операционных систем семейства Linux:
$home/.config/ngrok/ngrok.yml
;
Событие создание файла конфигурации в операционной системе Windows можно отслеживать на основе событий c Event ID 11 (FileCreate) журнала Sysmon/Operational
. В событиях отражается путь к созданному файлу конфигурации, который при нормализации записывается в поле filePath
события в SIEM.

Событие изменения файла в конфигурации в операционной системе Windows можно отслеживать на основе событий c Event ID 4663 (An attempt was made to access an object) журнала Security
, для генерации которого требуется настройка SACL. Так как маловероятно, что SACL будет установлен на директорию %UserProfile%\AppData\Local\
данное событие рассматривать не будем.
Событие создания или изменения файла конфигурации в операционной системе Linux можно отслеживать на основе событий auditd с системным вызовом openat. В событии, аналогично рассмотренному выше для Windows, путь к файлу конфигурации устанавливается в поле filePath
нормализованного события.

На основе данных событий можно обнаруживать, в том числе модифицированный клиент ngrok
, который мы могли не обнаружить на основании событий рассмотренных в разделе "События создания процесса". Но ngrok
позволяет использовать конфигурационный файл расположенный в иной директории и с другим именем.
Далее рассмотрим события связанные с сетевыми соединениями.
Сетевые соединения
Клиенту ngrok
требуется взаимодействовать с сервером для получения и передачи различной управляющей конфигурации, например для проверки лицензии. В качестве такого сервера в клиенте используется connect.ngrok-agent.com:443
.
События в Windows
В Windows DNS запросы регистрируются в событии c EventID 22 (DNSEvent) журнала Sysmon/Operational
:

DNS-запросы в операционной системе Windows также можно отслеживать с помощью службы Event Tracing for Windows(ETW). Для этого мы будем использовать провайдер Microsoft-Windows-DNS-Client
.
Подробнее со службой трассировки можно познакомиться в статье Изучаем Event Tracing for Windows: теория и практика.
Посмотреть сформированный лог можно через Event Viewer.

События в Linux
Сетевые соединения в операционной системе Linux можно отслеживать при помощи системного вызова [connect](connect(2) - Linux manual page (man7.org)). В событии можно аналогично рассмотренному в разделе создания процессов увидеть команду с которой запускался процесс, а также IP-адрес используемого сервера ngrok.

В качестве сервера ngrok
используются сервера Amazon AWS Network Operations, список которых приведен на странице s3.amazonaws.com. Данный список может меняться, поэтому эффективнее для обнаружения использовать события, содержащие DNS-запросы. Однако в операционной системе Linux анализировать DNS-запросы при помощи инструмента auditd
не получится, поэтому рассмотрим инструменты для анализа сетевого трафика.
Анализ сетевого трафика
Одним из методов анализа может быть анализ сетевого трафика с использованием специального программного обеспечения, например,tcpdump
или Wireshark
(метод применим для всех операционных систем). Ниже приведен пример запросов в программе `Wireshark
`:

Использование средств для анализа сетевого трафика для мониторинга сетевых подключений избыточно, и по их выводу трудно понять, что вызвало данную активность, поэтому рассмотрим специализированное решение для регистрации DNS-запросов.
eBPF в действии
В Linux одним из методов может выступать логирование DNS-запросов решений на базе eBPF. В качестве примера рассмотрим использование eBPF-dns-monitor. Инструмент представляет собой программу, написанную на Python, использующую библиотеку bcc. Программа фильтрует сетевые пакеты, направленные на 53 порт и формирует лог.
На скриншоте представлен вывод работы данного скрипта при запуске клиента ngrok. В выводе содержится информация о DNS-запросе, процессе, который вызвал данный запрос, и пользователе.

Отслеживая сетевое взаимодействие и сопоставляя его со списком серверов туннелирования, можно эффективно обнаруживать активность ngrok
. В журнале eBPF-dns-monitor
также фиксируем запрос IP для имени update.eqyinox.io
.hero
, который используется для получения обновлений клиента.
Еще одним маркером для эффективного обнаружения ngrok
, является анализ событий, связанных с созданием TCP-туннеля при подключении к RDP.
Туннелирование RDP
Для обнаружения использования RDP-туннеля в событиях также можно использовать событие службы Sysmon c EventID 3 (Network connection detected) для поиска необычных процессов, связывающих порт RDP с localhost:

В событии установлены значения DestinationIp
= ::1 и DestinationPort
= 3389
, которые характерны при подключении через туннель.
Дополнительно в событиях Event ID 4778 (A session was reconnected to a Window Station) и Event ID 4779 (A session was disconnected from a Window Station) журнала Security
, в поле ClientAddress
(поле cs3
нормализованного события) устанавливается значение ::%16777216
, которое устанавливается при сетевом подключении по IPv6 к локальному сервису.

Аналогичное значение фиксируется в поле Param3
события EventID 1149 (Remote Desktop Session Host Listener Availability) журнала Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational
и в поле Address
события EventID 24 (Remote Desktop Services: Session has been disconnected) журнала Microsoft-Windows-TerminalServices-LocalSessionManager/Operational.
Рассмотренные маркеры, зафиксированные в событиях при использовании RDP туннеля могут быть характерны для других аналогичных ngrok
инструментов. Разбор иных инструментов и способов туннелирования выходит за рамки статьи.
Охота на двоичный файл ngrok
Исполняемый файл клиента ngrok
можно найти по вхождению характерных строк используя YARA. К примеру можно использовать правило предложенное исследователем Moath Maharmeh. В данном правиле проверяется вхождение 3 или более строк из списка в файле: ngrok
, go.ngrok.com
, https://s3.amazonaws.com/dns.ngrok.com/tunnel.json
, ngrokService
, HTTPRoundTrip_KeyVal
.
Продемонстрируем работу правила с использованием сканера Simple-Yara:

На основе полученной информации, мы разработали правила детектирования использования инструмента ngrok на операционных системах Windows и Linux.
Правила детектирования в R-Vision SIEM
Для детектирования активности ngrok
представлены правила на языке VRL для продукта R-Vision SIEM.
Благодаря первому правилу можно отследить использование ngrok
на устройстве соперационной системой Windows по рассмотренным в статье маркерам.
Правило обрабатывает события с EventID 1, 11, 22 журнала Sysmon/Operationals
и события c EventID 4688 журнала Security.
filter: !vrl |
.dvendor == "Microsoft" &&
# Список EventID, которых обрабатывает правило
includes(["1","3","11","22","4688"], .externalId)
aliases:
ngrok:
filter: !vrl |
cmd, _err = downcase(.cmd)
cs1, _err = downcase(.cs1)
cs2, _err = downcase(.cs2)
dproc, _err = downcase(.dproc)
filePath, _err = downcase(.filePath)
# Блок кода обрабатывает события создания процесса
(includes(["1", "4688"], .externalId) &&
# Проверка по явному признаку содержания ngrok в названии процесса или в описании
(ends_with(dproc, "ngrok.exe") || contains(cs2, "ngrok") ||
# Проверка характерных для ngrok параметров коммандной строки "config add-server-addr",
# "config add-api-key", "config add-authtoken"
rv_contains_any(cmd, ["config add-server-addr", "config add-api-key", "config add-authtoken"]))) ||
# Проверка создания файла конфигурации ngrok.yml используемого по умолчанию на основе
# события с EventID 3 журнала Sysmon
(.externalId == "11" &&
ends_with(filePath, "\\appdata\\local\\ngrok\\ngrok.yml")) ||
# Проверка наличия в поле QueryName сервера управления ngrok на основе
# события с EventID 22 журнала Sysmon
(.externalId == "22" &&
(contains_all(cs1, ["connect", "ngrok-agent.com"]) ||
contains_all(cs1, ["tunnel", "ngrok.com"])))
Второе правило предназначено для отслеживанияRDP
подключений с использованием туннеля на основе событий с EventID 3, 4778, 4779.
filter: !vrl |
.dvendor == "Microsoft" &&
includes(["3","4778", "4779"], .externalId)
aliases:
rdpTunneling:
filter: !vrl |
# Проверяет значения поля ClientAddress в событиях с EventID 4778, 4779 со значением ::%16777216
(includes(["4778","4779"], .externalId) && contains(to_string(.cs3) ?? "", "::%16777216")) ||
# Проверяет значения полей SourceIP и DestinationIP равное ::1
# в событиях с EventID 3, где DestinationPort 3389
(.externalId == "3" &&
(ip_to_ipv6(.destinationTranslatedAddress) ?? "") == "::1" &&
(ip_to_ipv6(.sourceTranslatedAddress) ?? "") == "::1" &&
(to_int(.destinationTranslatedPort) ?? 0) == 3389)
Третье правило предназначено для отслеживания использования ngrok
на хостах с операционными системами семейства Linux.
Правила обрабатывает системные вызовы openat, execve, connect ,рассмотренные в статье и отслеживает характерные параметры запуска, а так же изменение файлов конфигурации используемые по умолчанию.
filter: !vrl |
.dvendor == "Linux" &&
includes(["oa", "execve","connect"], downcase(.cat) ?? "")
aliases:
ngrok:
filter: !vrl |
cat = downcase(.cat) ?? ""
dproc = downcase(.dproc) ?? ""
# Блок кода отслеживает явное указание ngrok в событии с системным вызовом connect
(cat == "connect" &&
ends_with(dproc,"/ngrok")) ||
# Блок кода отслеживает использование характерных для ngrok команд "config add-server-addr",
# "config add-api-key", "config add-authtoken" в событиях с системным вызовом execve
(cat == "execve" &&
rv_contains_any(downcase(.cmd) ?? "", ["config add-server-addr", "config add-api-key", "config add-authtoken"])) ||
# Блок кода отслеживает создание файла ngrok.yaml, используемые по умолчанию
# на основе событий с системным вызовом openat
(cat == "oa" &&
.filePermission == "w" &&
.cs4 == "openat" &&
contains(downcase(.filePath) ?? "", "ngrok.yml"))
При получении событий подходящих под фильтры получим оповещение в R-Vision SIEM.
Заключение: что делать
ngrok — один из примеров легальных инструментов, которые нередко используются атакующими в ходе кибератак, в том числе против организаций в России и странах СНГ. Изначально у разработчиков не было цели сделать его невидимым для средств обнаружения, поэтому при грамотной настройке мониторинга его активность можно выявить с помощью SIEM-решений.
К ключевым маркерам, позволяющим обнаружить ngrok, относятся:
имя исполняемого файла
ngrok
, описание процесса или характерные параметры командной строки в событиях запуска процесса;имя исполняемого файла в событиях
auditd
на основе системного вызоваconnect
;наличие конфигурационного файла
ngrok.yaml
в событиях создания и модификации файлов;DNS-запросы к доменам серверов
ngrok
;сетевые соединения с серверами
ngrok
из известного списка;использование характерного адреса источника при трансляции RDP-соединений через
ngrok
;уникальные строки в исполняемых файлах клиента
ngrok
, описанные в разделе «Охота на двоичный файл ngrok».
Практические рекомендации:
Добавить вышеуказанные индикаторы в правила корреляции SIEM и настроить автоматические оповещения.
Внедрить регулярный аудит системных журналов и сетевых соединений на наличие обращений к инфраструктуре
ngrok
.Обновлять базу IOC (Indicators of Compromise) и списки доменов/адресов, связанных с ngrok.
Использовать EDR/NGFW с возможностью блокировки специфичных для
ngrok
паттернов трафика.
Применение этих мер позволит не только своевременно выявить использование ngrok
в вашей сети, но и минимизировать риск его эксплуатации злоумышленниками.
Автор: Борис Нестеров @dino_cn, аналитик-исследователь угроз кибербезопасности R-Vision.