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

**Жертва открывает один порт: `9001`**.
Порт 9001 — это не стандартное веб-приложение. Поиск по **базе данных портов** показывает, что этот порт может быть связан с **Supervisord** (ETL Service Manager согласно IANA), Tor proxy или каким-либо другим внутренним сервисом. Однако мы не можем сделать вывод, основываясь только на номере порта.
⇒ Я напрямую обращаюсь через curl, чтобы прочитать ответ, а также открываю веб-интерфейс (GUI) для получения дополнительной информации.```
curl -i http://192.168.3.137:9001/


Анализ ответа:
Server: Medusa/1.12 и заголовок Supervisor Status→ Подтверждено, что это Supervisord, а не Tor или какой-либо другой сервис.
REFRESH, RESTART ALL, STOP ALLSupervisord — это менеджер процессов в Linux. Если port 9001 открыт в сеть без пароля, это опасная конфигурация. Атакующий может просматривать сервисы, перезапускать/останавливать процессы и при определённых конфигурациях использовать это для выполнения команд, если у него есть привилегии на изменение или управление управляемыми программами.
Вывод анализа: Мы можем подтвердить, что цель открывает административный интерфейс Supervisord в сеть на порту 9001. Это не стандартный веб-сервис, а интерфейс управления, используемый для мониторинга и управления процессами. Возможность доступа к этому интерфейсу без аутентификации создаёт риск того, что атакующий сможет просматривать статус управляемых сервисов или взаимодействовать с ними.
Однако необходимо различать видимый интерфейс и лежащий в основе механизм управления. Кнопки REFRESH, RESTART ALL и STOP ALL не обрабатывают запросы самостоятельно во фронтенде; вместо этого они должны вызывать интерфейс/бэкенд Supervisord, чтобы получать статус или отправлять команды управления процессами. Поэтому после подтверждения того, что веб-интерфейс открыт, следующим шагом анализа является определение того, существует ли лежащий в основе интерфейс управления за веб-интерфейсом и требует ли он аутентификации.
⇒ Размышление: Необходимо проверить, существует ли интерфейс управления за веб-интерфейсом и требует ли он аутентификации.

Согласно документации 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.Проверяем, активна ли конечная точка:```
curl -i -s -X POST -H "Content-Type: text/xml"
-d 'supervisor.getState'
http://192.168.3.137:9001/RPC2

Результат возвращает `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.
Таким образом, цепочка атаки выглядит следующим образом: