Shellcode: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
Nessun oggetto della modifica
Nessun oggetto della modifica
Riga 1:
In [[informatica]] uno '''shellcode''' è un [[programma (informatica)|programma]] in linguaggio [[assembly]] che tradizionalmente esegue una [[Shell (informatica)|shell]], come la [[shell Unix]] '/bin/sh' oppure la shell [[command.com]] sui [[sistema operativo|sistemi operativi]] [[MS-DOS|DOS]] e [[Microsoft Windows]]. Uno shellcode può essere utilizzato per sfruttare un [[bug]] mediante un [[exploit]], consentendo ad un [[hacker]] o un [[Cracker (informatica)|cracker]] di acquisire l'accesso alla [[riga di comando]] di un [[computer]], o più in generale di eseguire [[codice sorgente|codice]] arbitrario.
 
==Descrizione==
=== Tipi di shellcode ===
 
Esistono due diversi tipi di shellcode, locale e remoto. La distinzione dipende dal tipo di controllo che l'esecuzione dello shellcode fornisce sulla macchina bersaglio, che può essere locale o remoto (se avviene attraverso la rete).
 
==== Locale ====
 
Uno shellcode locale è utilizzato da un attaccante che possiede un accesso limitato alla macchina, ma che sfruttando una vulnerabilità di un processo con privilegi più elevati, per esempio un buffer overflow, può ottenerne gli stessi privilegi se l'esecuzione della shellcode va a buon fine.
 
==== Remoto ====
 
Lo shellcode remoto è invece utilizzato quando un attaccante vuole sfruttare una vulnerabilità di un processo di un'altra macchina sulla rete locale o su una rete intranet. Se lo Shellcode è eseguito correttamente, questo ritorna il controllo della macchina bersaglio attraverso la rete. Gli shellcode remoti utilizzano normalmente lo standard socket [[TCP/IP]] per consentire l'accesso alla shell della macchina bersaglio.
Riga 19 ⟶ 20:
Il firewall può fornire una protezione aggiuntiva contro un attaccante, anche se il sistema è vulnerabile, impedendo in maniera preventiva di ottenere l'accesso alla shell creata dall'esecuzione dello shellcode. Questa è una delle ragioni del perché a volte viene utilizzata una socket re-using shellcode, perché non creando nuove connessioni risulta più difficile da identificare e bloccare.
 
==== Download and execute ====
 
Download and execute è un tipo di shellcode remoto che effettua un [[download]] ed esegue una qualche forma di malware sul sistema bersaglio. Questo tipo di shellcode non crea una shell, ma istruisce la macchina di scaricare un certo file eseguibile dalla rete, salvarlo su disco e poi eseguirlo. Al giorno d'oggi, è comunemente utilizzato negli attacchi [[drive-by download]], quando una vittima visita un sito malevolo che cerca di avviare un download e di eseguire una shellcode per installare software sulla macchina vittima. Una variazione di questo tipo di shellcode è “download and loads a library”.<ref>{{Cita web|url=http://skypher.com/index.php/2010/01/11/download-and-loadlibrary-shellcode-released/
Riga 27 ⟶ 28:
|cognome=SkyLined |data=11 gennaio 2010 |accesso=19 gennaio 2010 }}</ref> I vantaggi di questa tecnica è che il codice dello shellcode può essere più piccolo, non richiede la creazione un nuovo processo sulla macchina bersaglio e che lo shellcode non ha bisogno di implementare il codice per la pulizia del processo bersagliato, ma questo può essere effettuato da una libreria caricata all'interno del processo.
 
==== Staged ====
 
Quando la quantità di dati che un attaccante può iniettare in un processo bersaglio è troppo limitata per una corretta esecuzione dello shellcode, è possibile eseguirlo in più fasi. Prima, un piccolo pezzo di shellcode (fase 1) viene eseguita. Questo codice scarica una fetta più grande dello shellcode (fase 2) nella memoria del processo e lo manda in esecuzione.
 
==== Egg-hunt ====
 
Egg-hunt è un altro tipo di shellcode a fasi. Viene utilizzato quando un attaccante ha la possibilità di inserire uno shellcode grande in un processo, ma non può determinare in che posizione della memoria verrà inserito. Quindi viene inserito nel processo un piccolo egg-hunt in una locazione predicibile e poi eseguito. Il codice cerca lo spazio di memoria per un shellcode più grande (the egg) e lo esegue.
 
==== Omelette ====
 
Questo tipo di shellcode è simile al egg-hunt, ma effettua una ricerca di più piccoli blocchi (eggs) ricombinandoli in uno più grande (omelette) che viene eseguito successivamente.
Riga 42 ⟶ 43:
|cognome=SkyLined |editore=Skypher.com |data=16 marzo 2009 |accesso=19 marzo 2009 }}</ref>
 
===Funzionamento===
==== Strategia di esecuzione di uno Shellcode ====
 
