Esecuzione di codice remoto (RCE), ha spiegato: che cosa è e come prevenirlo

Esecuzione di codice remoto (RCE) è una classe di falle di sicurezza del software/vulnerabilità. Le vulnerabilità RCE consentono a un attore malintenzionato di eseguire qualsiasi codice di propria scelta su una macchina remota tramite LAN, WAN o Internet. RCE appartiene alla più ampia classe di vulnerabilità ACE (Arbitrary Code Execution). Con Internet che diventa onnipresente, tuttavia, l’impatto delle vulnerabilità RCE cresce rapidamente. Così, RCEs sono ora probabilmente il tipo più importante di vulnerabilità ACE.

In questo caso, abbiamo voluto dare un’occhiata più dettagliata ai vari tipi di vulnerabilità RCE e alle possibili contromisure.

Classificazione RCE per origine

La maggior parte, se non tutte, delle vulnerabilità RCE note hanno un piccolo numero di cause sottostanti.

Esecuzione di codice dinamico

L’esecuzione di codice dinamico tende ad essere il vettore di attacco più comune che porta a RCE. La maggior parte dei linguaggi di programmazione ha un modo per generare codice con il codice ed eseguirlo sul posto. Questo è un concetto molto potente che aiuta a risolvere molti problemi complessi. Tuttavia, una terza parte malevola può facilmente abusarne per ottenere funzionalità RCE.

Spesso, il codice generato in fase di runtime si basa su alcuni input dell’utente. Il più delle volte, il codice include quell’input in qualche forma. Un attore dannoso, rendendosi conto che la generazione di codice dinamico farà uso di un dato input, potrebbe fornire codice valido come input per attaccare l’applicazione. Se gli input dell’utente non vengono controllati, quel codice verrà eseguito sulla macchina di destinazione.

In generale, l’esecuzione di codice dinamico causa due principali classi di vulnerabilità RCE: diretta e indiretta.

Direct

Nel caso di esecuzione diretta di codice dinamico, l’attore dannoso è consapevole del fatto che il suo input verrebbe utilizzato nella generazione del codice.

Indiretto

Un caso indiretto, ancora una volta, si riduce alla generazione di codice dinamico inclusi gli input dell’utente. L’input dell’utente, tuttavia, passa attraverso uno o più livelli. Alcuni livelli potrebbero persino trasformare quell’input prima che finisca con la generazione di codice dinamico. Inoltre, la generazione di codice dinamico potrebbe essere un effetto collaterale e non l’utilizzo primario dell’input. In quanto tale, non è molto evidente per l’utente che fornisce l’input che l’input verrà utilizzato come blocco di costruzione in uno snippet di codice da eseguire su una macchina remota.

Deserializzazione

La deserializzazione è un ottimo esempio di questo scenario. Apparentemente nessuna generazione di codice dinamico dovrebbe avvenire sulla deserializzazione. Questo è in realtà il caso in cui l’oggetto serializzato contiene solo campi di dati di tipi primitivi o altri oggetti di quel tipo. Le cose si complicano, tuttavia, quando i metodi / funzioni di un oggetto vengono serializzati. La deserializzazione quindi di solito include una qualche forma di generazione di codice dinamico.

Potresti pensare che i linguaggi dinamici siano l’unico posto in cui la serializzazione delle funzioni ha senso. Il problema sarà di portata limitata allora. Ma è anche uno scenario utile nei linguaggi statici. È un po ‘ più difficile da raggiungere in un linguaggio statico ma di gran lunga non impossibile.

Molto spesso, l’implementazione consiste in oggetti/funzioni proxy generati dalla deserializzazione. La generazione di oggetti / funzioni in fase di esecuzione è un caso di generazione di codice dinamico. Quindi, se i dati da deserializzare provengono da una richiesta fatta da una macchina remota, un attore dannoso potrebbe modificarlo. È possibile iniettare frammenti di codice serializzati con cura che ingannano la generazione di codice dinamico per eseguirli quando vengono richiamati come parte della deserializzazione.

Sicurezza della memoria

Un’altra causa di vulnerabilità RCE ha a che fare con la sicurezza della memoria. Sicurezza della memoria significa impedire al codice di accedere a parti della memoria che non ha inizializzato o ottenuto come input. Intuitivamente, ci si potrebbe aspettare una mancanza di sicurezza della memoria per provocare l’accesso non autorizzato ai dati. Tuttavia, il sistema operativo e l’hardware sottostante utilizzano la memoria per memorizzare il codice eseguibile effettivo. Anche i metadati relativi all’esecuzione del codice vengono memorizzati in memoria. Ottenere l’accesso a questo tipo di memoria potrebbe comportare ACE e possibilmente RCE. Quindi quali sono le ragioni principali dietro i problemi di sicurezza della memoria?

Difetti di progettazione software

I difetti di progettazione software sono un tipo di vulnerabilità di sicurezza della memoria in cui è presente un errore di progettazione in alcuni componenti sottostanti. Il più delle volte, che sarebbe un compilatore, interprete, o macchina virtuale, o potenzialmente il kernel del sistema operativo o librerie. Ci sono un certo numero di difetti diversi che appartengono a questa classe. Daremo uno sguardo più dettagliato a quello che è probabilmente il più comune.

Buffer overflow o buffer overread

