Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
my-CVE-2021-1675 — Analisi dettagliata e implementazione dell'exploit per Windows PrintNightmare (CVE-2021-1675/34527) con escalation dei privilegi basata su RPC ed esecuzione remota di codice tramite installazione di driver di stampa dannosi. | Kitploit
Strumenti/GitHubGitHub/hahaleyile/my-cve-2021-1675
Escalation di PrivilegiAnalisi delle VulnerabilitàExploitPaper e RicercaApprendimento e FormazioneStrumento di Accesso RemotoBinary Exploitation
GitHubhahaleyile/my-cve-2021-1675

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

my-CVE-2021-1675

Analisi dettagliata e implementazione dell'exploit per Windows PrintNightmare (CVE-2021-1675/34527) con escalation dei privilegi basata su RPC ed esecuzione remota di codice tramite installazione di driver di stampa dannosi.

Vedi Repository
3315 anni faNon ancora revisionato

= Rapporto di analisi di Print Nightmare :imagesdir: Figures :toc: :icons: font :figure-caption: Figura :xrefstyle: short :pdf-theme: basic-theme.yml

Il 29 giugno 2021, una vulnerabilità gravissima del servizio di stampa di Windows è stata divulgata come 0day, con un punteggio base di 8.8, pubblicata su GitHub (ora rimossa). Si tratta della celebre PrintNightmare: CVE-2021-34527, il cui grado di pericolosità è persino superiore a quello di EternalBlue.

== Informazioni di base sulla vulnerabilità

La vulnerabilità 34527 interessa quasi tutte le versioni successive a Windows 7 e Windows Server 2008; per i dettagli, si veda <>.

In termini di impatto, un attaccante con l'autenticazione di un utente normale può eseguire codice arbitrario in remoto con privilegi di amministratore. Per quanto riguarda la difficoltà di sfruttamento, la vulnerabilità è molto facile da sfruttare e, di conseguenza, estremamente pericolosa.

Dal punto di vista delle caratteristiche, la vulnerabilità 34527 si basa sulla vulnerabilità CVE-2021-1675. La 1675 è una vulnerabilità di elevazione locale dei privilegi e di esecuzione remota di codice, e ha molte somiglianze con la 34527.

Prima di comprendere il principio di funzionamento della vulnerabilità, dovremmo farci un'idea generale dell'architettura dello spooler di stampa di Windows; questo ci aiuterà a chiarire le relazioni tra i vari moduli coinvolti dalla vulnerabilità.

== Flusso di chiamata di CVE-2021-1675

=== Architettura dello spooler di stampa di Windows

L'architettura dello spooler può essere rappresentata come in <<spooler_arch>>:

[[spooler_arch]] .Print Spooler Architecture image::Print Spooler Architecture.png[]

Nello specifico, lo spooler di stampa serve a gestire i processi di stampa ed è composto dai seguenti componenti:

winspool.drv:: la libreria a collegamento dinamico fornita all'utente. Questo file definisce le API Win32 relative allo spooler che l'utente può chiamare. Tutte le API in esso contenute ottengono i servizi sotto forma di chiamate a procedure remote.

spoolsv.exe:: spoolsv.exe svolge il ruolo di server nel sistema ed è il primo programma a gestire le chiamate API. Questa architettura è stata pensata per consentire allo spooler di stampa di gestire sia i processi di stampa locali sia, senza alcuna distinzione, quelli remoti.

spoolsv.dll:: il programma di routing. Inoltra le richieste di stampa ricevute da spoolsv.exe ai vari provider di stampa e decide quale di essi gestirà definitivamente la richiesta. Il suo scopo è distinguere se il processo di stampa è remoto o locale. Su una macchina remota, assegna il processo al provider di stampa locale.

localspl.dll:: il provider di stampa locale. Il compito principale del provider di stampa è soddisfare le esigenze di gestione dei processi di stampa; la stragrande maggioranza delle API è implementata in questo modulo.

Proseguendo sulla base della teoria sopra descritta, facciamo un esempio: quando si chiama la funzione AddPrinterDriverEx (CVE-2021-1675), il flusso è il seguente:

=== Selezione della versione della funzione

Innanzitutto, questa funzione è in realtà una macro che, in base all'ambiente di compilazione locale, seleziona la versione Unicode (W) o la versione ANSI (A), come in <>:

[[AddPrinterDriverEx]] .AddPrinterDriverEx image::AddPrinterDriverEx.png[]

