L'iniezione di processo è una delle tecniche più importanti nella sicurezza informatica. Questa tecnica funziona inserendo codice in un altro spazio di indirizzi di processo già in esecuzione ed eseguendo il codice in quello spazio. Si tratta di un vero e proprio disastro dal punto di vista della sicurezza, poiché consente al codice di essere eseguito con le autorizzazioni del processo di destinazione, che potrebbe essere in grado di aggirare i controlli di sicurezza utilizzando l'escalation dei privilegi esistente nel processo di destinazione, i meccanismi di rilevamento, ecc.
L'iniezione di processo è un vettore di minaccia che ha generato molte forme di malware che infestano Internet e minacce persistenti avanzate (APT). Sebbene si tratti di una tecnica valida in un ambiente di sviluppo software per eseguire il debug o estendere un'applicazione, viene spesso utilizzata dagli autori delle minacce per eseguire codice senza autorizzazione, eludere la persistenza e rimanere inosservati.
Questo blog analizza i principi dell'iniezione di processo, i suoi meccanismi fondamentali, le tecniche comuni, i metodi di rilevamento e come prevenirla. Esploreremo anche alcuni fondamenti, come le operazioni di memoria, le tecniche di iniezione, i metodi di rilevamento e alcuni esempi pratici di attacchi.
Che cos'è l'iniezione di processo?
L'iniezione di processo consente di iniettare un codice nello spazio di memoria di un altro processo in esecuzione. Con questa tecnica, l'autore dell'attacco forza il processo di destinazione a eseguire un codice arbitrario scrivendo il proprio codice nello spazio di indirizzamento di quel processo. Il codice iniettato viene eseguito nel contesto e con i diritti del processo vulnerabile, ereditando così tutti i suoi diritti di accesso e il livello di affidabilità sul sistema.
L'iniezione di processo consiste essenzialmente nei seguenti componenti tecnici: acquisizione dell'handle del processo, allocazione della memoria nel processo di destinazione, operazioni di scrittura del codice e meccanismi di attivazione dell'esecuzione. Per eseguire il processo di iniezione vengono utilizzate funzioni API di Windows quali OpenProcess(), VirtualAllocEx(), WriteProcessMemory() e CreateRemoteThread().
Perché l'iniezione di processo è pericolosa?
Diversi aspetti tecnici rendono questo tipo di attacco relativamente pericoloso. Il codice eseguito dal thread iniettato ha gli stessi privilegi del processo di destinazione, con conseguente elevato accesso al sistema. Questo metodo aggira qualsiasi scansione di sicurezza basata su file, poiché il codice non sicuro esiste solo nella memoria.
Ha anche un grave effetto sulla stabilità e la sicurezza dei sistemi. Le operazioni di iniezione possono essere interrotte dai processi di destinazione e introdurre instabilità in tutto il sistema. Ciò avviene terminando i processi dei prodotti di sicurezza, rubando dati dalle applicazioni protette e stabilendo un accesso persistente al sistema che elude le comuni tecniche di pulizia.
Nozioni fondamentali sulla memoria di processo
La base tecnica delle tecniche di iniezione di processo è la comprensione delle strutture e delle operazioni della memoria di processo. Esistono caratteristiche interne del modello di gestione della memoria del sistema operativo Windows che consentono e limitano le interazioni e l'accesso alla memoria tra i processi. Esse modificano istantaneamente il modo in cui funziona l'iniezione di processi e il modo in cui i difensori possono rilevarla e proteggersi da essa.
Memoria virtuale e spazio di indirizzamento dei processi
Ogni processo Windows ha il proprio spazio di indirizzamento virtuale, isolato dagli altri processi in esecuzione sullo stesso sistema. L'intervallo di questo spazio di indirizzamento virtuale è compreso tra 0 e 0x7FFFFFFF per i processi a 32 bit e tra 0 e 0x7FFFFFFFFFF per i processi a 64 bit. La mappatura dagli indirizzi virtuali alle posizioni di memoria fisica viene eseguita con l'aiuto della tecnica di paging da parte del Gestore memoria di Windows.
Il processo ha una serie di regioni nel proprio spazio di indirizzamento, come il codice eseguibile del processo, le DLL caricate, le allocazioni dell'heap e lo spazio dello stack. Queste regioni hanno funzioni e tipi di dati specifici. Windows dispone di tabelle di pagine che descrivono dove si trovano le pagine dei frame di memoria e se si trovano nello spazio di indirizzamento virtuale.
Autorizzazioni e protezione della memoria
Esistono autorizzazioni di accesso per le regioni di memoria, che descrivono come i processi devono interagire con esse. Queste autorizzazioni includono:
- PAGE_EXECUTE: la memoria può essere eseguita come codice
- PAGE_READ: La memoria può essere letta
- PAGE_WRITE: La memoria può essere scritta
- PAGE_EXECUTE_READ: La memoria può essere eseguita e letta
- PAGE_EXECUTE_READWRITE: La memoria può essere eseguita, letta e scritta
Queste autorizzazioni sono applicate dal Gestore memoria di Windows a livello di pagina. Se un'applicazione (o un processo) tenta di accedere alla memoria in modo non consentito, il sistema genera una violazione di accesso.
API Windows critiche per le operazioni di memoria
Windows dispone di alcune API importanti per la manipolazione della memoria. Queste API sono gli elementi costitutivi dell'iniezione di processi. Le versioni "Ex" di queste funzioni sono destinate ai processi esterni, mentre le normali versioni successive sono destinate allo spazio di memoria del processo chiamante. La conoscenza di queste API consente il rilevamento di potenziali attività di iniezione e il loro tracciamento.
- VirtualAlloc/VirtualAllocEx: Riserva e assegna memoria in un processo
- VirtualProtect/VirtualProtectEx: Modifica le autorizzazioni delle aree di memoria
- ReadProcessMemory: Legge i dati dallo spazio di memoria di un altro processo
- WriteProcessMemory: Scrive dati nello spazio di memoria di un altro processo
- VirtualFree/VirtualFreeEx: Rilascia le regioni di memoria allocate
Tipi di tecniche di iniezione di processo
L'iniezione di processo comprende una serie di tecniche diverse che utilizzano tutte una qualche forma di esecuzione di codice per i processi di destinazione. Questa differenza nelle chiamate API di Windows e nella manipolazione della memoria determina modelli operativi e firme di rilevamento unici per ciascuna tecnica.
L'analisi di queste tecniche può essere di grande aiuto ai team di sicurezza nell'identificare e rispondere a metodi di iniezione specifici.
1. Iniezione DLL
L'iniezione DLL è il processo che forza un processo a caricare file DLL maligni. Utilizza una serie di funzioni API: OpenProcess(), VirtualAllocEx() e CreateRemoteThread(). Si inizia riservando memoria all'interno del processo di destinazione per contenere il percorso della DLL. Quindi si avvia un thread remoto che chiama LoadLibrary() con il percorso come parametro per istruire il processo di destinazione a caricare la DLL dannosa.
Una DLL iniettata ha pieno accesso alle funzioni/ai processi del processo di destinazione con indirizzi di memoria dell'intero spazio di memoria del processo di destinazione e di tutti gli altri moduli che il processo di destinazione ha caricato nella memoria.
2. Iniezione di codice
L'iniezione di codice è una forma di attacco che inietta codice dannoso nello spazio di memoria di un processo, dove il codice viene eseguito. Si tratta semplicemente di scrivere un codice all'indirizzo dello spazio di memoria di un processo. Si tratta di una tecnica in più fasi che include l'acquisizione di un handle sul processo, l'utilizzo di VirtualAllocEx() per allocare la memoria, WriteProcessMemory() per scrivere il codice e, infine, CreateRemoteThread() per eseguirlo.
Il codice eseguito ha le autorizzazioni del processo di destinazione in cui viene eseguito e tutti i privilegi di sicurezza e i diritti di accesso saranno ereditati.
3. Dirottamento dell'esecuzione del thread
Il dirottamento dell'esecuzione del thread sospende un thread nel processo di destinazione, modifica il suo contesto di esecuzione per puntare al codice dell'autore dell'attacco e continua l'esecuzione. In questa tecnica, l'autore dell'attacco utilizza le API SuspendThread(), GetThreadContext(), SetThreadContext() e ResumeThread().
Poiché utilizza un thread legittimo, è più difficile rilevarlo poiché il thread dirottato viene eseguito con i suoi privilegi esistenti per eseguire il codice dannoso.
4. Iniezione APC (chiamata di procedura asincrona)
L'iniezione APC mette in coda il codice dannoso da eseguire quando un thread entra in uno stato di allerta. Questo metodo mette in coda il codice su un thread utilizzando QueueUserAPC(). Il codice iniettato nel thread viene eseguito quando questo elabora la sua coda APC, cosa che di solito avviene durante particolari chiamate di sistema o operazioni di attesa. Questo metodo è particolarmente adatto ai thread che visitano ripetutamente stati mutabili.
5. Iniezione DLL riflettente
Il metodo di iniezione DLL riflettente carica una DLL con l'aiuto di un caricatore Windows e non scrive un artefatto del file system. Si tratta di una DLL personalizzata con istruzioni su come mapparla e indirizzarla nella memoria. Questo trucco consiste nell'iniettare il codice del caricatore e la DLL nella memoria del processo di destinazione ed eseguire il caricatore per preparare la DLL. In questo modo si evita il rilevamento da parte dei normali meccanismi di caricamento delle DLL e del monitoraggio.
6. Process Hollowing
Il Process Hollowing è una tecnica di iniezione furtiva in cui gli aggressori creano un processo legittimo in uno stato sospeso (utilizzando CreateProcess con CREATE_SUSPENDED), smappano il suo spazio di memoria originale (tramite NtUnmapViewOfSection/ZwUnmapViewOfSection), allocano nuova memoria (VirtualAllocEx), scrivono codice dannoso (WriteProcessMemory), correggono l'intestazione PE e i riposizionamenti, aggiornano il Process Environment Block (PEB) e infine reindirizzano il punto di ingresso (SetThreadContext) prima di riprendere l'esecuzione (ResumeThread). Ciò consente al codice dannoso di essere eseguito con l'identità e i privilegi di un processo legittimo.
Come funziona l'iniezione di processo?
Le iniezioni di processo seguono una serie di passaggi nel tentativo di eseguire codice in un processo di destinazione. Indipendentemente dal metodo di iniezione, l'implementazione tecnica segue determinati passaggi che manipolano la memoria del processo e modificano il modo in cui viene eseguito il flusso del processo.
Il primo è l'identificazione del processo di destinazione e le operazioni di acquisizione dell'accesso. Il processo dannoso utilizza OpenProcess() per ottenere un handle sul processo di destinazione. I diritti di accesso richiesti per questo handle sono PROCESS_CREATE_THREAD, PROCESS_QUERY_INFORMATION, PROCESS_VM_OPERATION, PROCESS_VM_WRITE e PROCESS_VM_READ.
Il secondo passaggio cruciale è l'allocazione della memoria nel processo di destinazione. VirtualAllocEx() alloca lo spazio di memoria nello spazio di indirizzamento del processo di destinazione riservando e impegnando pagine della memoria virtuale.
Il terzo passo consiste nel copiare lo shellcode nell'area di memoria allocata. WriteProcessMemory() copia i byte di codice dal buffer di origine alla regione di memoria del processo di destinazione. Questa operazione deve tenere conto dei requisiti di allineamento e dimensione.
L'ultimo passo dell'esecuzione rappresenta i componenti fondamentali finali. Ogni tecnica impiega un meccanismo o un altro:
- CreateRemoteThread() crea un nuovo thread per eseguire il codice iniettato
- QueueUserAPC() mette in coda l'esecuzione del codice in un thread esistente
- SetThreadContext() modifica il flusso di esecuzione del thread esistente
- Modifica diretta dei puntatori di funzione o degli hook
Una volta avviata l'esecuzione, il codice iniettato viene eseguito all'interno del contesto del processo di destinazione, avendo accesso alle risorse e al token di sicurezza del processo di destinazione. Questo codice può quindi eseguire qualsiasi operazione per cui è stato progettato, utilizzando i privilegi e il livello di affidabilità del processo di destinazione.
Come rilevare gli attacchi di iniezione di processo?
L'iniezione di processo è difficile da rilevare perché coinvolge diversi componenti e comportamenti del sistema. Per identificare l'attività di iniezione, i sistemi di sicurezza devono monitorare i movimenti della memoria, le chiamate API e tutti i comportamenti dei processi.
Questi metodi di rilevamento, combinati tra loro, formano una strategia di rilevamento complessiva.
Analisi dei modelli di memoria
L'analisi della memoria si concentra sulla ricerca di modelli comuni nelle regioni di memoria dei processi. Ciò avviene perché queste regioni della memoria di processo vengono scansionate dagli strumenti di sicurezza per verificare le impostazioni di autorizzazione della memoria di processo e il contenuto previsto. Ciò include il rilevamento di regioni eseguibili anomale e pagine che non sono conformi alle loro tipiche firme di contenuto all'interno dei processi, tra le altre cose.
Gli scanner di memoria cercano deviazioni dai binari di processo originali, monitorando le modifiche nelle strutture di memoria di processo normalmente statiche o cercando segmenti di codice dinamico.
Monitoraggio delle chiamate API
Le sequenze sospette di chiamate di manipolazione della memoria vengono rilevate dal monitoraggio API di Windows. Gli strumenti di sicurezza monitorano OpenProcess() per l'accesso ai processi, VirtualAllocEx() per l'allocazione della memoria e WriteProcessMemory() per la scrittura della memoria. Se viene creato o manipolato un thread, ad esempio CreateRemoteThread(), questo sarà un chiaro segno di iniezione.
Anche le modifiche allo stato dei processi e dei thread tramite API come SuspendThread() e SetThreadContext() dovrebbero essere monitorate, poiché spesso si trovano nelle catene di iniezione.
Indicatori comportamentali
Il monitoraggio del comportamento dei processi viene effettuato per identificare modelli di attività imprevisti che suggeriscono questi tentativi di iniezione. I sistemi di rilevamento delle intrusioni controllano i thread in un processo in esecuzione relativamente stabile e le modifiche nella mappa di memoria del processo per tenere traccia di tali processi.
Questi comportamenti, insieme alla modifica delle tabelle degli indirizzi di importazione e alle operazioni di memoria tra processi, sono indicatori rilevanti per il rilevamento.
Strumenti di rilevamento
L'individuazione dell'iniezione di processi richiede alcuni strumenti di sicurezza con capacità di monitoraggio approfondito. L'analisi in tempo reale viene effettuata da monitor di processo che controllano le chiamate API e le azioni di sistema, mentre gli strumenti di analisi della memoria eseguono un'analisi approfondita degli spazi di memoria del processo. Gli analizzatori di log degli eventi consentono ai team di registrare la cronologia degli eventi di sicurezza all'interno del sistema in modo da poter ottenere una prospettiva sul passato.
Le soluzioni di rilevamento e risposta aziendali (EDR) come SentinelOne, combinano vari metodi di monitoraggio con funzionalità analitiche. Esistono strumenti di amministrazione del sistema, come il monitoraggio dei processi e l'esplorazione dei processi, che mostrano i processi in dettaglio e l'allocazione di memoria per ciascun processo.
Come prevenire gli attacchi di iniezione di processi?
La prevenzione dell'iniezione di processi non può essere garantita da un unico controllo di sicurezza, ma richiede controlli a livello di sistema, processo e codice. Queste misure di mitigazione si concentrano sulla limitazione delle capacità di iniezione di processo, nonché sul rendere più difficile l'iniezione nei potenziali processi di destinazione.
Prevenzione a livello di sistema
Le misure preventive a livello di sistema iniziano con una corretta gestione degli accessi e dei privilegi. I sistemi dovrebbero avere diritti di creazione e manipolazione dei processi configurati in modo da limitare gli utenti non amministratori, in modo che possano solo aprire handle a processi sensibili sui sistemi. Queste restrizioni sono applicate dal controllo dell'account utente (UAC) e dai criteri AppLocker per gestire quali processi possono essere eseguiti e a quale livello di privilegio.
Firma del codice
Un altro importante livello di prevenzione è l'applicazione della firma del codice. I moduli devono essere caricati con le loro firme digitali verificate e i codici firmati in modo inappropriato o non firmati devono essere rifiutati dai sistemi. I criteri di Windows Defender Application Control (WDAC) applicano i requisiti di integrità del codice e disabilitano il caricamento di DLL e file eseguibili non firmati.
Protezione della memoria
I meccanismi di protezione della memoria sono una parte importante della difesa. La prevenzione dell'esecuzione dei dati (DEP) protegge dall'esecuzione di codice dalle pagine di dati, mentre la randomizzazione del layout dello spazio di indirizzamento (ASLR) rende difficile prendere di mira una memoria specifica.
Le mitigazioni di processo protetto medio includono Control Flow Guard (CFG), che controlla gli obiettivi per le chiamate indirette, e Protected Process Light (PPL), che limita la capacità dei processi di aprire quelli esistenti in base ai livelli di firma dei membri.
Rafforzamento delle applicazioni
Anche per il rafforzamento delle applicazioni, il team di sicurezza deve seguire pratiche di codifica sicure e opzioni del compilatore. Gli sviluppatori devono configurare le funzionalità di sicurezza, come /DYNAMICBASE e /NXCOMPAT, implementare la gestione delle eccezioni e convalidare le operazioni di memoria all'interno del processo di debug dell'applicazione.
Cybersicurezza alimentata dall'intelligenza artificiale
Elevate la vostra posizione di sicurezza con il rilevamento in tempo reale, la risposta automatica e la visibilità totale dell'intero ambiente digitale.
Richiedi una demoConclusione
L'iniezione di processo inietta codice dannoso negli spazi di memoria insieme ad altri processi in corso. L'autore dell'attacco costringe i processi di destinazione a eseguire codice arbitrario, oltre a scrivere il proprio codice negli spazi di indirizzamento. Il motivo per cui è così pericoloso è che può eludere le tradizionali tecniche di rilevamento delle minacce. Per individuarlo è necessario utilizzare soluzioni di sicurezza avanzate e strategie di prevenzione.
Queste includono la protezione della memoria, i controlli comportamentali, i controlli di accesso e altro ancora. Comprendere i meccanismi delle tecniche di iniezione di processo consente alle organizzazioni di rafforzare adeguatamente i propri sistemi e implementare controlli di sicurezza più efficaci.
"Domande frequenti sull'iniezione di processo
L'iniezione di processo è un attacco in cui l'autore copia ed esegue un codice nella memoria di un processo. Ciò consente a un malintenzionato di eseguire il proprio codice nel processo di destinazione, eludendo le misure di sicurezza.
L'iniezione di processo è una tecnica utilizzata principalmente per nascondere attività e persistenza, nonché per eseguire codice con privilegi più elevati. Se la DLL di Windows viene iniettata in un altro processo attraverso processi normali, il codice eseguito eseguirà operazioni con lo stesso livello di affidabilità del processo di destinazione e avrà gli stessi diritti di accesso, rendendo più difficile per gli strumenti di sicurezza rilevare comportamenti dannosi.
Il rilevamento dell'iniezione di processo richiede il monitoraggio della memoria, dell'API e dei comportamenti dei processi. Gli analizzatori di programmi statici contrassegnano tali tentativi di iniezione cercando modelli quali allocazioni di memoria anomale, creazioni di thread e sequenze API di manipolazione dei processi anomale.
L'iniezione di processo è utilizzata principalmente dal malware, ma in alcuni scenari questa tecnica può essere utilizzata in modo legittimo, ad esempio per il debug, l'analisi del malware, le tecniche di monitoraggio e per estendere le funzionalità di un'applicazione.
Nelle campagne in stile APT (Advanced Persistent Threat), il process injection svolge un ruolo fondamentale nel garantire la persistenza ed evitare il rilevamento. Gli autori delle APT utilizzano tecniche di iniezione avanzate per ottenere l'accesso permanente ai sistemi infetti e garantire che non vengano mai scoperti durante un'operazione prolungata.
