Non vediamo l'ora di bloccarti: DoS remoto tramite Wininit.exe
Editoriale e contributi aggiuntivi di Tricia Howard
Analisi riassuntiva
Stiv Kupchik, ricercatore di Akamai, ha scoperto una nuova vulnerabilità DoS (Denial-of-Service) in Wininit.exe di Microsoft, CVE-2022-44707, con un punteggio CVSS di 6.5.
La vulnerabilità è stata responsabilmente segnalata a MSRC in agosto e descritta nella Patch Tuesday di dicembre 2022.
La vulnerabilità sfrutta il meccanismo di memorizzazione nella cache RPC, su cui abbiamo svolto ricerche approfondite. Forniamo una POC (Proof-of-Concept) dell'attacco nel nostro kit di strumenti RPC.
Sfruttando questa vulnerabilità, un criminale può aggirare un controllo di sicurezza grazie al meccanismo di memorizzazione nella cache e interagire con il meccanismo di arresto su un computer Windows remoto, ottenendo il controllo per interrompere o avviare gli arresti.
La vulnerabilità interessa tutte le versioni di Windows prive di patch, a partire da Windows 8/Server 2012, rafforzando l'importanza di applicare tempestivamente le patch.
Introduzione
Nel nostro post precedente, Cold Hard Cache, abbiamo rivelato alcune altre vulnerabilità RPC che abbiamo individuato utilizzando il nostro kit di strumenti RPC, ed è finalmente giunto il momento. Oggi, in un altro episodio degli attacchi RPC, abbiamo Wininit.
Wininit è un processo Windows critico, che svolge un ruolo cruciale sia nell'avvio che nell'arresto del sistema operativo Windows (in base al principio che se si arresta in modo anomalo, l'intero sistema si arresta in modo anomalo). Pertanto, espone più interfacce RPC che implementano la funzionalità di arresto, alcune delle quali sono anche documentate. La vulnerabilità che abbiamo riscontrato si trova nell'interfaccia WindowsShutdown .
Che cos'è l'interfaccia WindowsShutdown?
WindowsShutdown è una delle poche interfacce RPC esposte da Wininit. È responsabile del processo di arresto (proprio come il resto delle interfacce RPC di Wininit; sorprendente, no?). L'UUID dell'interfaccia è d95afe70-a6d5-4259-822e-2c84da1ddb0d. Fa parte di MS-RSP (Remote Shutdown Protocol) e ha le seguenti funzionalità:
Osservando il file IDL, possiamo notare che solo WsdrInitiateShutdown e WsdrAbortShutdown sono documentati. Dovremmo preoccuparci di una funzione non documentata (una domanda mai fatta a nessun ricercatore)? Per rispondere, diamo un'occhiata al callback di sicurezza per questa interfaccia.
Il callback di sicurezza
Il callback controlla innanzitutto il protocollo di trasporto e consente solo ALPC o TCP. Quindi, viene controllato il livello di autenticazione e solo RPC_C_AUTHN_LEVEL_PKT_PRIVACY viene consentito. Se la funzione chiamata non è WsdrCheckForHiberboot, viene controllato il token dell'utente che chiama in remoto. Ciò viene eseguito confrontando il token con un SID noto (salvato in una variabile globale, creata durante l'inizializzazione di WinInit), SECURITY_NETWORK_RID. Le chiamate a WsdrCheckForHiberboot non subiscono alcuna limitazione dal callback di sicurezza.
L'interfaccia RPC è registrata con il comportamento cache predefinito; quindi, in teoria, se riusciamo a chiamare WsdrCheckForHiberboot, il risultato positivo memorizzato nella cache ci consentirebbe di ignorare il controllo SID nelle successive chiamate a WsdrInitiateShutdown e WsdrAbortShutdown.
Quindi, cosa dobbiamo fare per chiamare WsdrCheckForHiberboot?
WsdrCheckForHiberboot
Non ci interessa cosa faccia la funzione o cosa sia hiberboot (per chi se lo chiede, è l'avvio rapido di Windows), ma dobbiamo sapere come chiamarlo correttamente. È necessario definire correttamente la funzione in un file IDL per compilare un client per esso. Sebbene la funzione non sia documentata, possiamo provare a esaminare il file advapi CheckForHiberboot, l'unico client RPC documentato per cui abbiamo trovato WsdrCheckForHiberboot. Richiede solo due argomenti: un puntatore booleano e un booleano.
Possiamo ricreare la definizione della funzione con questi argomenti, compilando un file e un programma IDL. Ma ci manca ancora qualcosa. Durante la chiamata della funzione in remoto con il nostro client, il runtime RPC ci dice che stiamo chiamando la funzione in modo errato restituendo un errore stub RPC.
Anziché fare più ipotesi, possiamo fare qualcosa di più delicato, ma complicato. Lo stub dell'interfaccia RPC, comprende un campo chiamato ProcFormatString. È fondamentalmente una lunga stringa binaria che descrive i tipi di argomenti e i valori restituiti per tutte le funzioni esposte dall'interfaccia. Questo campo viene utilizzato dal runtime RPC durante il marshalling e l'annullamento del marshalling delle chiamate di funzione (che è il processo che ha restituito l'errore stub RPC durante il nostro tentativo iniziale). Analizzando manualmente quella stringa binaria in modo scrupoloso, alla fine abbiamo scoperto che esiste un altro argomento che la funzione si aspetta di ottenere, del tipo wchar_t*. Nella figura successiva, potete visualizzare la sezione di ProcFormatString di WsdrCheckForHiberboot, con i nostri commenti su ciascuna parte:
Dopo aver aggiunto quel "nuovo" argomento alla nostra definizione di funzione, ci siamo riusciti! CheckForHiberboot viene restituito correttamente e possiamo procedere a chiamare sia WsdrInitiateShutdown che WsdrAbortShutdown.
Imma, ti faccio finire, ma…
Il nostro desiderio immediato è quello di utilizzare un attacco di memorizzazione nella cache per chiamare WsdrInitiateShutdown e ottenere un arresto remoto. Questa volta non sono necessarie ipotesi. Non solo la definizione della funzione è documentata nel file IDL, ma i flag che si aspetta di ottenere sono documentati nella funzione advapi InitiateShutdownA. Quindi, usando la combinazione di flag di SHUTDOWN_GRACE_OVERRIDE, SHUTDOWN_HYBRID e SHUTDOWN_FORCE_OTHERS possiamo forzare un arresto immediato.
Con questo, abbiamo sostanzialmente terminato la nostra catena di attacchi, che ci permesso di aggirare il callback di sicurezza e il relativo controllo SID e di eseguire un arresto remoto. Dal punto di vista tecnico, si tratta di un'escalation di privilegi (che consente a qualsiasi utente autenticato di chiamare WsdrInitiateShutdown in remoto anziché solo quelli consentiti dal SECURITY_NETWORK_RID). Poiché possiamo ottenere un arresto solo utilizzando questa interfaccia, la vulnerabilità è stata invece classificata come vulnerabilità DoS.
Rilevamento
Forniamo un OSQuery per rilevare le versioni prive di patch (e quindi vulnerabili) di Wininit.exe. I clienti di Akamai Guardicore Segmentation possono utilizzare la funzionalità Insight combinata a a una query per cercare le risorse vulnerabili..
WITH product_version AS (
WITH os_minor AS (
WITH os_major AS (
SELECT substr(product_version, 0, instr(product_version, ".")) as os_major, substr(product_version, instr(product_version, ".")+1) as no_os_major_substr
FROM file
WHERE path = "c:\windows\system32\wininit.exe"
)
SELECT substr(no_os_major_substr, instr(no_os_major_substr, ".")+1) as no_os_minor_substr, substr(no_os_major_substr, 0, instr(no_os_major_substr, ".")) as os_minor, os_major
FROM os_major
)
SELECT
CAST(substr(no_os_minor_substr, instr(no_os_minor_substr, ".")+1) AS INTEGER) AS product_minor,
CAST(substr(no_os_minor_substr, 0, instr(no_os_minor_substr, ".")) AS INTEGER) AS product_major,
CAST(os_minor AS INTEGER) AS os_minor,
CAST(os_major AS INTEGER) AS os_major
FROM os_minor
)
SELECT
CASE
WHEN NOT ((os_major = 6 AND os_minor = 3) OR (os_major = 6 AND os_minor = 2) OR (os_major = 10 AND os_minor = 0))
THEN "not supported"
WHEN os_major = 6 AND os_minor = 3 AND product_major = 9600 AND product_minor >= 20716 THEN "patched"
WHEN os_major = 6 AND os_minor = 2 AND product_major = 9200 AND product_minor >= 24011 THEN "patched"
WHEN (
(product_major = 14393 AND product_minor >= 5582)
OR
(product_major = 10240 AND product_minor >= 19624)
OR
(product_major = 19041 AND product_minor >= 1620)
OR
(product_major = 22621 AND product_minor >= 963)
OR
(product_major = 22000 AND product_minor >= 1335)
OR
(product_major = 20348 AND product_minor >= 1366)
OR
(product_major = 17763 AND product_minor >= 3770)
)
THEN
"patched"
ELSE
"not patched"
Riepilogo
Sebbene questa vulnerabilità non sia critica (è solo un arresto remoto, e nemmeno non autenticato), dimostra il potenziale distruttivo intrinseco di MS-RPC, poiché è integrato anche nei servizi più critici del sistema operativo Windows. Inoltre, a differenza di altri tipi di vulnerabilità, con RPC non sono quasi necessari ipotesi: tutte le carte sono sul tavolo (binario); basta saperle leggere.
Trovare modi per sfruttare queste funzioni critiche è esattamente il motivo per il quale proseguiamo la nostra vasta ricerca su MS-RPC. Nonostante il suo uso diffuso, è in gran parte poco studiato nello schema generale delle cose. Vulnerabilità come quella esaminata oggi mostrano perché questo tipo di lavoro è necessario e non vediamo l'ora di esaminare il lavoro di altri ricercatori su MS-RPC se lo desiderano.
Questa vulnerabilità è stata responsabilmente segnalata alla fine di agosto e corretta nella Patch Tuesday di dicembre 2022.