Exploit de preuve de concept pour CVE-2025-67644, une vulnérabilité d'injection SQL dans LangGraph SQLite Checkpoint. Démontre une injection SQL arbitraire via des clés de filtre de métadonnées non assainies, permettant l'exfiltration de données et le contournement de filtres.
CVE-2025-67644 est une vulnérabilité d'injection SQL (CWE-89) dans le paquet langgraph-checkpoint-sqlite (faisant partie de l'écosystème LangGraph / LangChain).
Elle permet à un attaquant d'injecter du SQL arbitraire via des clés de filtre de métadonnées non assainies transmises aux méthodes list() / alist() de SqliteSaver.
Impact : Contournement complet des filtres, fuite de tous les enregistrements de checkpoints (y compris l'état de conversation potentiellement sensible, les identifiants de threads, les métadonnées), et dans certains scénarios de déploiement — un accès plus large à la base de données.
Versions affectées : < 3.0.1
Corrigé dans : ≥ 3.0.1
Score CVSS : 7.3 (Élevé) — AV:L / AC:L / PR:L / UI:N / S:C / C:H / I:L / A:N
La logique interne _metadata_predicate() utilisait une interpolation f-string non sécurisée de clés de dictionnaire contrôlées par l'utilisateur dans une expression d'extraction JSON :
f"json_extract(CAST(metadata AS TEXT), '$.{query_key}')"
Un attaquant capable de fournir des clés arbitraires (par exemple via une entrée API) peut fermer prématurément le chemin JSON et injecter des fragments SQL, tels que :
{"env') OR '1'='1": "anything"}
→ ce qui produit une clause WHERE toujours évaluée à vrai → renvoie tous les enregistrements.
flowchart TD
A["Utilisateur / Client API"] -->|"Envoie un dictionnaire de filtre malveillant"| B["Application utilisant langgraph-checkpoint-sqlite"]
B -->|"Transmet filter=..."| C["Méthode SqliteSaver.list"]
C -->|"Interpolation non sécurisée de clés"| D["Logique de prédicat de métadonnées"]
D -->|"Construit du SQL injectable"| E["Moteur SQLite"]
E -->|"Renvoie TOUS les checkpoints / données sensibles"| F[Attaquant]
F -->|"Exfiltration de données / contournement d'autorisation"| G["Impact obtenu"]
(Cette version évite les parenthèses dans le texte des nœuds lorsque c'est possible et utilise des guillemets autour des libellés contenant des caractères spéciaux/points pour éviter les erreurs d'analyse.)
--dump-all (afficher tous les enregistrements), --threads-only (extraire uniquement les thread_ids)pip install langgraph-checkpoint-sqlite"<3.0.1" # e.g. ==2.0.0
# Basic check (count only)
python3 exploit.py checkpoints.db
# Dump full checkpoint details
python3 exploit.py checkpoints.db --dump-all
# Extract thread_ids only (useful for enumeration)
python3 exploit.py checkpoints.db --threads-only --dump-all
# Test against in-memory database (quick & volatile)
python3 exploit.py ":memory:" --dump-all
Installez la version vulnérable :
pip install langgraph-checkpoint-sqlite==2.0.0
Enregistrez le code de l'exploit sous le nom exploit.py
Exécutez-le contre une base de données de checkpoints existante ou nouvelle :
python3 exploit.py checkpoints.db --dump-all
Mettez à jour immédiatement :
pip install --upgrade langgraph-checkpoint-sqlite
(version ≥ 3.0.1)
N'acceptez pas de clés de filtre de métadonnées arbitraires provenant de sources non fiables (utilisateurs, API, payloads JSON, etc.)
Dans ≥ 3.0.1, la bibliothèque impose une regex stricte sur les clés : ^[a-zA-Z0-9_.-]+$
Ceci est une preuve de concept publiée à des fins uniquement éducatives et de recherche en sécurité.
N'utilisez pas ce code contre des systèmes de production ou toute cible sans autorisation écrite explicite.
L'auteur n'est pas responsable de l'utilisation abusive ou des dommages causés par ce code.
Divulgation responsable et recherche uniquement.
Mohammed Idrees Banyamer
@banyamer_security