Vi serve il cloud computing? Iniziate subito

Non vediamo l'ora di bloccarti: DoS remoto tramite Wininit.exe

Stiv Kupchik

scritto da

Stiv Kupchik

January 31, 2023

Stiv Kupchik

scritto da

Stiv Kupchik

Stiv Kupchik svolge il ruolo di Security Researcher Team Lead in Akamai. I suoi progetti di ricerca ruotano intorno ai componenti interni dei sistemi operativi, alla ricerca sulle vulnerabilità e all'analisi dei malware. Ha presentato la sua ricerca in occasione di conferenze come Black Hat, Hexacon e 44CON. Oltre ad essere un esperto di cybersicurezza, Stiv ha conseguito anche una laurea in fisica.

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).

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à: 

Funzioni esposte di WindowsShutdown: WsdrInitiateShutdown, WsdrAbortShutdown e WsdrCheckForHiberboot Figura 1: Le funzionalità dell'interfaccia WindowsShutdown

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.

Decompilazione del callback di sicurezza per WindowsShutdown Figura 2: Il callback di sicurezza per WindowsShutdown

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.

Disassemblaggio dell'advapi32 di CheckForHiberboot Figura 3: L'advapi CheckForHiberboot: l'unico client RPC documentato per WsdrCheckForHiberboot

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.

Ricreazione iniziale della definizione di WsdrCheckForHiberboot, basata sulla funzione advapi Figura 4: La prima ricreazione della definizione di WsdrCheckForHiberboot

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:

Ricreazione iniziale della definizione di WsdrCheckForHiberboot, basata sulla funzione advapi Figura 5: La sezione di WsdrCheckForHiberboot della ProcFormatString

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.



Stiv Kupchik

scritto da

Stiv Kupchik

January 31, 2023

Stiv Kupchik

scritto da

Stiv Kupchik

Stiv Kupchik svolge il ruolo di Security Researcher Team Lead in Akamai. I suoi progetti di ricerca ruotano intorno ai componenti interni dei sistemi operativi, alla ricerca sulle vulnerabilità e all'analisi dei malware. Ha presentato la sua ricerca in occasione di conferenze come Black Hat, Hexacon e 44CON. Oltre ad essere un esperto di cybersicurezza, Stiv ha conseguito anche una laurea in fisica.