Ma sia la versione a caratteri wide sia quella a caratteri stretti portano allo stesso risultato, poiché le stringhe del kernel di Windows sono codificate in Unicode; pertanto, alla fine, le chiamate della versione ANSI vengono convertite in chiamate della versione Unicode, come in <>:

[[AnsiToUnicode]] .AnsiToUnicode image::AnsiToUnicode.png[]

Una volta che tutti i parametri della funzione ANSI sono stati convertiti nella versione Unicode, viene chiamata una funzione (<>):

[[AnsiCallUnicode]] .AnsiCallUnicode image::AnsiCallUnicode.png[]

Tale funzione è in realtà la versione Unicode di AddPrinterDriverEx (<>):

[[GetUnicodeProcAddress]] .GetUnicodeProcAddress image::GetUnicodeProcAddress.png[]

=== La funzione API invia la richiesta RPC al server dello spooler

All'interno della funzione della versione Unicode, viene innanzitutto selezionato il tipo dei parametri della funzione in base al valore di Level:

image::pDriverInfo.png[]

In questa vulnerabilità si imposta Level a 2, selezionando cioè per il parametro pDriverInfo il tipo di struttura DRIVER_INFO_2. Subito dopo, Windows elabora i parametri della funzione e, una volta completata l'elaborazione, prosegue la gestione dell'API tramite una chiamata a procedura remota:

image::set arguments.png[]

image::NdrClientCall3.png[]

=== Il meccanismo MSRPC

Il meccanismo di chiamata a procedura remota di Microsoft è costruito sullo standard DCE. In termini semplici, una chiamata a procedura remota consiste nell'eseguire su un sistema remoto processi predefiniti dal programmatore o dal sistema stesso.

Concretamente, la RPC serializza la funzione da chiamare in remoto, la trasmette al sistema remoto attraverso la rete; il sistema remoto la deserializza e la esegue. Nell'architettura realizzata da Microsoft, TCP/IP e SMB sono i protocolli generalmente scelti per trasportare le chiamate RPC.

Per usare MSRPC, è necessario innanzitutto definire la descrizione dell'interfaccia IDL della funzione da chiamare, quindi usare lo strumento MIDL per generare gli stub di serializzazione corrispondenti per il client e per il server. Per alcune API Win32, invece, lo stub lato server è già definito, quindi è sufficiente generare e usare lo stub lato client.

MSRPC usa un UUID per identificare un determinato tipo di protocollo; ad esempio, MS-RPRN descrive il protocollo di stampa remota e tutte le funzioni relative alla stampa remota fanno parte di questo protocollo. MSPRC usa l'UUID 12345678-1234-ABCD-EF00-0123456789AB per identificare tale protocollo (<<rprn_uuid>>):

[[rprn_uuid]] .MS-RPRN UUID image::spoolss uuid.png[]

Successivamente, sempre su questa connessione, si può usare l'operator number per identificare le funzioni all'interno del protocollo e chiamarle in remoto; ad esempio, AddPrinterDriverEx si identifica con 89 (<<addPrinterDriverEx_opnum>>):

[[addPrinterDriverEx_opnum]] .AddPrinterDriverEx Opnum image::AddPrinterDriverEx Opnum.png[]

Nell'uso di MSRPC ci sono due punti a cui prestare particolare attenzione:

[IMPORTANT]

  • Per le connessioni TCP/IP viene usata una porta dinamica, il cui valore deve essere ottenuto tramite l'endpoint mapper in ascolto sulla porta 135.

"As you can see in your output, the scripts are trying to connect to port 135 (endpoint mapper) in order to get the TCP/IP port where the DCOM endpoint is listening (that is a dynamic port)." -- SecureAuthCorp/impacket issue #412

  • Inoltre, alcune funzioni RPC richiedono l'autenticazione per essere chiamate; per questo motivo la vulnerabilità richiede i privilegi di un utente normale. ====

=== spoolsv.exe gestisce le richieste API

[[call_flow]] .RpcAddPrinterDriverEx Call Flow image::Function Calls.png[]

Come si può vedere da <<call_flow>>, spoolsv.exe chiama queste funzioni; dall'analisi interna delle funzioni, però, il modulo non esegue alcuna operazione significativa oltre all'inizializzazione. Alla fine, il modulo chiama la funzione puntata da pLocalProvidor, cioè la funzione LocalAddPrinterDriverEx nel modulo localspl.dll. In quanto provider di stampa locale, localspl è effettivamente il modulo che implementa la funzionalità dell'API.

=== Logica di implementazione della funzione del provider di stampa locale