Buffer overflow (noto anche come buffer overread) è una tecnica abbastanza semplice e ben nota per violare la sicurezza della memoria. Sfrutta un difetto di progettazione o un bug per scrivere nelle celle di memoria che seguono la fine effettiva di un buffer di memoria. Il buffer stesso viene restituito da una chiamata legittima all’API pubblica. Tuttavia, il buffer serve solo come punto di origine per calcolare gli indirizzi di memoria fisica dei valori privati di campo/membro di qualche oggetto o contatore di programma. La loro posizione relativa al buffer è ben nota o potrebbe essere indovinata. La ricerca del codice se disponibile o il debug dell’esecuzione del programma in fase di runtime potrebbero aiutare un attore dannoso a ottenere posizioni relative.

Quindi, un overflow del buffer consente di modificare la memoria che dovrebbe essere inaccessibile in base alla progettazione. Tale buffer potrebbe risiedere nello spazio degli indirizzi di un’altra macchina ed essere modificato chiamando un’API remota. Ciò consentirà l’accesso alla memoria della macchina remota. Chiaramente ci sono vari modi per utilizzare questo tipo di accesso nella strumentazione di un RCE. L’ipotesi generale è che se esiste una vulnerabilità di overflow del buffer, è possibile un RCE. Quindi, i proprietari di codice dovrebbero correggere gli overflow del buffer al più presto, ben prima che emerga l’attacco RCE effettivo.

Ambito

Più spesso, l’overflow del buffer si rivolge al codice C/C++ poiché questi linguaggi non hanno controlli di dimensione del buffer incorporati. Molti altri framework e tecnologie popolari finiscono per utilizzare le librerie C / C++ in profondità sotto la superficie che li rende automaticamente vulnerabili a questo tipo di attacco.

Nodo.js è un buon esempio di questo poiché, oltre ad essere basato su C/C++, JavaScript runtime consente anche componenti aggiuntivi nativi C/C++. Per questo motivo, un utente malintenzionato può creare con cura le richieste a un Nodo.server js per causare buffer overflow e quindi modificare la memoria di sistema sulla macchina interessata, causando l’esecuzione di codice arbitrario.

Difetti di progettazione hardware

È interessante notare che le violazioni della sicurezza della memoria possono verificarsi anche a causa di difetti di progettazione della sicurezza hardware. Mentre meno comuni e più difficili da trovare, tali vulnerabilità di solito hanno un impatto estremamente elevato.

Deviare gli attacchi RCE

Mentre il risultato di ogni attacco RCE è lo stesso in termini di un attaccante che esegue il codice, i vettori di attacco sono di natura molto diversa. Bloccare tutti richiede uno sforzo significativo. Inoltre, lo sforzo cresce insieme allo stack tecnologico. Tutti i vettori di attacco descritti in questo post sono tecnologia-agnostico. Tutte le implementazioni sono specifiche della tecnologia, però, e così sono i meccanismi di difesa.

Quindi, un approccio tradizionale per risparmiare tempo è quello di monitorare il traffico di rete per i contenuti sospetti invece di monitorare ogni endpoint con la sua tecnologia specifica. Un Web Application firewall (WAF) esegue in genere questo lavoro. Anche se ciò consente di risparmiare tempo, ha anche un prezzo: il WAF è un collo di bottiglia per le prestazioni della rete e manca di tutte le informazioni di base disponibili nell’endpoint effettivo o a livello di applicazione e utente. Quindi, l’analisi del traffico WAF non potrebbe mai essere perfetta. L’euristica è inevitabile senza dati completi, quindi non tutte le minacce emergeranno o si presenteranno falsi positivi, o più spesso entrambi.

Muoversi all’interno della app: L’approccio di Sqreen

Sqreen risolve queste carenze WAF senza aumentare il costo di sviluppo per l’utente finale spostando la visibilità all’interno dell’applicazione, portando una protezione più completa con una RASPA specifica per la tecnologia e WAF in-App. RASP e WAF di Sqreen vengono eseguiti all’interno dell’applicazione Web, dell’API o del microservizio che riceve il traffico di rete. Non richiede alcuna modifica del codice, però. Utilizza punti di strumentazione specifici per ogni tecnologia (ad esempio, API JVM per Java, API v8 per Node.js, ecc.) per modificare il codice prima dell’esecuzione in runtime. Pertanto, è in grado di monitorare e modificare gli eventi di sistema e di rete pur avendo il contesto completo di tutto ciò che accade all’interno dell’applicazione.

Pertanto, Sqreen può rilevare che l’app utilizza componenti con problemi di sicurezza della memoria noti. Può anche rilevare gli input utente effettivi che lo rendono agli eventi di esecuzione del codice dinamico. Naturalmente, questo è un approccio superiore per rilevare e prevenire RCEs rispetto a un WAF tradizionale che ha accesso solo al traffico di rete.

Avvolgendo

Chiaramente, RCE è un vettore di attacco molto potente. Ma, per fortuna, è possibile difendersi dagli attacchi RCE, anche. Le informazioni di cui sopra possono davvero aiutare a costruire la vostra strategia di difesa. Se sei interessato ad altri vettori di attacco e dettagli, consulta i nostri post precedenti su SQL injection, XXE e LFI.

Leave a Reply