Aller au contenu

CVE-2026-64849 : falsification de requête côté serveur (SSRF) critique dans les notifications webhook de MLflow

HERMES

SCORE DE MENACE HERMES & EXPOSITION DE L'INFRASTRUCTURE CLOUD MLOPS

Cible : MLflow (Plateforme de cycle de vie Machine Learning)
Confiance : 99%
94 / 100
CRITIQUE

Mesure la pertinence opérationnelle réelle, la militarisation de l'exploit et la posture de menace active.

Décomposition des dimensions
Exploitabilité 20 / 20
Activité de menace 18 / 20
Militarisation 19 / 20
Exposition 19 / 20
Prévalence 19 / 20
Impact 19 / 20
Maturité de l'exploit 20 / 20
Potentiel d'attaque en chaîne 20 / 20
⚖️ Divergence & Justification opérationnelle

Le CVSS v3.1 attribue à la CVE-2026-64849 la note de 9.3 (Critique) et le CVSS v4.0 affiche 9.3. Le score de menace Hermes s'établit à 94 (CRITIQUE). La corrélation est directe : les serveurs MLflow s'exécutent fréquemment dans des espaces de noms Kubernetes privilégiés ou sur des machines virtuelles cloud disposant de rôles IAM pour accéder aux compartiments S3/GCS hébergeant modèles et données d'entraînement. L'exploitation de la SSRF permet d'extraire les jetons de métadonnées d'instance et de compromettre le locataire cloud.

🕸️ Graphe de connaissances connecté & Provenance

CVE-2026-64849: Critical Server-Side Request Forgery (SSRF) in MLflow Webhook NotificationsVULNÉRABILITÉ

Nœuds connectés : 2
Relations sortantes actives
→ affectsCOMPOSANTCPython Interpreter & Standard Library
98% VERY_HIGH

Software platform affected by security vulnerabilities and agentic attack patterns.

🔍 Pourquoi cette relation ? (Preuves & Provenance)

“Confirmed security vulnerability in CPython Interpreter & Standard Library documented in Hermes dossier.”

Preuves vérifiées associées :
→ usesTECHNIQUE D'ATTAQUET1552: Unsecured Credentials
90% VERY_HIGH

Adversaries search compromise victims for unsecured credentials in files, environment variables, or memory.

🔍 Pourquoi cette relation ? (Preuves & Provenance)

“Attack execution telemetry aligns with MITRE ATT&CK technique T1552.”

Preuves vérifiées associées :

1. Contexte technique & matrice des logiciels affectés

Section intitulée « 1. Contexte technique & matrice des logiciels affectés »

MLflow centralise le suivi des expériences d’apprentissage automatique, le packaging de code, le registre de versions de modèles et les déploiements en production.

ParamètreSpécification TechniqueContexte de Menace
Identifiant CVECVE-2026-64849Identifiant de vulnérabilité international
Composant vulnérablemlflow.server.handlers (Gestionnaire de Webhooks)Moteur de notification d’événements du registre de modèles
Vecteur réseauHTTP/HTTPS (Port par défaut TCP 5000)Serveurs de suivi MLflow publics ou internes au VPC
Cause racineDestination d’URL non restreinte dans le client HTTP (CWE-918)SSRF ciblant les API de métadonnées cloud
Versions affectéesMLflow < 3.15.0Serveurs de suivi cloud et sur site
Versions corrigées3.15.0Version officielle imposant une liste de blocage d’IP
Impact d’exploitationVol des identifiants IAM, rebond dans la grappe KubernetesPrise de contrôle de l’environnement cloud

2. Décomposition technique : mécanisme de la faille SSRF de webhook

Section intitulée « 2. Décomposition technique : mécanisme de la faille SSRF de webhook »

MLflow permet aux utilisateurs de créer des webhooks pour notifier des systèmes externes (Slack, PagerDuty, coureurs CI/CD) des évolutions de modèles :

