Разбор машины Kobold из 10-го сезона HackTheBox. Это easy-машина с интересной цепочкой уязвимостей: chaining через Docker volumes, reuse учётных данных и два пути до root. Главная изюминка — точка входа через RCE в инструменте из экосистемы ИИ. Спойлер: уязвимость в MCP-тулзе. Новый attack surface, который важно учитывать при пентестах.
Сканирование портов
Начинаем с полного сканирования портов с помощью Nmap. Обнаружено четыре открытых TCP-порта:
- OpenSSH 9.6p1 Ubuntu — свежая версия, без известных CVE.
- nginx 1.24.0 — редирект на https://kobold.htb.
- nginx 1.24.0 (SSL) — на порту 443, с заголовком «Kobold Operations Suite».
- Порт 3552 — не распознан Nmap, но содержит HTTP-сервис.
SSH недоступен без учётных данных, порт 80 редиректит на HTTPS. Основные цели — порты 443 и 3552.
Ключевая находка: SSL-сертификат на 443 порту содержит wildcard *.kobold.htb в Subject Alternative Name. Это сигнал: нужно искать сабдомены.
Исследование веб-приложений
Открываем https://kobold.htb — статичный лендинг без интерактива. Тупик.
Порт 3552: при попытке доступа по HTTPS — ошибка wrong version number. Сервис работает по HTTP. Открываем http://kobold.htb:3552.
Перед нами — Arcane v1.13.0, панель управления Docker. Форма входа с полями Username/Password. Внизу — ссылка на GitHub и версия. Без логина не пройти. Запоминаем.
Поиск сабдоменов
Wildcard в сертификате указывает на наличие сабдоменов. Используем ffuf для vhost-энумерации.
Находим один сабдомен: mcp.kobold.htb. Добавляем его в /etc/hosts.
MCPJam Inspector — точка входа
Открываем https://mcp.kobold.htb.
Перед нами — MCPJam Inspector v1.4.2, платформа для разработки MCP-серверов. Полный доступ без аутентификации: Servers, Chat, App Builder, Tools, Settings. В настройках видим подключённый Ollama и версию v1.4.2.
Model Context Protocol (MCP) — стандарт для интеграции ИИ-моделей с внешними инструментами. Такие dev-тулзы всё чаще попадают в production без защиты.
Получение доступа (Foothold)
Уязвимость: GHSA-232v-j27c-5pp6
MCPJam Inspector ≤1.4.2 уязвим к RCE. Причины:
- Слушает на 0.0.0.0 вместо 127.0.0.1 — API доступен извне.
- Эндпоинт /api/mcp/connect принимает serverConfig.command — произвольную команду без аутентификации и валидации.
Это задокументированный функционал, который в публичном доступе превращается в RCE за один запрос.
Эксплуатация
Запускаем listener на атакующей машине.
Отправляем payload, который выполняет reverse shell.
Получаем соединение как пользователь ben. Стабилизируем shell: теперь работают стрелки, автодополнение и интерактивные команды.
Разведка изнутри
Пользователи и группы
Пользователь alice — в группе docker, ben — нет. Зато ben состоит в группе operator. Нужно найти путь к Docker-привилегиям.
Внутренние сервисы
На порту 8080 — сервис, доступный только локально. Это Docker-контейнер с PrivateBin.
Проверяем nginx-конфиг — обнаруживаем сабдомен bin.kobold.htb, проксирующий запросы в контейнер. Добавляем в /etc/hosts.
Группа operator имеет read/write-доступ к /privatebin-data/ — это Docker volume, общий между хостом и контейнером. Мы можем писать файлы, которые будут доступны внутри контейнера.
PrivateBin LFI → Утечка учётных данных
Уязвимость: CVE-2025-64714 (GHSA-g2j9-g8r5-rg82)
PrivateBin 2.0.2 уязвим к LFI через cookie template. При включённой опции template_selection = true можно выполнить path traversal и загрузить произвольный PHP-файл из директории tpl/.
Сама по себе LFI в контейнере ограничена его файловой системой. Но у нас есть доступ к общему volume — это позволяет построить цепочку атаки.
Эксплуатация
Шаг 1: с хоста (как ben) размещаем PHP-вебшелл в /privatebin-data/data/shell.php.
Шаг 2: через браузер устанавливаем cookie: template=../../../../data/shell. Сервер загружает наш файл.
Шаг 3: выполняем команды в контейнере. Считываем конфиг PrivateBin — находим учётные данные MySQL.
В комментарии указано: база временно отключена из-за миграции. Но пароль, скорее всего, переиспользуется.
Привилегии: основной путь
Reused-пароль → Arcane Dashboard
Найденный пароль пробуем на всех сервисах. su alice и SSH не работают. Проверяем Arcane Dashboard на http://kobold.htb:3552.
Логин неизвестен. Ищем дефолтные учётные данные Arcane: в документации указано — arcane/arcane-admin. Пароль сменили, но логин остался.
Пробуем:
- Username: arcane
- Password: <LEAKED_PASSWORD>
Успешный вход. Теперь у нас полный доступ к Docker через веб-интерфейс.
Урок: при reuse паролей всегда проверяйте дефолтные логины из документации. Их часто не меняют.
Создание привилегированного контейнера
В Arcane создаём новый контейнер:
- Имя: pwned
- Образ: privatebin/nginx-fpm-alpine:2.0.2
- Volume: / → /hostfs
- Privileged mode: включён
Запускаем контейнер, открываем shell. Получаем доступ к файловой системе хоста. Читаем root-флаг.
Альтернативный путь: newgrp docker
Есть более быстрый способ — за три команды, без UI и поиска паролей.
При исследовании системы обнаруживаем, что в /etc/gshadow пользователь ben состоит в группе docker, хотя /etc/group этого не показывает.
Команда newgrp читает членство в группах из /etc/gshadow. Если запись есть — можно переключиться без пароля.
Выполняем:
newgrp docker
Теперь у нас доступ к Docker. Запускаем контейнер с монтированием корня хоста:
docker run --rm -u 0 -v /:/hostfs --entrypoint /bin/sh <image> -c "cat /hostfs/root/root.txt"
Получаем root-флаг. Быстро, но менее показательно с точки зрения обучения.
Нюансы:
- --entrypoint /bin/sh — чтобы перехватить stdin.
- -u 0 — запуск от root в контейнере.
- --rm — автоматическое удаление после завершения.
Выводы
MCP-инструменты — новый attack surface
MCPJam Inspector — не исключение. Многие MCP-сервисы по умолчанию слушают на 0.0.0.0 без аутентификации. База vulnerablemcp.info уже содержит десятки подобных уязвимостей. AppSec-инженерам нужно включать аудит MCP-конфигураций в security review.
Docker group = root
Членство в группе docker эквивалентно root. Достаточно одной команды docker run -v /:/hostfs, чтобы получить полный контроль. Это должен быть обязательный пункт при аудите Linux-систем.
LFI в контейнере ≠ тупик
Даже изолированная LFI может стать вектором атаки, если есть общий volume с правами на запись. Цепочка: размещение файла → триггер LFI → утечка конфига → reuse пароля.
Reused-пароли и дефолтные логины
Нашли пароль — пробуйте его везде. И не ограничивайтесь логинами из конфигов. Ищите дефолтные учётные данные в документации. Например, arcane для Arcane Dashboard — часто остаётся без изменений.