АйТи Фреш
Главная / Статьи / Безопасность
Безопасность

Kea Control Agent доступен по сети: проверяем возможность загрузки hooks с правами root

Автор: Семёнов Евгений Сергеевич, директор ООО «АйТи-Фреш» · · ~7 мин чтения
Kea Control Agent доступен по сети: проверяем возможность загрузки hooks с правами root

Сканер обнаружил Kea Control Agent и написал про выполнение кода. Перезагружать DHCP, закрывать порт или готовиться к восстановлению сервера? Я, Семёнов Евгений Сергеевич, директор ООО «АйТи-Фреш», начинаю с проверки конкретной цепочки: кто достучится до API, какие команды ему разрешены, откуда загрузится библиотека и чьи права она получит. Покажу порядок диагностики и результаты лабораторной проверки одного пакета в разных режимах.

Открытый API ещё не доказывает удалённый захват сервера

Для выполнения собственного кода через hooks атакующему нужны сразу несколько условий. Он должен добраться до административного API, получить возможность передать подходящую конфигурацию и указать доступную процессу библиотеку под своим контролем. Дальше загрузку должны разрешить ограничения Kea и операционной системы. Если загружающий процесс имеет UID 0, код библиотеки получает его привилегии. Именно последнее звено превращает проблему DHCP в потенциальную компрометацию сервера.