Un exploit comunemente inserisce uno shellcode all'interno del processo bersaglio prima o nello stesso istante in cui si verifica un exploit di una vulnerabilità, per ottenere il controllo sul [[program counter]]. Il program counter vieni indirizzato per puntare allo shellcode da mandare in esecuzione.
L'inserimento dello shellcode è spesso fatta immagazzinando il codice nei dati inviati sulla rete al processo vulnerabile, rendendolo disponibile in un file che viene letto dal processo o attraverso la riga di comando o variabili di ambiente nel caso si tratti di exploit locali.
 
==== Shellcode encoding ====
 
Dato che molti processi filtrano o limitano i dati che possono essere inseriti, spesso lo shellcode deve essere scritto per superare queste restrizioni, rendendo il codice piccolo, privo di [[null]] o caratteri alfanumerici. Sono state trovate diverse soluzioni per aggirare queste restrizioni:
Riga 55 ⟶ 57:
Da quando gli strumenti di [[intrusion detection system|intrusion detection]] possono identificare la firma di semplici shellcode inviati attraverso la rete, questi vengono codificati e resi self-decrypting o [[virus polimorfo|polimorfici]] per evitare di essere riconosciuti.
 
===== Percent encoding =====
Gli exploit che hanno come obiettivo i browser, codificano comunemente lo shellcode in una stringa JavaScript usando la notazione di [[percent-encoding]] o URL-encoding, tramite caratteri di escape “\uXXXX” o mediante [[entity]]. Alcuni exploit fanno un'ulteriore offuscamento dello shellcode codificato tramite stringhe per evitare di essere rilevati da strumenti di [[intrusion detection system|IDS]].
Per esempio, sul una architettura [[IA-32]], due istruzioni di <code>[[NOP]]</code> (no-operation) prima di essere codificate hanno questa forma.
Riga 70 ⟶ 72:
"&amp;#37008;"
 
==== Shellcode Null-Free ====
Molti shellcode vengono scritti senza utilizzare il bytes [[null]], perché sono progettati per essere inseriti nel processo bersaglio attraverso un stringa null-terminata. Quando una stringa null-terminata viene copiata, la copia includerà il primo carattere null, ma i bytes successivi a questo non verranno processati. Quando lo shellcode che contiene il null viene inserito in questa maniera, verrà inserita solo una parte dello shellcode non rendendolo in grado di eseguire successivamente.
Per produrre uno shellcode libero da [[null]] partendo da uno che contiene dei bytes null, possono essere sostituite le istruzioni macchina che contengono gli zeri con istruzioni che producono lo stesso effetto ma che sono prive di bytes null. Per esempio su una architettura [[IA-32]] si potrebbe eseguire questa sostituzione:
Riga 79 ⟶ 81:
che hanno lo stesso effetto ma richiedono meno bytes per la codifica e sono prive di bytes a null.
 
==== Shellcode alfanumerici e stampabili ====
In certe circostanze, un processo bersaglio potrebbe filtrare tutti i bytes provenienti dallo shellcode inserito che non sono stampabili o alfanumerici. In queste condizioni, il range di istruzioni che possono essere utilizzate per scrivere uno shellcode diventano molto limitate. Una soluzione a questo problema è stata pubblicata da Rix in [[Phrack]] 57<ref>{{Cita web|url=http://www.phrack.org/issues.html?issue=57&id=15#article |cognome=Rix
|titolo=Writing ia32 alphanumeric shellcodes
Riga 86 ⟶ 88:
|data=November 2009 |accesso=10 gennaio 2010 }}</ref>
 
==== Shellcode a prova di caratteri Unicode ====
 
Molti programmi moderni utilizzano la codifica di stringhe in formato Unicode per permettere l'internalizzazione del testo. Spesso questi programmi convertono le stringhe ASCII in ingresso prima di processarle. Le stringhe Unicode codificate in [[UTF-16]] utilizzano due byte per decodificare ogni carattere ( o quattro bytes per alcuni caratteri speciali). Quando una stringa [[ASCII]] viene convertita in UTF-16, un byte a zero viene inserito dopo ogni bytes della stringa originale. Obscu ha mostrato in [[Phrack]] 61<ref>{{Cita web|url=http://www.phrack.org/issues.html?issue=61&id=11#article |cognome=Obscou
Riga 92 ⟶ 94:
|editore=Phrack |data=13 agosto 2003 |accesso=29 febbraio 2008 }}</ref> che è possibile scrivere shellcode che possono eseguire correttamente anche dopo questa trasformazione. Esistono programmi in grado di modificare automaticamente ogni shellcode in uno codificato mediante UTF-16 e sono basati sullo stesso principio di un decoder automodificante che decodifica lo shellcode originale.
 
=== Piattaforme ===
 
Molti shellcode sono scritti in codice macchina a causa del basso livello a cui la vulnerabilità diventa sfruttabile. Lo shellcode è spesso creato per attaccare una specifica combinazione di processore, sistema operativo e service pack, che vengono chiamati comunemente piattaforma. Per alcuni exploit, a causa dei vincoli imposti dal processo bersaglio, è necessario creare uno shellcode specifico. In ogni caso non è sempre possibile per uno shellocde lavorare per exploit multipli, service pack, sistemi operativi e eventualmente processori.<ref>{{Cita web|url=http://www.phrack.org/issues.html?issue=57&id=14#article |cognome=Eugene