[[LocalAddPrinterDriverEx]] .LocalAddPrinterDriverEx image::LocalAddPrinterDriverEx.png[]

Innanzitutto, <> mostra che il modulo verifica che lo spooler sia in esecuzione e poi salta alla funzione SplAddPrinterDriverEx.

[[SplAddPrinterDriverEx]] .SplAddPrinterDriverEx image::SplAddPrinterDriverEx.png[]

L'interno della funzione <> è il punto cruciale in cui si stabilisce se la funzione AddPrinterDriverEx può essere eseguita con successo. La prima parte non va considerata: WPP è una tecnologia legata alla registrazione dei log, quindi la saltiamo per ora.

Nella seconda parte, Microsoft definisce una variabile, v12, un flag che determina se la funzione deve continuare l'esecuzione o uscire immediatamente.

[[bittest]] .bittest dwFileCopyFlags image::bittest in spl.png[]

Come si vede da <>, le condizioni per continuare l'esecuzione sono due: la prima è che v12 sia 0, cioè che il test bittest abbia successo; la seconda è che Validate abbia successo. Validate è un controllo dei privilegi e non esiste un buon modo per aggirarlo. Tra le API presenti c'è OpenProcessToken, il che indica che è necessario elevare i privilegi nel processo successivo; se non si è amministratori, non è possibile farlo.

Quindi, per continuare l'esecuzione, l'unica strada è aggirare il controllo di bittest; il valore esaminato, a4 — il quarto parametro della funzione — è il parametro documentato sul sito ufficiale <>:

|=== |Name/value |Description

|APD_STRICT_UPGRADE

0x00000001

|Add the replacement printer driver only if none of the files of the replacement driver are older than any corresponding files of the currently installed driver.

|APD_STRICT_DOWNGRADE

0x00000002

|Add the replacement printer driver only if none of the files of the currently installed driver are older than any corresponding files of the replacement driver.

|APD_COPY_ALL_FILES

0x00000004

|Add the printer driver and copy all the files in the driver directory. File time stamps MUST be ignored.

|APD_COPY_NEW_FILES

0x00000008

|Add the printer driver and copy the files in the driver directory that are newer than any of the corresponding files that are currently in use.

|APD_COPY_FROM_DIRECTORY

0x00000010

|Add the printer driver by using the fully qualified file names that are specified in the _DRIVER_INFO_6 structure. If this flag is specified, one of the other copy flags in this bit field MUST be specified.

|APD_DONT_COPY_FILES_TO_CLUSTER

0x00001000

|When adding a printer driver to a print server cluster, do not copy the driver files to the shared cluster disk.

|APD_COPY_TO_ALL_SPOOLERS

0x00002000

|Add the printer driver to cluster spooler servers.

|APD_INSTALL_WARNED_DRIVER

0x00008000

|Add the printer driver, even if it is in the server's List of Warned Printer Drivers.

|APD_RETURN_BLOCKING_STATUS_CODE

0x00010000

|Specifies the implementation-specific error code to return if the printer driver is blocked from installation by server policy.

|===

Il bittest 16 verifica se il 16° bit della variabile è 1; il valore corrispondente del parametro è 0x8000 (APD_INSTALL_WARNED_DRIVER). Dalla descrizione si capisce anche che questo parametro significa aggiungere il driver della stampante al server senza alcuna verifica.

Si dice che, prima che 1675 fosse corretta, questo parametro non fosse ancora presente nella documentazione ufficiale; non è difficile capire dove risiedesse la vulnerabilità.

=== Metodo di sfruttamento della vulnerabilità

Quando il metodo di aggiunta del driver della stampante viene effettivamente eseguito, se è stata scelta la struttura DRIVER_INFO_2, accadono le seguenti cose:

. Vengono aperti rispettivamente DriverFile, ConfigFile e DataFile, verificando che i tre file esistano. Di questi, solo DataFile può essere un percorso UNC.

. Se tutti e tre i file esistono, vengono copiati nella directory C:\Windows\System32\spool\drivers\x64\3\New, come mostrato in <<cp_conf_file>> e <<cp_data_file>>: + [[cp_conf_file]] .Copy Config File image::copy config file.png[] + [[cp_data_file]] .Copy Data File image::copy data file.png[]

ifdef::backend-pdf[] Per i risultati di esecuzione del programma malevolo, si veda https://github.com/hahaleyile/my-CVE-2021-1675[il mio repository]; la GIF dimostrativa è il file gif nella directory Figures. endif::[]

== La patch di Microsoft per la vulnerabilità 1675