ISC описывает этот механизм в CVE-2025-32801 как локальное повышение привилегий: непривилегированный пользователь размещает файл и обращается к недостаточно защищённому API. Затронуты upstream-версии 2.4.0–2.4.1, 2.6.0–2.6.2 и 2.7.0–2.7.8; первые исправления вышли в 2.4.2, 2.6.3 и 2.7.9. Версии до 2.4 ISC не оценивала. Сетевой доступ расширяет круг потенциальных атакующих, но сам по себе не объясняет, как их библиотека попадёт на сервер. [Уведомление ISC](https://kb.isc.org/docs/cve-2025-32801).

На 5 сентября 2026 года актуальны стабильная Kea 3.2.0 и LTS 3.0.4. Ветка 2.6 завершила поддержку у ISC; сопровождение дистрибутивом проверяется отдельно. Для существующего внедрения с Control Agent я рассматриваю поддерживаемую LTS и план миграции: в 3.0 агент объявлен устаревшим, а в 3.2 удалён. Прямой HTTP(S) API демонов сохраняет административные возможности, поэтому обновление архитектуры не заменяет ограничение доступа. [Версии ISC](https://www.isc.org/kea/), [миграция с Control Agent](https://kb.isc.org/docs/kea-control-agent-migration).

Мой критерий: отдельно подтвердить доступ к управлению DHCP и отдельно — возможность исполнения контролируемой библиотеки с привилегиями целевого процесса.
Цифры и версии: Открытый API ещё не доказывает удалённый захват сервера — схема
Цифры и версии: Открытый API ещё не доказывает удалённый захват сервера

Сначала проверяю bind address и реальную аутентификацию

Начните с фактического слушающего сокета: `sudo ss -lntp`. Порт 8000 — стандартный, но искать нужно все слушатели нужного процесса. `127.0.0.1` ограничивает прямые подключения локальным сетевым пространством; `0.0.0.0` означает все IPv4-интерфейсы. Между слушателем и атакующим остаются маршрутизация и firewall. Отдельно проверьте IPv6, reverse proxy и опубликованные контейнерные порты. Надпись «внутренний адрес» меня не успокаивает, пока API доступен из пользовательского VLAN.

В Control Agent адрес задаёт `http-host`, порт — `http-port`; без этих параметров используется `127.0.0.1:8000`. Для Basic важен непустой список `authentication.clients`: одного блока с `type: basic` недостаточно. Я проверяю три обращения: без учётных данных, с неправильным паролем и с рабочим. Пароль передаю только через защищённый транспорт; Basic поверх обычного HTTP не обеспечивает его конфиденциальность. [Конфигурация Control Agent](https://kea.readthedocs.io/en/kea-3.0.4/arm/agent.html).

Для первичной проверки подходят запросы ниже. Адрес документационный — замените его своим. Выполните их с административного узла и из сегмента, которому управление запрещено. Смотрите одновременно HTTP-код и JSON: HTTP 200 ещё не означает успешное выполнение команды. `list-commands` показывает поддерживаемые команды, но наличие `config-set` в списке не доказывает разрешение записи при RBAC или фильтрации посредником. Пароль также не создаёт автоматически роль «только мониторинг». [Справочник API](https://kea.readthedocs.io/en/kea-3.0.4/api.html).

Loopback закрывает прямой сетевой путь. Локальные пользователи и процессы всё ещё могут обращаться к нему, поэтому аутентификация нужна и здесь.
Kea Control Agent доступен по сети: проверяем возможность загрузки hooks с правами root — схема

Выясняю, какой процесс загрузит библиотеку

Здесь легко проверить не того пользователя. Запрос без `service`, либо с пустым списком, обрабатывает сам Control Agent. Библиотеку из `Control-agent.hooks-libraries` загружает `kea-ctrl-agent`. При `"service":["dhcp4"]` агент пересылает команду через Unix-сокет, а библиотеку из `Dhcp4.hooks-libraries` загружает уже `kea-dhcp4`. Поэтому непривилегированный CA перед DHCP-сервером, работающим от root, не исключает root-impact. [Алгоритм обработки команд CA](https://kea.readthedocs.io/en/kea-2.6.4/arm/agent.html).

Я сопоставляю PID, эффективный UID, командную строку и unit каждого адресата. Строка `User=kea` в найденном файле ещё не доказывает, что именно так запущен работающий процесс: встречаются drop-in, собственные unit и ручные старты. Для Linux смотрю также capabilities и ограничения службы. `NoNewPrivileges=yes` ограничивает получение новых привилегий через запуск программ, но не отбирает уже имеющиеся права у кода, загруженного внутрь процесса. [Семантика systemd](https://github.com/systemd/systemd/blob/main/man/systemd.exec.xml).

Следующая точка — Unix-сокет и весь путь к нему. Проверяю владельца, группы, ACL и права родительского каталога через `namei -l` и `getfacl`. Если посторонний пользователь может обращаться прямо к DHCP-сокету, пароль HTTP-агента его не остановит. Добавление учётной записи мониторинга в группу Kea тоже требует осознанного решения: доступ к сокету предоставляет административный API. [Файлы и права Kea](https://kb.isc.org/docs/kea-files).

UID 0 внутри контейнера не равен автоматически root на хосте: границу ущерба дополнительно определяют user namespace, capabilities и доступные монтирования.
Памятка: Выясняю, какой процесс загрузит библиотеку — схема
Памятка: Выясняю, какой процесс загрузит библиотеку

Проверяю путь hooks и не использую config-test как песочницу

`library` обозначает локальную библиотеку, а не URL для скачивания. Файл должен существовать в файловой системе, которую видит адресат команды. Для рассматриваемой цепочки нужно установить, кто способен создать или подменить этот файл. Проверяйте доступные на запись каталоги, общие тома и пути развёртывания. Возможность изменять JSON не равна возможности передать ELF-бинарник: штатный `config-set` сам по себе не является загрузчиком файлов. Механизм эксплуатации исследован командой SUSE. [Разбор первооткрывателей](https://security.opensuse.org/2025/05/28/kea-dhcp-security-issues.html).

Начиная с 2.6.3 в соответствующей стабильной ветке, hooks разрешено загружать из каталога, заданного при сборке. Его показывает `kea-ctrl-agent -W` или `kea-dhcp4 -W` как Hooks directory. При запуске каталог можно переопределить переменной `KEA_HOOKS_PATH`; это не поле REST-запроса. Проверяйте фактическое окружение процесса, владельцев библиотек и каталогов. В Kea 3.0 появился также флаг `-X`, отключающий ограничения путей и прав. Обновлённый бинарник с таким флагом требует отдельной оценки. [Ограничение каталога](https://kea.readthedocs.io/en/kea-2.6.3/arm/hooks.html#configuring-hook-libraries), [флаг запуска CA](https://kea.readthedocs.io/en/kea-3.0.4/arm/agent.html).

И неприятная деталь: проверка совместимости библиотеки тоже может исполнять её код. В исходниках Kea 3.0.4 проверка hooks включает открытие через `dlopen` и вызов `version()`; для CA она выполняется и при `config-test`. Это вывод из кода, а не предположение по названию команды. Ошибка ABI или совместимости с многопоточностью не доказывает, что исполнения ещё не было. [Парсер CA](https://github.com/isc-projects/kea/blob/Kea-3.0.4/src/bin/agent/simple_parser.cc#L176), [загрузчик библиотек](https://github.com/isc-projects/kea/blob/Kea-3.0.4/src/lib/hooks/library_manager.cc#L378).

Не отправляйте config-test с неизвестной .so на рабочий сервер. config-set также не годится для пробного «касания»: он заменяет полную конфигурацию и может нарушить обслуживание.

Лабораторная проверка: один пакет, три режима

Для статьи я проверил именно лабораторный запуск, без привязки к клиентскому проекту. Среда — Ubuntu 24.04, архитектура amd64, пакет `kea-ctrl-agent` версии `2.4.1-3ubuntu0.2`; сам бинарник сообщает `2.4.1`. Пакет и зависимости распакованы отдельно, системная служба не устанавливалась. Это существенно: ручной старт не воспроизводит штатную защиту Ubuntu через service user, AppArmor и подготовленную конфигурацию. Canonical прямо учитывает эти меры при оценке CVE-2025-32801. [Позиция Ubuntu](https://ubuntu.com/security/CVE-2025-32801).

Во всех запусках использовался адрес `127.0.0.1:18083`, без публикации наружу. Сначала агент работал с эффективным UID 0, без аутентификации. Существенная часть конфигурации выглядела так: `{"Control-agent":{"http-host":"127.0.0.1","http-port":18083}}`; дополнительно логирование направлялось в stdout. POST с телом `{"command":"list-commands"}` вернул HTTP 200 и `result: 0`. В списке присутствовали `config-set`, `config-test` и `config-write`.

Затем я добавил внутрь `Control-agent` блок `authentication` с `type: basic`, `realm: lab` и одним клиентом с одноразовым лабораторным паролем. Без credentials и с неправильным паролем тот же запрос получил HTTP 401 и `Unauthorized`; с правильными — HTTP 200 и `result: 0`. В третьем режиме убрал Basic и запустил тот же бинарник через `setpriv --reuid=65534 --regid=65534 --clear-groups`. Эффективный UID 65534 подтверждён через `/proc`; ответ снова оказался успешным.

Чем закончилась проверка: root и непривилегированный процесс вернули совершенно одинаковый список из 11 команд. По такому ответу сканер не определит права процесса. Аутентификация при этом действительно изменила возможность обращения к API. Все тестовые процессы после проверки остановлены. Загрузка собственной библиотеки, удалённая достижимость извне и получение root этим опытом не проверялись — приписывать их результатам было бы технической ошибкой.

Эксперимент подтверждает различие доступа и привилегий при одинаковом пакете. Он не является демонстрацией эксплуатации.
Цифры и версии: Лабораторная проверка: один пакет, три режима — схема
Цифры и версии: Лабораторная проверка: один пакет, три режима

Что я исправляю первым

Если административный API открыт пользовательским сегментам, сначала ограничиваю сетевой доступ, сохраняя необходимые связи управления и HA. Для локального клиента выбираю loopback и аутентификацию. Для удалённого — отдельный управленческий маршрут, firewall и HTTPS с проверкой сертификатов; где инфраструктура позволяет, добавляю клиентские сертификаты. Перенос на другой номер порта можно отложить: он не заменяет эти меры. [Рекомендации ISC по защите API](https://kb.isc.org/docs/kea-security).

Для существующего CA на 3.0.4 ниже приведён фрагмент настроек доступа: его нужно объединить с рабочей конфигурацией, сохранив сокеты, hooks и логирование. Файл пароля заранее создаётся с уникальным секретом и доступом только доверенным администраторам и service user. Если CA стоит за reverse proxy, защищаю и прямой backend-путь. Иначе получается типичная ошибка: красивый вход с паролем снаружи и свободный административный порт за ним.

Далее перевожу демоны на отдельные непривилегированные учётные записи, используя поддерживаемые настройки пакета. DHCPv4 может требовать capabilities для привилегированного порта и raw sockets, поэтому слепая замена `User=root` способна остановить выдачу адресов. Библиотеки и скрипты оставляю недоступными сервису на запись; каталог данных отделяю от каталога кода. После изменений проверяю получение и продление аренды, мониторинг, DDNS и HA, если они используются. [Запуск Kea без root](https://kea.readthedocs.io/en/kea-3.0.4/arm/install.html#running-kea-from-a-non-root-account-on-linux).

Если API действительно не используется, уберите и HTTP-вход, и ненужные Unix control sockets. Перед этим проверьте зависимости Stork, автоматизации и HA.

Как сформулировать вывод, который поможет принять решение

В отчёте я разделяю факты и условия. «Из пользовательского VLAN без пароля выполнен list-commands» — проверяемый факт. «Доступна замена конфигурации» требует подтверждения правил авторизации. «Возможна загрузка контролируемой библиотеки от root» требует проверки файла, разрешённого пути, адресата команды и его полномочий. Если доставка библиотеки не установлена, так и пишу. Это не повод закрывать находку: доступ к управлению DHCP уже требует исправления.

Даже без собственного машинного кода административный API способен причинить существенный ущерб: изменить параметры выдачи адресов или отключить DHCP. Отдельная проблема — чтение конфигурации: ответ `config-get` может содержать пароли баз данных. Поэтому я не прикладываю его целиком в общий тикет. Для расследования сохраняю необходимые артефакты с ограниченным доступом, отмечаю время проверок и сравниваю активную конфигурацию с утверждённой. [Поведение команд управления](https://kea.readthedocs.io/en/kea-3.0.4/arm/ctrl-channel.html).

При признаках чужих библиотек или несанкционированной переконфигурации простого закрытия порта недостаточно: нужны сохранение доказательств и расследование возможной компрометации. А для обычной находки сканера я добиваюсь короткого, воспроизводимого заключения по пунктам ниже. Непроверенное условие остаётся неопределённостью, а проверенная граница доступа — конкретным результатом. Тогда администратор понимает, что исправлять сегодня и какую часть риска ещё предстоит подтвердить.

Частые вопросы

Можно ли передать ссылку на .so в hooks-libraries?

Поле library обозначает локальный файл, а не команду скачивания. Для рассматриваемой цепочки библиотека должна находиться в файловой системе адресата и проходить ограничения доступа и пути.

Если Control Agent работает без root, сервер защищён?

Нужно проверить адресата команды. Непривилегированный CA может пересылать команды DHCP-демону с UID 0 через доступный ему Unix-сокет.

Можно ли закрыть находку после получения HTTP 401?

Только в части проверенного входа без credentials. Дополнительно проверяются прямые порты, Unix-сокеты, права авторизованных клиентов и другие сетевые сегменты.

Проверим реальный риск Kea
Я помогу проверить доступ к API, права демонов и реальные условия загрузки hooks на вашем сервере. Оставьте заявку в rf-buh — согласуем аудит и план исправлений.
Бесплатная консультация →
© ООО «АйТи-Фреш» · Москва · Все статьи