Nel kernel Linux è stata identificata una vulnerabilità (CVE-2021-3609) che consente a un utente locale di elevare i propri privilegi nel sistema. Il problema è causato da una condizione di gara nell'implementazione del protocollo CAN BCM e si manifesta nelle versioni del kernel Linux da 2.6.25 a 5.13-rc6. Nei vari distribuzioni, la problematica rimane irrisolta (RHEL, Fedora, Debian, Ubuntu, SUSE, Arch).
Il ricercatore che ha scoperto la vulnerabilità è riuscito a preparare un exploit per ottenere i diritti di root sui sistemi con kernel Linux 5.4 e versioni successive, dimostrando anche la possibilità di un attacco riuscito su Ubuntu 20.04.02 LTS. Non si esclude la possibilità di adattare l'exploit per lavorare anche con versioni più vecchie del kernel (nel kernel 5.4, il codice CAN BCM (net/can/bcm.c) è stato convertito da hrtimer_tasklet a HRTIMER_MODE_SOFT).
Il protocollo CAN BCM consente di registrare un proprio gestore di messaggi in arrivo tramite il bus CAN (controller area network) e di associarlo a un socket di rete specifico. Quando arriva un messaggio in ingresso, viene chiamata la funzione bcm_rx_handler(). L'attaccante può sfruttare la condizione di gara per chiudere il socket di rete contemporaneamente all'esecuzione di bcm_rx_handler(). Quando il socket viene chiuso, viene chiamata la funzione bcm_release(), che libera la memoria allocata per le strutture bcm_op e bcm_sock, che continuano però a essere utilizzate nel gestore bcm_rx_handler() ancora in esecuzione. Si verifica quindi una situazione che porta a un accesso a un blocco di memoria già liberato (use-after-free).
L'attacco consiste nell'aprire due socket CAN BCM e collegarli all'interfaccia vcan. Nel primo socket viene effettuata una chiamata sendmsg() con il flag RX_SETUP per configurare il gestore dei messaggi CAN in arrivo, mentre nel secondo socket viene effettuata una chiamata sendmsg() per inviare un messaggio al primo socket. Dopo la ricezione del messaggio, viene attivata la chiamata bcm_rx_handler(), e l'attaccante individua il momento opportuno per chiudere il primo socket, il che porta all'attivazione di bcm_release() e alla liberazione delle strutture bcm_op e bcm_sock, sebbene il lavoro di bcm_rx_handler() non sia ancora terminato.
Attraverso manipolazioni del contenuto di bcm_sock, l'attaccante può sovrascrivere il puntatore alla funzione sk->sk_data_ready(sk), reindirizzare l'esecuzione e, utilizzando tecniche di Return-Oriented Programming (ROP), ottenere la sovrascrittura del parametro modprobe_path e forzare l'esecuzione del proprio codice con privilegi di root. Utilizzando la tecnica ROP, l'attaccante non cerca di posizionare il proprio codice in memoria, ma si occupa di frammenti di istruzioni machine già esistenti nelle librerie caricate, che terminano con un'istruzione di ritorno (di solito, si tratta delle conclusioni delle funzioni di libreria). Il funzionamento dell'exploit consiste nel creare una catena di chiamate di tali blocchi (“gadget”) per ottenere la funzionalità desiderata.

Per l'attacco è necessario avere accesso per creare socket CAN e un'interfaccia di rete vcan configurata. I diritti necessari per effettuare l'attacco possono essere ottenuti da un utente non privilegiato in contenitori creati in sistemi con il supporto attivato per gli spazi dei nomi degli identificatori utente (user namespaces). Ad esempio, gli user namespaces sono abilitati per impostazione predefinita in Ubuntu e Fedora, ma non sono attivati in Debian e RHEL.
Fonte: opennet.ru