L'8 giugno 2021, Microsoft ha corretto la vulnerabilità CVE-2021-1675; le modifiche specifiche sono le seguenti:

[[path_1675]] .CVE-2021-1675 Patch image::IsElevated.png[]

[[YIsElevationRequired]] .YIsElevationRequired image::YIsElevationRequired.png[]

[[YIsElevated]] .YIsElevated image::YIsElevated.png[]

[[unset_1675]] .Unset APD_INSTALL_WARNED_DRIVER image::JudgeIsElevated.png[]

Microsoft ha aggiunto alla funzione RpcAddPrinterDriverEx un controllo sull'elevazione dei privilegi dell'utente, e l'utente può rimuovere questa restrizione tramite il registro di sistema (<<path_1675>>). È sufficiente creare una chiave chiamata NoWaringNoElevationOnInstall nella posizione specificata del registro (<>), oppure che l'account RPC riesca a ottenere il token di processo TOKEN_QUERY (<>), per aggirare la patch. Se la patch è attiva, il 16° bit del parametro dwFileCopyFlags viene azzerato tramite un'operazione AND, il che significa che il valore del parametro APD_INSTALL_WARNED_DRIVER viene neutralizzato (<<unset_1675>>).

== Bypass della patch di 1675

Anche se Microsoft ha applicato la patch alla funzione RpcAddPrinterDriverEx, è comunque possibile aggirarla tramite la chiamata remota RpcAsyncAddPrinterDriver. Come mostrato in <<async_send>>, questa funzione lato client è una chiamata remota diretta al lato server:

[[async_send]] .RpcAsyncAddPrinterDriver Send image::RpcAsyncAddPrinterDriver Send.png[]

Il lato server alloca innanzitutto lo spazio per il thread e poi prosegue la chiamata, come mostrato in <<async_receive>>:

[[async_receive]] .RpcAsyncAddPrinterDriver Receive image::RpcAsyncAddPrinterDriver Receive.png[]

Nella funzione che viene chiamata successivamente, tutti i parametri vengono inseriti nello stack e YAddPrinterDriverEx viene eseguito in un thread (<<async_yadd>>):

[[async_yadd]] .thread start YAddPrinterDriverEx image::thread start YAddPrinterDriverEx.png[]

In questo modo si aggira con successo la patch di Microsoft per RpcAddPrinterDriverEx.

In altre parole, chiamando in remoto la funzione RpcAsyncAddPrinterDriver, si può continuare a eseguire codice arbitrario con privilegi di amministratore.

Inoltre, secondo quanto dichiarato da <>, la patch presenta ancora problemi nella verifica dei Token e, sulle macchine con UAC completamente disattivato, la patch risulta inefficace. Tuttavia, non conoscendo a fondo questi meccanismi, non mi esprimo oltre in merito.

== La correzione di Microsoft per la vulnerabilità 34527

Scarica lo strumento

. Il motivo per cui vengono copiati in questa directory è che i file corrispondenti devono essere eseguiti; 3 indica che il driver della stampante è un driver di tipo v3. I nuovi file vengono prima copiati nella directory New per evitare di sovrascrivere i file nella directory 3. Se nella directory 3 esiste un file con lo stesso nome, il file omonimo viene spostato nella directory Old come backup, quindi i file da New vengono copiati in 3 sovrascrivendo i file esistenti. Questo si può osservare eseguendo una seconda volta il metodo RpcAddPrinterDriverEx: + .Second Time RPC Call image::second time call.png[] + .Backup Files To Old Directory image::backup file.png[] + .Copy New Files To Destination image::copy file.png[] + In base a questo meccanismo, possiamo salvare un file da un percorso remoto come file in un percorso locale, poiché tra i parametri della funzione sia il driver sia il file di configurazione possono essere solo percorsi locali; solo il parametro del file dati può essere un percorso remoto.

. Secondo <>, pConfigFile è la DLL di configurazione del driver del dispositivo, quindi deve essere caricata una volta per l'inizializzazione. Anche l'esecuzione reale lo ha confermato. + .Load pConfigFile image::Load Image.png[] + In questo modo, è sufficiente scrivere una DLL dannosa e inserire il codice malevolo nel punto di ingresso della DLL perché venga eseguito; si può così eseguire codice arbitrario, e per di più con privilegi di amministratore. + .spoolsv.exe is under administrator privilege image::spoolsv user.png[]

