Un
buffer è un blocco contiguo di memoria utilizzato in maniera temporanea per
contenere più istanze dello stesso tipo di dati. Quasi tutti i programmi che
usiamo normalmente hanno bisogno di un consistente quantitativo di memoria
temporanea: ad esempio, quando il nostro browser instaura delle connessioni, i
relativi dati sono temporaneamente collocati nei buffer prima di essere elaborati.
Questi buffer solitamente hanno una dimensione
fissa, definita alla creazione del programma o, in alcuni casi, dipendente
dalle varie configurazioni. Ma cosa succede se l'input è più grande del buffer?
Ovvero se i dati sono troppi? Normalmente il risultato è imprevedibile: può non
accadere nulla, il programma può smettere di funzionare e aver bisogno di
essere riavviato o altre conseguenze più o meno dannose per il sistema.
Cos'è successo? Semplice, i dati in
eccesso hanno sovrascritto delle aree di memoria che non erano necessariamente
vuote; i dati ora presenti in queste aree non sono più validi e quindi possono
condurre a vari problemi. Questi aspetti, dal punto di vista della sicurezza,
hanno due conseguenze strettamente collegate:
- attacchi di tipo DoS (Denial of Service);
- esecuzione di codice remoto.
Nel primo caso l'obiettivo dell'attacco è
semplicemente quello di bloccare il software colpito da buffer overflow, quindi
l’attacco è costruito in maniera tale da causare un crash dell’applicazione
“vittima”. Spesso il programma attaccato è parte del sistema operativo, quindi
è facile immaginare sul piano pratico le conseguenze dell’attacco.
Nel secondo caso l'azione è molto più
grave: i dati di overflow sono costruiti accuratamente in modo da portare
all'esecuzione di codice non previsto dal programma, come ad esempio l'apertura
di una shell remota. Tale codice comprende una serie di "trucchi" e
meccanismi creati con l'obiettivo di permettere ad un eventuale intruso di
prendere il controllo della macchina, scavalcando le altre eventuali misure di
sicurezza.
Lo scopo complessivo di un attacco di
buffer overflow è di sovvertire le funzioni di un programma in modo che
l'attaccante possa prenderne il controllo, e, se esso è
sufficientemente privilegiato, anche dell'host stesso. Tipicamente l'attaccante
sceglie come "vittima" programmi di root e immediatamente esegue
codice simile ad exec(sh) per ottenere una shell con i privilegi di root
Per ottenere questo risultato l'attaccante
deve:
1.
Predisporre il codice “malizioso” da eseguire nello spazio d'indirizzamento del
programma vittima.
2.
Permettere al programma di saltare a quel codice, con parametri esatti,
caricati nei registri e nella memoria.
In sostanza, i vari metodi d’attacco
tramite buffer overflow tendono ad alterare il controllo del flusso del programma
in modo da permettergli di saltare al codice
d'attacco. Il metodo base è di far traboccare un buffer che ha un debole o
inesistente controllo sul limite dei suoi input, con il risultato di sovrascrivere,
con un'opportuna sequenza di byte, una parte adiacente allo stato del programma.
Pagina precedente | Torna in cima | Pagina successiva