Exploit chain root di OpenBSD corretta nelle patch di settembre
L’exploit root di OpenBSD dimostrato dalla società di sicurezza Calif può consentire a un utente locale di ottenere root, il massimo livello di controllo amministrativo del sistema operativo, su OpenBSD 7.9. Il proof-of-concept concatena una integer overflow nella shared memory con un’altra vulnerabilità nel kernel, il nucleo del sistema operativo. Insieme, le vulnerabilità aggirano la randomizzazione degli indirizzi del kernel di OpenBSD e le protezioni del processore SMAP and SMEP, progettate per impedire al kernel di accedere impropriamente alla memoria controllata dall’utente o di eseguire codice al suo interno.
OpenBSD ha risolto i due problemi sottostanti con aggiornamenti separati pubblicati a settembre. Errata 018, rilasciato il 14 settembre, ha corretto la integer overflow nella funzione shmat(4), utilizzata per collegare la shared memory e consentire ai processi di accedere alla stessa area di memoria. OpenBSD ha classificato questo aggiornamento come correzione di affidabilità anziché come correzione di sicurezza. Errata 026 è seguito il 30 settembre e ha corretto la use-after-free legata al conteggio dei riferimenti, una condizione in cui il kernel continua a utilizzare la memoria dopo che questa è stata rilasciata. Tale aggiornamento è stato classificato come correzione di sicurezza.
Entrambe le correzioni sono disponibili tramite syspatch, l’utilità di patch di OpenBSD, e si applicano a tutte le architetture hardware supportate. Anche OpenBSD 7.8 ha ricevuto la correzione della integer overflow. Al momento della pubblicazione non era stato assegnato alcun identificatore CVE a nessuna delle due vulnerabilità e non vi erano prove che fossero state sfruttate da attaccanti. Calif ha dichiarato di aver segnalato le vulnerabilità a OpenBSD all’inizio di quest’anno e di aver poi pubblicato su GitHub un’analisi tecnica dettagliata e il codice proof-of-concept completo, dopo che le patch erano diventate disponibili.
La prima fase prende di mira shm_nattch, il contatore che registra quanti processi hanno collegato un segmento di shared memory. È memorizzato come short integer con segno a 16 bit, con un valore massimo di 32.767. Calif ha ricondotto questa scelta progettuale al codice sorgente BSD originale del 1988; OpenBSD ha ereditato il tipo senza aumentarne le dimensioni. L’exploit collega 127 segmenti di shared memory e crea 259 processi, spingendo il contatore oltre il suo limite e facendolo ripartire da un valore negativo pari a -32.643.
Una race condition, nella quale il risultato dipende dalla tempistica di operazioni simultanee, trasforma quindi il contatore danneggiato in una use-after-free. Il kernel rilascia la memoria nonostante altri processi la stiano ancora utilizzando. Una distinta out-of-bounds write, ossia la scrittura di dati oltre l’area di memoria assegnata, modifica i contatori associati alle appartenenze multicast di rete. Quando il socket interessato viene chiuso, le successive riduzioni dei contatori modificano le page-table entries, i record che controllano come la memoria viene mappata e come vi si accede.
Queste modifiche rendono accessibile in supervisor mode una mappatura della memoria utente e neutralizzano Supervisor Mode Access Prevention (SMAP) e Supervisor Mode Execution Prevention (SMEP). L’exploit può quindi sostituire un function pointer, un indirizzo memorizzato che indica al sistema quale codice eseguire, in una posizione prevedibile del kernel ed eseguire il proprio codice con privilegi root. Poiché si tratta di una local privilege escalation, da sola non fornisce un percorso remoto per entrare in un sistema. Diventa rilevante quando qualcuno dispone già della possibilità di eseguire codice o utilizzare un account su un host OpenBSD privo delle patch.
Il meccanismo KARL di OpenBSD esegue nuovamente il linking del kernel durante l’avvio per cambiare la posizione di funzioni e dati. Calif ha scoperto che i memory allocator responsabili dell’assegnazione della memoria del kernel rimangono deterministici. Né l’allocator della fase iniziale di avvio né il best-fit allocator randomizzano il proprio indirizzo di base. Di conseguenza, le strutture create nelle prime fasi dell’avvio, compresi i function pointer utilizzati dagli handler delle interfacce di rete lo0 ed enc0, compaiono agli stessi indirizzi dopo riavvii ripetuti sul medesimo hardware. La exploit chain dimostrata non necessita quindi di una vulnerabilità di information disclosure che riveli preventivamente gli indirizzi del kernel.
Oltre all’installazione dei due errata, Calif ha proposto quattro misure più ampie di hardening: controlli di safe-unlinking per le linked list del kernel, già utilizzati da FreeBSD e NetBSD; la randomizzazione della mappatura autoreferenziale delle page-table; l’aggiunta della randomizzazione all’allocazione della memoria del kernel; e l’impiego di bounds checking basato sul compilatore per rilevare accessi alla memoria oltre i limiti consentiti. Si tratta di difese proposte, non di correzioni indicate come già presenti in OpenBSD.
Per i provider di hosting e le aziende che gestiscono infrastrutture OpenBSD, l’azione immediata consiste nell’utilizzare syspatch e verificare che le correzioni applicabili di settembre siano installate su ogni sistema interessato. Gli amministratori dovrebbero inoltre controllare quali utenti e servizi sono autorizzati a eseguire codice locale, poiché l’exploit pubblicato richiede un accesso locale prima di poter elevare i privilegi. Le organizzazioni che valutano la sicurezza di ambienti basati su OpenBSD possono utilizzare AEU-I per servizi IT, infrastrutture e consulenza incentrati sulla sicurezza.