. La funzione CreateInternalDriverFileArray() decide, in base al flag delle operazioni sui file, se controllare la directory dei driver dello spool. Se il flag a5 è impostato a False, la funzione di caricamento del driver controlla solo se la directory dell'utente contiene il file del driver da copiare. In caso contrario, la funzione tenta di cercare il driver nella directory dei driver dello spool. Questo richiede che dwFileCopyFlags includa anche il flag APD_COPY_FROM_DIRECTORY. + image::APD.png[] + image::APD_1.png[]

[TIP]

In sintesi, l'idea di sfruttamento del codice malevolo è la seguente: inizializzare la DLL dannosa come configfile, così da eseguire codice arbitrario con privilegi di amministratore. È sufficiente avviare una condivisione samba sull'host dell'attaccante e far sì che la vittima scarichi il programma malevolo sul proprio computer come datafile e lo esegua.

== Utilizzo del programma di exploit

Questo programma è basato su docker e risolve efficacemente i problemi di dipendenza dall'ambiente.

Innanzitutto, l'utente scarica il file compose nella propria directory, quindi crea in quella directory una cartella chiamata share da usare come directory di montaggio. L'utente può inserire il programma malevolo nella cartella share; la cartella verrà condivisa come percorso samba smb.

Quindi, l'utente digita il comando nel terminale

[source,docker]

docker-compose up -d

per avviare il cluster (un contenitore). L'utente può entrare nel contenitore per operare al suo interno; l'ambiente nel contenitore è già completamente configurato.

In alternativa, si può digitare direttamente nel terminale il comando

[source,docker]

docker-compose run my_cve python main.py -h

per eseguire il comando.

== Risultato di esecuzione del programma di exploit

Ringrazio <> per il codice open source che mi è servito come riferimento!

ifndef::backend-pdf[] .Program running result image::exploit.gif[] endif::[]

Il 6 luglio 2021, Microsoft ha risolto temporaneamente il problema di questa vulnerabilità dello spooler di stampa con una nuova serie di patch.

Secondo la dichiarazione ufficiale, questa patch farà sì che l'installazione dei driver delle stampanti sul server di stampa possa essere eseguita solo da amministratori. Inoltre, Microsoft ha aggiunto un criterio di gruppo e due chiavi di registro per consentire agli utenti di personalizzare tale criterio.

Attraverso la decompilazione con ida di <<restrict_async>>, possiamo vedere che Microsoft ha aggiunto alle funzioni Async un controllo sui Token e sulle voci di registro.

[[restrict_async]] .restrict in async function image::restrict in async.png[]

Da <<restrict_rpcadd>> possiamo vedere che Microsoft ha aggiunto alla funzione RpcAddPrinterDriverEx un controllo sul gruppo di utenti e sulla relativa chiave di registro.

[[restrict_rpcadd]] .restrict in RpcAddPrinterDriverEx Function image::restrict in rpcadd.png[]

Quindi, probabilmente la correzione della vulnerabilità 1675 presenta effettivamente ancora problemi per quanto riguarda la verifica dei Token.

== Piano del progetto

. Aggiungere il supporto della chiamata remota RpcAsyncAddPrinterDriver, per aggirare la patch di Microsoft dell'8 giugno e realizzare l'exploit per CVE-2021-34527.

. Comprendere il meccanismo di UAC e perfezionare questa analisi della vulnerabilità.

[bibliography] == Riferimenti

  • [[[a,Sito ufficiale]]] Windows Print Spooler Remote Code Execution Vulnerability https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2021-34527

  • [[[b,dwFileCopyFlags]]] https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/b96cc497-59e5-4510-ab04-5484993b259b

  • [[[c,Analisi della vulnerabilità Windows PrintNightmare (CVE-2021-34527) e della relativa patch]]] https://www.freebuf.com/vuls/279876.html

  • [[[d,gentilkiwi/mimikatz]]] https://github.com/gentilkiwi/mimikatz

  • [[[e,Documentazione ufficiale]]] DRIVER_INFO_2 structure https://docs.microsoft.com/en-us/windows/win32/printdocs/driver-info-2

  • [[[f,cube0x0]]] https://github.com/cube0x0

  • [[[g,James Forshaw]]] https://twitter.com/tiraniddo/status/1410726790994169857

  • [[[h,Dichiarazione ufficiale]]] KB5005010: Restricting installation of new printer drivers after applying the July 6, 2021 updates https://support.microsoft.com/en-us/topic/kb5005010-restricting-installation-of-new-printer-drivers-after-applying-the-july-6-2021-updates-31b91c02-05bc-4ada-a7ea-183b129578a7