
Exploit di escalation dei privilegi su Linux tramite snapd (CVE-2019-7304)
A gennaio 2019, è stato scoperto che le versioni correnti di Ubuntu Linux erano vulnerabili a un'escalation locale dei privilegi a causa di un bug nell'API di snapd. Questo repository contiene il POC originale dell'exploit, reso disponibile per scopi di ricerca e didattici. Per una descrizione dettagliata della vulnerabilità e dell'exploit, consulta il post sul blog qui.
Ubuntu viene fornito con snapd per impostazione predefinita, ma qualsiasi distribuzione dovrebbe essere sfruttabile se ha questo pacchetto installato. Puoi facilmente verificare se il tuo sistema è vulnerabile. Esegui il comando qui sotto. Se il tuo snapd è 2.37.1 o più recente, sei al sicuro.
$ snap version
...
snapd 2.37.1
...
Nota: alcuni sistemi restituiscono la versione del pacchetto di distribuzione di snapd quando esegui questo comando, diversamente dalla versione upstream mostrata nell'esempio sopra. Se la versione del tuo snapd ha un riferimento a qualcosa come un numero di versione di Ubuntu aggiunto (esempio: 2.34.2ubuntu0.1 o 2.35.5+18.10.1), consulta questo link per determinare se stai eseguendo una versione patchata.
Questo exploit bypassa i controlli di accesso per utilizzare una funzione API ristretta (POST /v2/create-user) del servizio snapd locale. Questo interroga l'Ubuntu SSO per ottenere un nome utente e una chiave SSH pubblica di un indirizzo email fornito, e poi crea un utente locale basato su questi valori.
Lo sfruttamento riuscito di questa versione richiede una connessione Internet in uscita e un servizio SSH accessibile tramite localhost.
Per sfruttare, crea prima un account su Ubuntu SSO. Dopo averlo confermato, modifica il tuo profilo e carica una chiave pubblica SSH. Quindi, esegui l'exploit in questo modo (con la chiave privata SSH corrispondente alla chiave pubblica che hai caricato):
python3 ./dirty_sockv1.py -u "[email protected]" -k "id_rsa"
[+] Slipped dirty sock on random socket file: /tmp/ktgolhtvdk;uid=0;
[+] Binding to socket file...
[+] Connecting to snapd API...
[+] Sending payload...
[+] Success! Enjoy your new account with sudo rights!
[Script will automatically ssh to localhost with the SSH key here]
Questo exploit bypassa i controlli di accesso per utilizzare una funzione API ristretta (POST /v2/snaps) del servizio snapd locale. Ciò consente l'installazione di snap arbitrari. Gli snap in modalità 'devmode' bypassano il sandbox e possono includere un 'install hook' che viene eseguito nel contesto di root al momento dell'installazione.
dirty_sockv2 sfrutta la vulnerabilità per installare uno snap vuoto in modalità 'devmode' che include un hook che aggiunge un nuovo utente al sistema locale. Questo utente avrà i permessi per eseguire comandi sudo.
A differenza della versione uno, questa non richiede che il servizio SSH sia in esecuzione. Funzionerà anche su versioni più recenti di Ubuntu senza alcuna connessione Internet, rendendola resiliente ai cambiamenti ed efficace in ambienti ristretti.
Nota per chiarezza: questa versione dell'exploit non si nasconde all'interno di uno snap dannoso. Invece, utilizza uno snap dannoso come meccanismo di distribuzione per il payload di creazione dell'utente. Ciò è possibile grazie allo stesso bug uid=0 della versione 1
Questo exploit dovrebbe essere efficace anche su sistemi non Ubuntu che hanno installato snapd ma che non supportano l'API 'create-user' a causa di una sintassi shell Linux incompatibile.
Alcuni sistemi Ubuntu più vecchi (come 16.04) potrebbero non avere i componenti snapd necessari per il sideloading. In tal caso, questa versione dell'exploit potrebbe innescare l'installazione di quelle dipendenze. Durante tale installazione, snapd potrebbe aggiornarsi a una versione non vulnerabile. I test mostrano che l'exploit ha ancora successo in questo scenario. Vedi la sezione di risoluzione dei problemi per maggiori dettagli.
Per sfruttare, basta eseguire lo script senza argomenti su un sistema vulnerabile.
python3 ./dirty_sockv2.py
[+] Slipped dirty sock on random socket file: /tmp/gytwczalgx;uid=0;
[+] Binding to socket file...
[+] Connecting to snapd API...
[+] Deleting trojan snap (and sleeping 5 seconds)...
[+] Installing the trojan snap (and sleeping 8 seconds)...
[+] Deleting trojan snap (and sleeping 5 seconds)...
********************
Success! You can now `su` to the following account and use sudo:
username: dirty_sock
password: dirty_sock
********************
Se stai usando la versione due e l'exploit viene completato ma non vedi il tuo nuovo account, potrebbe essere dovuto ad alcuni aggiornamenti snap in background. Puoi visualizzarli eseguendo snap changes e poi snap change #, facendo riferimento alla riga che mostra l'installazione dello snap dirty_sock. Alla fine, questi dovrebbero completarsi e il tuo account dovrebbe essere utilizzabile.
La versione 1 sembra essere la più semplice e veloce, se il tuo ambiente la supporta (servizio SSH in esecuzione e accessibile da localhost).
I sistemi non vulnerabili produrranno un output simile al seguente:
[!] System may not be vulnerable, here is the API reply:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
Date: Mon, 18 Feb 2019 07:07:12 GMT
Content-Length: 119
{"type":"error","status-code":401,"status":"Unauthorized",
"result":{"message":"access denied","kind":"login-required"}}
Per favore apri issue per qualsiasi cosa strana.
Il problema è stato segnalato direttamente al team di snapd tramite il bug tracker di Ubuntu. Puoi leggere l'intera discussione qui.
Sono rimasto molto colpito dalla risposta di Canonical a questo problema. Il team è stato fantastico con cui lavorare, e l'esperienza complessiva mi fa sentire molto bene nell'essere un utente Ubuntu io stesso.
Link di advisory pubblici:
Nota: sto pubblicando informazioni solo su questo repository GitHub, il mio blog su initblog.com e il blog del mio team su shenaniganslabs.io. Qualsiasi sito che si spaccia per fonte ufficiale è purtroppo al di là del mio controllo.