# Gestionnaire vulnérable dans mlflow/server/handlers.py
def _create_webhook(request_data):
url = request_data.get("url")
# ANOMALIE : Aucun contrôle d'adresse de boucle locale ou d'IP de métadonnées
webhook = WebhookModel(url=url, events=request_data.get("events"))
return webhook_store.save(webhook)
def _dispatch_webhook_notification(webhook, payload):
# Requête sortante directe initiée depuis le serveur MLflow
response = requests.post(webhook.url, json=payload, timeout=5)
return response.text
+----------------------------------------------------------------------------------------------------+
| DIAGRAMME DE SÉQUENCE DE L'ATTAQUE CVE-2026-64849 |
+----------------------------------------------------------------------------------------------------+
[Attaquant Distant]
│
│ [1] HTTP POST /ajax-api/2.0/mlflow/webhooks/create
│ Charge : { "url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/",
│ "events": ["MODEL_VERSION_CREATED"] }
▼
[Serveur de Suivi MLflow (Port 5000 / Instance AWS EC2 ou EKS)]
│
├───► 1. Enregistrement du Webhook :
│ - Accepte l'URL cible sans validation DNS ni filtrage d'IP privées
│
│ [2] L'attaquant déclenche : POST /ajax-api/2.0/mlflow/model-versions/create
▼
[Moteur de Déclenchement de Webhook MLflow]
│
├───► 3. Requête SSRF Interne :
│ - Émet un appel HTTP GET/POST vers http://169.254.169.254/latest/meta-data/
│ - Le service IMDS AWS répond depuis le contexte de l'instance
│ - MLflow capture les jetons d'accès IAM temporaires :
│ AccessKeyId, SecretAccessKey, Token
│
▼
[Exfiltration des Identifiants via les Journaux d'Événements]
│
└───► L'attaquant lit le jeton répercuté dans les traces de notification :
- Configure l'AWS CLI avec les identifiants IAM dérobés
- Accède aux compartiments S3 hébergeant les poids et données de modèles
- Élève ses privilèges sur l'ensemble du compte cloud AWS
+----------------------------------------------------------------------------------------------------+

3. Renseignement sur les menaces & exploitation dans la nature

Section intitulée « 3. Renseignement sur les menaces & exploitation dans la nature »
  • Ciblage des infrastructures MLOps : des scanners automatisés recherchent les serveurs MLflow sur le port 5000 hébergés sur des plages d’adresses d’opérateurs cloud.
  • Vulnérabilité IMDSv1 : les environnements où AWS IMDSv2 n’est pas rendu obligatoire permettent l’extraction directe des clés IAM sans jeton de session préalable.
  • Pivot réseau au sein de Kubernetes : lorsque MLflow tourne dans une grappe Kubernetes, les attaquants ciblent https://kubernetes.default.svc pour interroger l’API avec le jeton de compte de service du pod situé dans /var/run/secrets/kubernetes.io/serviceaccount/token.

TactiqueID TechniqueNom de la TechniqueManifestation dans l’Attaque
Accès initialT1190Exploitation d’application publiqueRequête HTTP POST enregistrant un webhook malveillant
Accès aux identifiantsT1552.005API de métadonnées d’instance cloudInterrogation de 169.254.169.254 pour récupérer les clés IAM
DécouverteT1046Découverte de services réseauBalayage des ports de services internes via la SSRF
Déplacement latéralT1021Services distantsUtilisation des jetons IAM pour accéder à l’infrastructure cloud

alert http any any -> $MLFLOW_SERVERS 5000 (
msg:"HERMES DEFENSE - Tentative de SSRF Metadonnees Webhook MLflow (CVE-2026-64849)";
flow:established,to_server;
http.method; content:"POST";
http.uri; content:"/webhooks/create";
http.request_body; pcre:"/(\"url\"\s*:\s*\"https?:\/\/(169\.254\.169\.254|metadata\.google\.internal|127\.0\.0\.1|localhost))/i";
classtype:web-application-attack;
sid:202664849;
rev:1;
reference:cve,2026-64849;
)
title: Connexion du processus MLflow vers l'IP de métadonnées cloud
id: 8c7b6a5d-4e3f-2a1b-0c9d-64849c026e02
status: high
description: Détecte les flux réseau sortants initiés par le processus serveur MLflow vers les adresses de métadonnées cloud.
author: Hermes Codex Detection Engineering
date: 2026-09-11
logsource:
product: linux
category: network_connection
detection:
selection_process:
Image|contains: 'python'
CommandLine|contains: 'mlflow'
selection_destination:
DestinationIp:
- '169.254.169.254'
- '127.0.0.1'
condition: selection_process and selection_destination
falsepositives:
- Appels légitimes d'authentification initiale par le SDK cloud officiel (doivent employer IMDSv2).
level: critical
tags:
- attack.initial_access
- attack.t1190
- attack.credential_access
- attack.t1552.005

6. Réponse à incident & rétro-ingénierie (DFIR)

Section intitulée « 6. Réponse à incident & rétro-ingénierie (DFIR) »
  1. Interrogation de la base de données des webhooks MLflow :
    SELECT id, url, events, created_time FROM webhooks;
    -- Identifier toute URL ciblant 169.254, localhost ou des plages IP internes
  2. Revue des journaux CloudTrail / GCP audit :
    • Filtrer les appels GetRole ou AssumeRole provenant de l’IP du serveur MLflow.
  3. Analyse des flux réseau sortants :
    • Vérifier dans les VPC Flow Logs les connexions vers 169.254.169.254:80.
{
"query": {
"bool": {
"must": [
{ "term": { "url.path": "/ajax-api/2.0/mlflow/webhooks/create" } },
{ "wildcard": { "http.request.body.content": "*169.254.169.254*" } }
]
}
}
}

  1. Mise à niveau de MLflow : mettre à jour vers la version 3.15.0 ou ultérieure.
  2. Activation obligatoire d’IMDSv2 sur AWS : exiger les jetons de session et restreindre la limite de sauts réseau (hop limit) à 1 pour empêcher les requêtes depuis les conteneurs :
    Fenêtre de terminal
    aws ec2 modify-instance-metadata-options \
    --instance-id i-0123456789abcdef0 \
    --http-tokens required \
    --http-put-response-hop-limit 1
  3. Filtrage réseau sortant : appliquer des règles Kubernetes NetworkPolicies interdisant tout accès des pods MLflow à 169.254.169.254/32.
  4. Renouvellement des identifiants IAM : révoquer et renouveler immédiatement les clés de rôles IAM associées à l’instance MLflow.