17 августа 2026 года - через считанные часы после присвоения идентификатора CVE-2026-64849 - honeypot-сеть watchTowr зафиксировала массовое неизбирательное сканирование открытых MLflow-инстансов по всему интернету. CVSS 9.3, без аутентификации, полностью автоматизируемая эксплуатация. Атакующим не понадобился даже технический writeup - хватило самого факта CVE. К 19 августа CISA внесла уязвимость в каталог Known Exploited Vulnerabilities с дедлайном патчинга 2 сентября, решение SVSC - Act: активная эксплуатация, автоматизируемая, полный технический импакт. Ниже - разбор механики, kill chain с MITRE ATT&CK маппингом и detection-правила, которых на момент публикации нет ни в одном русскоязычном источнике.
Зачем атакующим MLOps: кража cloud credentials через SSRF
MLflow - open-source платформа для управления жизненным циклом ML-моделей: трекинг экспериментов, версионирование артефактов, деплой. Типичный инстанс крутится на облачной VM или в Kubernetes-кластере, и ему выданы IAM-права на чтение S3-бакетов с артефактами, доступ к Secrets Manager, подключение к training-данным в BigQuery или другом хранилище. Подробнее - в нашем руководстве по безопасность llm приложений.Компрометация credentials такого инстанса - не кража одного токена. Это доступ ко всей ML-инфраструктуре организации: обучающим данным (часто содержащим PII и коммерческую тайну), моделям (интеллектуальная собственность), облачным хранилищам и реестрам. Если атакующий получает credentials избыточно привилегированной облачной identity, один SSRF в MLflow превращается в инцидент совсем другого масштаба - с lateral movement через полоблака. Утечка training-данных с персональными данными - прямое нарушение 152-ФЗ и потенциальные оборотные штрафы. Утечка production-моделей - ущерб конкурентоспособности, который трудно оценить в деньгах, но легко ощутить на рынке.
Отдельная головная боль для SOC: MLflow живёт в «доверенной» внутренней среде. Data-science команды открывают веб-интерфейс без аутентификации «для удобства», а security-команды не включают его в периметр мониторинга - «это же dev-инструмент, не прод». В результате у SOC нет baseline для MLflow-трафика, и отличить легитимный webhook-тест от эксплуатации - задача нетривиальная. А если атакующий заходит через скомпрометированный внутренний хост, запрос придёт с доверенного IP - и задача становится ещё веселее.
Эксплуатация SSRF в облаке: механика CVE-2026-64849
Работает если:- MLflow версии ниже 3.15.0 (затронуты все версии PyPI-пакета
mlflow, подтверждено OSV.dev) - Tracking Server доступен по сети - внешний IP или внутренний без сетевой сегментации
- Webhook API не закрыт reverse proxy или сетевой политикой
- MLflow обновлён до 3.15.0+
- Исходящие соединения из MLflow ограничены whitelist-адресами (artifact store, DB)
- IMDSv2 включён в required-режиме на AWS (для этой конкретной CVE)
- Webhook test endpoint недоступен из-за whitelist-правил на reverse proxy
POST /api/2.0/mlflow/webhooks/{id}/test. Согласно advisory MLflow и подтверждению SecurityWeek, дефолтный Tracking Server экспонирует API model-registry webhooks без аутентификации. Ключевой дефект (CWE-918, Server-Side Request Forgery): функция _validate_webhook_url() в mlflow/utils/validation.py проверяет только оригинальный URL перед отправкой запроса. А вот mlflow/webhooks/delivery.py послушно следует HTTP-редиректам и переразрешает hostname без привязки к ранее валидированному адресу. Один redirect - и MLflow обращается к произвольному внутреннему ресурсу, возвращая атакующему response_status и response_body.CVSS-вектор:
AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:N. Что это значит на практике: сетевой доступ (AV:N), низкая сложность (AC:L), нулевые привилегии (PR:N), нулевое взаимодействие пользователя (UI:N). Scope Changed (S:C) - уязвимый компонент (MLflow) позволяет атаковать другой компонент (cloud metadata service), выходящий за его security boundary. Высокий урон конфиденциальности (C:H) - атакующий читает secrets.Паттерн «валидация URL на входе без ревалидации после redirect-цепочки» - не баг конкретного коммита, а системная слабость webhook-архитектуры MLflow. По документам URL проверяется. На практике - проверяется только до первого redirect.
Kill chain: от сканирования до кражи IAM токенов через SSRF
| Этап | Действие атакующего | MITRE ATT&CK |
|---|---|---|
| Initial Access | Сканирование открытых MLflow-инстансов, POST к webhook test endpoint | Exploit Public-Facing Application (T1190, Initial Access) |
| Credential Access | SSRF-redirect на metadata service, получение temporary tokens | Cloud Instance Metadata API (T1552.005, Credential Access) |
| Persistence | Использование украденных cloud credentials из внешней инфраструктуры | Cloud Accounts (T1078.004, Persistence / Privilege Escalation) |
| Discovery | Перечисление доступных облачных ресурсов с украденным токеном | Cloud Service Discovery (T1526), Cloud Infrastructure Discovery (T1580) |
| Collection | Скачивание training data, model artifacts из облачного хранилища | Data from Cloud Storage (T1530, Collection) |
Целевые metadata-эндпоинты по облачным провайдерам:
- AWS IMDS:
http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>- временные AccessKeyId, SecretAccessKey, Token IAM-роли EC2/ECS/EKS - GCP Metadata:
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token- OAuth-токен сервисного аккаунта с доступом к Cloud Storage, Vertex AI, BigQuery - Azure IMDS:
http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/- токен Managed Identity
CVE-2026-64849.yaml) и PoC-репозитории уже на GitHub. Порог входа для атакующего - нулевой.Detection уязвимостей MLOps-инфраструктуры: правила для SIEM
Источники логов и что в них искать
MLflow access log. POST-запросы к путям/webhooks/ с сегментом /test. Мониторьте source IP: внешний адрес или нестандартный внутренний сегмент - critical-алерт. Но если атакующий зашёл через скомпрометированный внутренний хост (insider threat, lateral movement), запрос придёт с легитимного IP. Поэтому критично смотреть не только на source, но и на содержимое webhook URL в теле запроса - наличие 169.254, metadata.google, metadata.azure в URL однозначно указывает на SSRF.VPC Flow Logs / сетевые логи. Исходящие соединения из MLflow-пода или VM к link-local адресам (
169.254.169.254) или metadata.google.internal. В штатном режиме MLflow не обращается к metadata-сервисам через HTTP - любое такое соединение аномально. Точка.CloudTrail (AWS) / Cloud Audit Logs (GCP) / Activity Log (Azure). Использование IAM-роли MLflow-инстанса с нехарактерного IP-адреса. Если credentials утекли, атакующий будет вызывать
sts:GetCallerIdentity, s3:ListBuckets, secretsmanager:GetSecretValue из своей инфраструктуры - не из подсети, где работает MLflow.Sigma-правило для обнаружения обращений к metadata service
YAML:
title: MLflow SSRF to Cloud Metadata Service
logsource:
category: network_connection
product: vpc_flowlogs
detection:
selection:
dst_ip:
- '169.254.169.254'
- 'fd00:ec2::254'
src_process|contains:
- 'mlflow'
- 'gunicorn'
filter_baseline:
# Исключите штатные SDK-обращения (boto3/google-cloud) - настройте под ваш baseline
event_count|gte: 3
condition: selection and not filter_baseline
level: critical
Дополнительные корреляции
WAF / reverse proxy: блокировка POST-запросов к/api/2.0/mlflow/webhooks/*/test от IP вне trusted-списка. Если тестовый эндпоинт нужен data science-команде - CIDR-whitelist их подсети, всё остальное - deny.CloudTrail корреляция: событие
AssumeRole с ролью MLflow-инстанса, где source IP не принадлежит VPC MLflow. Дополнительный алерт: вызовы iam:ListRoles, s3:ListBuckets, secretsmanager:ListSecrets от этой роли из нетипичных AWS-регионов.Baseline-аномалия: если в вашем SIEM есть baseline исходящих соединений MLflow - отклонение по destination IP/port однозначно указывает на эксплуатацию или misconfiguration. Если baseline нет - создайте его прямо сейчас. Серьёзно, прямо сейчас. Это первый шаг к detection, и без него всё остальное - декорация.
IOC для ретроспективного поиска
- POST к
/api/2.0/mlflow/webhooks/{id}/testс URL, содержащим169.254,metadata.google,metadata.azure - Webhook-объекты в MLflow с URL, ведущими на нестандартные домены или IP вне корпоративного диапазона
- В CloudTrail:
eventSource: sts.amazonaws.com,eventName: GetCallerIdentityот IP вне корпоративных диапазонов, где principal - роль MLflow - Нетипичные
s3:GetObjectзапросы к бакетам с model artifacts от IP, отличных от MLflow-инстанса
Incident response при атаках на ML-пайплайны
Если MLflow версии ниже 3.15.0 был доступен из интернета - запускайте playbook вне зависимости от наличия явных следов эксплуатации. watchTowr и RU-источники подтверждают: атакующие могли отработать до включения подробного логирования. Отсутствие следов ≠ отсутствие компрометации.Шаг 1. Изоляция (0–30 минут). Закройте внешний доступ через security group, network policy или firewall rule. Не останавливайте сервис - access-логи нужны для расследования.
Шаг 2. Аудит логов (30 мин - 2 часа). Access-логи MLflow: POST к
/webhooks/*/test. VPC Flow Logs: исходящие к 169.254.169.254. CloudTrail: нестандартное использование IAM-роли MLflow.Шаг 3. Ротация credentials (параллельно с шагом 2). Перевыпустите все credentials, к которым имел доступ MLflow: IAM-роли AWS, сервисные аккаунты GCP, Managed Identity Azure. Ротация обязательна даже без явных следов компрометации - временные токены могли быть похищены и использованы до начала расследования.
Шаг 4. Анализ lateral movement (2–8 часов). С украденными credentials атакующий мог добраться до S3-бакетов (T1530, Data from Cloud Storage), Secrets Manager, Kubernetes API, других облачных сервисов. В CloudTrail ищите API-вызовы от роли MLflow из нехарактерных IP-адресов и регионов.
Шаг 5. Патч и hardening. Обновление MLflow до 3.15.0, выполнение рекомендаций из раздела ниже.
Защита MLflow сервера: hardening против SSRF атак на облачные платформы
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
или поставьте reverse proxy с обязательной аутентификацией перед MLflow. Для GCP: Workload Identity на GKE вместо node-level service account. Для Azure: Azure AD Workload Identity вместо VM-level Managed Identity - сужает scope credentials до конкретного пода.
Ограничение: аутентификация на MLflow не закрывает вектор, если атакующий уже внутри сети - скомпрометированный хост или insider. В этом случае сетевая сегментация и мониторинг egress остаются единственной линией обороны.
MLOps-инфраструктура - слепая зона большинства SOC. ML-платформы не входят в стандартный asset inventory, не покрываются типовыми SIEM-правилами, не проходят регулярный пентест. CVE-2026-64849 - очередной обход SSRF-защиты в webhook-flow MLflow. Не единичный баг, а архитектурный паттерн: валидация URL на входе без ревалидации после redirect-цепочки. Но корень глубже конкретного CVE - IAM-роль MLflow-инстанса часто имеет permissions, которые data scientist запросил два года назад, и которые никто с тех пор не ревьюил. Один SSRF - и весь этот scope у атакующего.
Пока ML-команды живут в парадигме «trusted internal network», а SOC не мониторит ML-платформы как production-актив, каждый следующий CVE в MLflow, Kubeflow или Ray будет давать тот же результат. Nuclei-шаблон опубликован, PoC на GitHub, EPSS в Top 10% - окно для проактивной защиты сужается быстрее, чем для реактивного патчинга. Проверьте свой MLflow-инстанс прямо сейчас:
nmap -p 5000 <your-mlflow-host> - если порт торчит наружу без аутентификации, у вас та же проблема. Тематический тред с playbook'ом по detection в MLOps-инфраструктуре и адаптации Sigma-правил под разные SIEM ведётся на codeby.net.