Buffer overflow: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
Nessun oggetto della modifica
Morenocalle (discussione | contributi)
Funzionalità collegamenti suggeriti: 3 collegamenti inseriti.
Etichette: Modifica visuale Modifica da mobile Modifica da web per mobile Modifica da mobile avanzata Attività per i nuovi utenti Suggerito: aggiungi collegamenti
 
(167 versioni intermedie di 96 utenti non mostrate)
Riga 1:
{{Nota disambigua|il buffer overflow legato alle telecomunicazioni|Buffer overflow (telecomunicazioni)}}
{{stub informatica}}
 
[[File:Buffer overflow basicexample.svg|alt=Esempio di buffer overflow|miniatura|Esempio di buffer overflow|300x300px]]
Il '''buffer overflow''' è un problema che può affliggere un [[programma]] software. Consiste nel fornire al programma più dati di quanto esso si aspetti di ricevere, facendo in modo che una parte di questi dati vadano scritti in zone di memoria dove sono, o dovrebbero essere, altri dati o lo [[stack]] del programma stesso. Come conseguenza di ciò, a seconda di cosa è stato sovrascritto e con quali valori, il programma può dare risultati errati o imprevedibili, bloccarsi, o (se è un driver di sistema o lo stesso sistema operativo) bloccare il [[computer]]. Questo tipo di debolezza dei programmi è noto da molto tempo, ma solo di recente la sua conoscenza si è diffusa tanto da permettere anche a degli [[hacker]] dilettanti di sfruttarla per bloccare o prendere il controllo di altri computer collegati in rete.
'''Buffer overflow''' (o '''buffer overrun'''), in [[informatica]], è una condizione di errore che si verifica a [[runtime]] quando in un [[buffer]] di una data dimensione vengono scritti dati di dimensioni maggiori.
 
== Storia ==
Un caso del genere si può verificare quando il programma non controlla in anticipo la lunghezza dei dati in arrivo, ma si limita a scrivere il loro valore in un [[buffer]] di lunghezza prestabilita, confidando che l'utente (o il mittente) non immetta più dati di quanti esso ne possa contenere. Se invece, per errore o per calcolo, vengono inviati più dati della capienza del buffer destinato a contenerli, i dati ''extra'' vanno a sovrascrivere le variabili interne del programma, o il suo stesso stack. Conoscendo molto bene il programma in questione e il tipo di macchina su cui gira, si può precalcolare una serie di dati ''malevoli'' che inviata per provocare un buffer overflow consenta a un malintenzionato di prendere il controllo del programma, e tramite questo dell'intero computer.
I buffer overflow divennero noti e furono parzialmente documentati al pubblico già nel 1972, quando il Computer Security Technology Planning Study individuò un exploit capace di sfruttare la vulnerabilità: "The code performing this function does not check the source and destination addresses properly, permitting portions of the monitor to be overlaid by the user. This can be used to inject code into the monitor that will permit the user to seize control of the machine.", dove per ''monitor'' si intendeva quello che oggi è il [[kernel]].<ref>{{Cita web|url=http://csrc.nist.gov/publications/history/ande72.pdf|titolo="Computer Security Technology Planning Study" - Pag. 61|accesso=5 settembre 2016|urlarchivio=https://web.archive.org/web/20110721060319/http://csrc.nist.gov/publications/history/ande72.pdf|dataarchivio=21 luglio 2011|urlmorto=sì}}</ref>
 
Il primo clamoroso esempio di attacco basato su buffer overflow fu il [[Morris worm|Morris Worm]] (noto anche come Internet Worm), che nel 1988 portò al crash di più di 6.000 sistemi connessi a Internet in poche ore, sfruttando il buffer overflow nel processo demone ''finger'' di UNIX per propagare attraverso la rete.<ref>{{Cita web|url=https://www.sans.org/reading-room/whitepapers/securecode/buffer-overflow-attack-mechanism-method-prevention-386|titolo=Inside the Buffer Overflow Attack:Mechanism, Method, & Prevention}}</ref>
Non tutti i programmi sono vulnerabili a questo tipo di inconveniente: perchè un dato programma sia a rischio è necessario che:
# il programma preveda l'input di dati di lunghezza variabile e non nota a priori;
# che li immagazzini entro [[buffer]] allocati nel suo spazio di memoria dati vicini ad altre strutture dati vitali per il programma stesso;
# che il programmatore non abbia implementato alcun mezzo di controllo della correttezza dell'input in corso.
 
Più tardi, nel 1995, Thomas Lopatic pubblicò sulla [[mailing list]] di Bugtraq un exploit basato sullo stack smashing nel web server NCSA HTTPD su sistema operativo [[HP-UX]], e un anno dopo, nel 1996, Elias Levy (anche noto come Aleph One) pubblicò un articolo intitolato "Smashing the Stack for Fun and Profit" sull'''ezine'' [[Phrack]], una guida step-by-step alle tecniche di exploiting degli stack buffer overflows.<ref>{{Cita web|url=https://rdist.root.org/2010/05/03/why-buffer-overflow-exploitation-took-so-long-to-mature/|titolo=Why buffer overflow exploitation took so long to mature|sito=rdist|data=3 maggio 2010|accesso=5 settembre 2016}}</ref><ref>{{Cita web|url=http://seclists.org/bugtraq/1995/Feb/109|titolo=Bugtraq: Vulnerability in NCSA HTTPD 1.3|cognome=Lopatic|nome=Thomas|sito=seclists.org|accesso=5 settembre 2016}}</ref>
La prima condizione è facilmente verificabile, dalle specifiche del programma; le altre due invece sono interne ad esso e riguardano la sua [[programma completo|completezza]] in senso teorico.
 
In seguito i buffer overflow furono sfruttati da due importanti ''internet worm'': nel 2001 il [[Code Red (malware)|Code Red worm]], che sfruttava il buffer overflow nei server [[Internet Information Services|Microsoft Internet Information Services]] (IIS) 5.0<ref>{{Cita web|url=https://www.sans.org/reading-room/whitepapers/malicious/code-red-worm-45|titolo=What is Code Red Worm?}}</ref>, e nel 2003 l'[[SQL Slammer]] worm, che compromise le macchine che eseguivano [[Microsoft SQL Server|Microsoft SQL Server 2000]].<ref>{{Cita web|url=http://pen-testing.sans.org/resources/papers/gcih/sql-slammer-worm-101033|titolo=SQL Slammer worm|accesso=5 settembre 2016|dataarchivio=13 settembre 2016|urlarchivio=https://web.archive.org/web/20160913082805/http://pen-testing.sans.org/resources/papers/gcih/sql-slammer-worm-101033|urlmorto=sì}}</ref>
=Stack overflow=
Lo ''stack overflow'', come il buffer overflow, consiste nella sovrascrittura dell'area dati del programma, ma questa volta non è causata da un input di dati troppo lungo ma dall'attività del programma stesso: chiamando con dei parametri particolari una funzione [[ricorsione (informatica)|ricorsiva]] del programma, questa accumula chiamate in sospeso sullo stack fino a riempirlo completamente e inizia a sovrascrivere la memoria adiacente.
 
Nonostante sia una delle vulnerabilità note da più tempo, ancora oggi il buffer overflow rappresenta una falla di sicurezza diffusa ed estremamente attuale: organizzazioni come [[CERT|CERT/CC]] e [[SANS]] pubblicano ancora oggi avvisi relativi alla sicurezza informatica che includono un numero rilevante di exploit basati su buffer overflow; inoltre diversi elementi della lista “CWE/SANS Top 25 Most Dangerous Software Error” sono varianti del buffer overflow.<ref>{{Cita web|url=https://cwe.mitre.org/top25/|titolo=CWE -
----
2011 CWE/SANS Top 25 Most Dangerous Software Errors|sito=cwe.mitre.org|accesso=17 agosto 2016}}</ref>
[http://www.phrack.org/show.php?p=49&a=14 Smashing the stack for fun and profit] apparso nella [[ezine]] Phrack dell'11 agosto [[1996]].
 
Nel febbraio 2016 i ricercatori di Google e di Red Hat scoprirono la presenza di una vulnerabilità di tipo stack buffer overflow nella funzione ''getaddrinfo'' della libreria ''[[glibc]]'' (tutte le versioni a partire dalla 2.9). Tale libreria è utilizzata da centinaia di applicazioni e dalla maggior parte delle distribuzioni Linux (incluse quelle installate nei [[router]] e in altro tipo di hardware): la funzione interessata è quella che si occupa del DNS lookup (risoluzione nomi degli host e indirizzi IP) e la vulnerabilità può permettere a un attaccante l'invio di domini o DNS server malevoli, oltre che attacchi ''[[Attacco man in the middle|man-in-the-middle]]'' fino all'esecuzione di codice arbitrario sulla macchina della vittima.<ref>{{Cita web|url=https://security.googleblog.com/2016/02/cve-2015-7547-glibc-getaddrinfo-stack.html|titolo=CVE-2015-7547: glibc getaddrinfo stack-based buffer overflow|lingua=en|accesso=6 settembre 2016}}</ref><ref>{{Cita web|url=https://access.redhat.com/it/node/2171131|titolo=Falla di sicurezza critica: glibc stack-based buffer overflow in getaddrinfo() (CVE-2015-7547) - Red Hat Customer Portal|sito=access.redhat.com|accesso=6 settembre 2016}}</ref>
[[categoria:informatica]]
 
[[Categoria:sicurezza informatica]]
== Descrizione ==
Quando, per errore o per malizia, vengono inviati più dati della capienza del buffer destinato a contenerli (che per errore, malizia o superficialità non è stato progettato a dovere), i dati ''extra'' vanno a sovrascrivere le variabili interne del programma, o il suo stesso [[Pila (informatica)|stack]]; come conseguenza di ciò, a seconda di cosa è stato sovrascritto e con quali valori, il programma può dare risultati errati o imprevedibili, bloccarsi, o (se è un driver di sistema o lo stesso sistema operativo) bloccare il [[computer]]. Conoscendo molto bene il programma in questione, il sistema operativo e il tipo di computer su cui gira, si può precalcolare una serie di dati ''malevoli'' che inviati per provocare un buffer overflow consenta ad un malintenzionato di prendere il controllo del programma (e a volte, tramite questo, dell'intero computer).
 
Non tutti i programmi sono vulnerabili a questo tipo di inconveniente. Per i linguaggi di basso livello, come l’assembly, i dati sono semplici array di byte, memorizzati in registri o in memoria centrale: la corretta interpretazione di questi dati (indirizzi, interi, caratteri, istruzioni, ecc…) è affidata alle funzioni e alle istruzioni che li accedono e manipolano; utilizzando linguaggi di basso livello si ha dunque un maggiore controllo delle risorse della macchina, ma è richiesta una maggiore attenzione in fase di programmazione in modo da assicurare l’[[integrità dei dati]] (e quindi evitare fenomeni come il buffer overflow). I linguaggi di più alto livello, come Java e Python (e molti altri), che definiscono invece il concetto di tipo di una variabile e che definiscono un insieme di operazioni permesse a seconda del tipo, non soffrono di vulnerabilità come il buffer overflow, perché non consentono di memorizzare in un buffer una quantità maggiore di dati rispetto alla sua dimensione. Fra questi due estremi si trova il linguaggio C che presenta alcune delle astrazioni tipiche dei linguaggi di alto livello insieme a elementi tipici dei linguaggi di basso livello, come la possibilità di accedere e manipolare indirizzi di memoria: ciò rende il linguaggio suscettibile ad usi inappropriati della memoria; se a questo si unisce il fatto che alcune librerie di funzioni molto diffuse (in particolare per l’input e la manipolazione di stringhe come la ''gets'') non effettuano un corretto controllo della dimensione dei buffer su cui lavorano, e che il C è stato usato negli anni ’70 per scrivere il sistema operativo UNIX (e da questo sono poi derivati i sistemi come Linux) e molte delle applicazioni pensate per eseguire su di esso, ne consegue che ancora oggi è presente e circola una grande quantità di codice vulnerabile al buffer overflow.<ref name=":0">{{Cita libro|autore=William Stallings, Lawrie Brown|titolo=Computer Security - Principles and Practice|anno=2015|editore=Pearson|città=|ISBN=978-0-13-377392-7}}</ref>
 
Non tutti i programmi sono vulnerabili a questo tipo di inconveniente, infatti perché un dato programma sia a rischio è necessario che:
* Il programma preveda l'input di dati di dimensione variabile e li memorizzi all'interno di un buffer;
* Il linguaggio di programmazione utilizzato non preveda controlli automatici di ''bounds checking'' del buffer (a tempo di compilazione o a tempo di esecuzione), e il programmatore non inserisca tali verifiche all'interno del codice.
 
== Conseguenze ==
Quando questo accade viene sovrascritta parte della zona di memoria immediatamente adiacente al buffer in questione, con diversi effetti possibili a seconda di dove è situato il buffer e di come è organizzata la memoria in quella particolare piattaforma software; in alcuni [[Programma (informatica)|programmi]] software questo provoca delle vulnerabilità di [[sicurezza informatica|sicurezza]]. I linguaggi ''managed'', cioè basati su un modello di memoria gestito a runtime come Java, dovrebbero in teoria essere immuni da questo tipo di errore, ma in pratica la possibilità rimane presente in caso di chiamate a codice nativo, o a causa di bug del modulo manager (la JVM nel caso di Java) o del compilatore JIT.
 
Il buffer overflow può essere indicato con diversi nomi a seconda della posizione occupata dal buffer all’interno della memoria allocata per il processo. La posizione del buffer è importante in quanto gli effetti del buffer overflow sono principalmente legati a:
* cosa c’è vicino al buffer
* quali dati vanno a sovrascrivere le aree di memoria adiacenti al buffer
 
== Vulnerabilità ==
=== Memoria virtuale di un processo ===
Quando viene eseguito un programma il sistema operativo normalmente genera un nuovo processo e alloca in memoria centrale uno spazio di memoria virtuale riservato al processo stesso.
 
Questo spazio di memoria in generale ha una struttura data da (partendo dall’alto verso il basso):
* Kernel
* [[pila (informatica)|Stack]] (cresce verso il basso)
* Memoria libera
* [[Heap (struttura dati)|Heap]] (cresce verso l’alto)
* Dati globali
* Codice del programma
L’esecuzione del programma consiste a sua volta di diverse chiamate a funzioni: ciascuna chiamata genera uno stack frame all’interno dello stack (che man mano cresce verso il basso nella struttura descritta sopra, con politica [[LIFO]]); all’interno del frame la funzione chiamata memorizza le variabili locali, l’indirizzo dell’istruzione della funzione chiamante a cui dovrà restituire il controllo (return address) e il puntatore al frame della funzione chiamante; questi ultimi due in particolare giocano un ruolo fondamentale nell’assicurare il giusto flusso di esecuzione al programma fra una chiamata di funzione e l’altra, infatti:
* Il return address dice alla funzione chiamata a quale istruzione della funzione chiamante bisogna restituire il controllo;
* Il puntatore al frame della funzione chiamante consente di ripristinare il suo contesto di esecuzione prima di restituirle il controllo;
Lo stack cresce verso il basso ad ogni chiamata di funzione, e ciascun frame generato presenta dunque una struttura del tipo (sempre dall’alto verso il basso):
{| class="wikitable"
|Return address
|-
|Puntatore al frame della funzione chiamante
|-
|Variabile locale 1
|-
|Variabile locale 2
|-
|...
|}
<ref name=":0" />
 
=== Stack buffer overflow ===
Quando il buffer è allocato nello stack, ovvero è una variabile locale di una funzione, l’eventuale immissione all’interno del buffer di una quantità di dati superiore alla sua portata prende il nome di '''stack buffer overflow''' (o '''stack smashing''', o '''stack-based buffer overflow''').
 
In questo caso i dati adiacenti al buffer che potrebbero essere sovrascritti dai dati ''extra'' sono il return address e il frame pointer.
 
Se i dati in eccesso sovrascrivono frame pointer e return address, al termine dell’esecuzione la funzione tenterebbe di restituire il controllo all’istruzione puntata dal return address che potrebbe contenere:
* L’indirizzo di un’area di memoria non accessibile: i dati in eccesso sono casuali, il programma va in crash restituendo tipicamente un [[errore di segmentazione]]. È un esempio di come lo ''stack buffer overflow'' possa essere utilizzato come attacco del tipo [[Denial of Service|denial of service]] (DoS), compromettendo la disponibilità del servizio colpito.
* Un indirizzo di memoria ben preciso: i dati in eccesso sono calcolati in modo da sovrascrivere il return address con l’indirizzo di un’area di memoria a cui l’attaccante vuole avere accesso, o con l’indirizzo in cui si trova il codice che l’attaccante vuole eseguire.
In questo secondo caso rientrano gli attacchi basati sull’iniezione di [[shellcode]]; i dati inseriti all’interno del buffer contengono codice eseguibile in linguaggio macchina ([[assembly]]), e la sovrascrittura del return address viene fatta in modo da rimandare al codice iniettato all’interno del buffer. Compito di tale codice è normalmente quello di richiamare un’interfaccia a riga di comando, ovvero una [[Shell (informatica)|shell]], motivo per cui tale codice è detto shellcode (una chiamata alla funzione ''execve'' che esegue la Bourne shell per i sistemi UNIX, una chiamata a ''system (“command.exe”)'' nei sistemi Windows). In ogni caso il programma in esecuzione viene sostituito dalla shell, che eseguirà con gli stessi privilegi del programma di partenza.
 
Esiste una variante di questo tipo di attacco che si basa sulla sostituzione solo del frame pointer, e che può essere utilizzata quando l'overflow consentito è limitato e non permette di arrivare alla sovrascrittura del return address. L'attacco consiste nello sfruttare l'overflow per sostituire il frame pointer memorizzato in modo da farlo puntare a uno stack frame fasullo, iniettato all'interno del buffer insieme allo shellcode; in questo ''stack frame'' fasullo l'attaccante ha inserito come return address un puntatore allo shellcode: quando la funzione colpita termina la sua esecuzione, quindi, restituisce correttamente il controllo alla funzione chiamante (il return address infatti non è stato cambiato), ma questa riprenderà l'esecuzione con un contesto fasullo e, quando a sua volta anche lei terminerà di eseguire, il controllo verrà infine trasferito allo shellcode (poiché in questo stack frame è stato alterato il RA in modo da puntare al codice maligno). Gli attacchi [[Off-by-one error|off-by-one]] si basano proprio su questo principio: se per un errore di scrittura il programmatore consente l'immissione all'interno di un buffer anche solo di un byte in più del dovuto (usando ad esempio un <= invece del ''<'' nel test di una condizione di controllo), questo semplice byte in più potrebbe essere utilizzato da un attaccante per modificare il frame pointer memorizzato a sufficienza da farlo puntare ad uno stack frame fasullo, e ottenere quindi indirettamente il trasferimento del controllo al codice maligno iniettato.<ref name=":0" />
 
Infine bisogna ricordare che [[stack overflow]] e stack buffer overflow non sono sinonimi: il primo indica una situazione per cui si richiede una quantità troppo elevata di memoria nello stack, il secondo una situazione in cui (per varie ragioni) si inserisce in un buffer nello stack una quantità di dati più grande della capacità del buffer stesso.<ref>{{Cita libro|autore=Jon Erickson|titolo=Hacking - The Art of Exploitation|url=https://archive.org/details/hackingartofexpl0000eric_g6n4|anno=2008|editore=No Starch Press|città=|ISBN=978-1-59327-144-2}}</ref>
 
=== Heap overflow ===
{{Vedi anche|Heap overflow}}
Un programma può richiedere al sistema operativo di allocare dinamicamente una certa quantità di memoria nell'area [[Heap (struttura dati)|heap]], sfruttando chiamate di sistema come ''malloc()'' e ''free''() in C/UNIX. Questi buffer possono ugualmente essere suscettibili a problemi di overflow nel momento in cui vi si possa inserire una quantità di dati superiore alla memoria allocata, e questi dati andrebbero come al solito a sovrascrivere le aree di memoria adiacenti al buffer.
 
Si parla in questi casi di '''heap overflow''', ma a differenza dello stack, nell'area heap non sono memorizzati né indirizzi di ritorno, né frame pointer che possano essere alterati da un attaccante per trasferire il controllo dell'esecuzione a codice arbitrario. Tuttavia questo non significa che tali anomalie non costituiscano delle vulnerabilità pericolose: nel 2002 fu riscontrata una vulnerabilità di tipo heap overflow in un'estensione di Microsoft IIS che poteva essere sfruttata per eseguire codice arbitrario proprio su questo tipo di server.<ref>{{Cita web|url=https://www.kb.cert.org/vuls/id/363715|titolo=Vulnerability Note VU#363715 - Microsoft Internet Information Server (IIS) vulnerable to heap overflow during processing of crafted ".htr" request by "ISM.DLL" ISAPI filter|accesso=19 agosto 2016}}</ref>
 
Quando un programma presenta diverse funzioni che eseguono la stessa operazione ma in modo diverso (ad esempio il ''sorting''), e si desidera stabilire a ''runtime'' quale utilizzare per processare i dati in ingresso, spesso si usa memorizzare dei puntatori a funzione nell'area heap: questi puntatori contengono gli indirizzi iniziali delle funzioni, e vengono utilizzati per richiamarne successivamente l'esecuzione. In uno scenario del genere, un attaccante potrebbe sfruttare l'overflow di un buffer allocato sullo heap per sovrascrivere tali puntatori, sostituendoli con un puntatore allo shellcode iniettato attraverso l'overflow: la successiva chiamata a una delle funzioni comporterebbe il trasferimento del controllo allo shellcode invece che alla funzione attesa.<ref>{{Cita web|url=https://www.sans.org/reading-room/whitepapers/threats/buffer-overflows-dummies-481|titolo=Buffer Overflows for Dummies - SANS Institute}}</ref>
 
== Contromisure ==
Esistono varie tecniche per prevenire o rivelare il fenomeno del buffer overflow, con vari tradeoff. In generale queste difese possono essere adottate a vari livelli:<ref name=":1">{{Cita web|url=http://www.preserve-it-all.org/emc-plus/rsa-labs/historical/countermeasures-against-buffer-overflow-attacks.htm|titolo=RSA Laboratories - Countermeasures against Buffer Overflow Attacks|accesso=31 agosto 2016|dataarchivio=14 settembre 2016|urlarchivio=https://web.archive.org/web/20160914092946/http://www.preserve-it-all.org/emc-plus/rsa-labs/historical/countermeasures-against-buffer-overflow-attacks.htm|urlmorto=sì}}</ref>
* A livello di linguaggio
* A livello di codice sorgente
* A livello di compilatore
* A livello di sistema operativo
 
=== Difese a livello di linguaggio ===
La miglior difesa da attacchi basati sul buffer overflow sta nella scelta di un linguaggio di programmazione che fornisca controlli automatici sulla dimensione dei buffer (o a tempo di compilazione o a ''runtime'') come Java, Python o Perl. Se questa opzione può essere presa in considerazione per lo sviluppo di nuovi programmi, resta però difficilmente applicabile nel caso di progetti esistenti, in cui ciò comporterebbe la riscrittura del codice nel nuovo linguaggio.<ref name=":1" />
 
Un'alternativa consiste nell'utilizzo di ''safe library'', ovvero librerie di funzioni che implementano protezioni contro il buffer overflow: in C rappresentano funzioni vulnerabili ''strcat'', ''strcpy'', ''gets'', ''sprintf'' (e altre ancora...) di cui esistono controparti "sicure" come ''strncpy'', ''strncat'', ''snprintf''. Un esempio di queste ''safe library'' sono "libsafe", "libparanoia" e "libverify".<ref>{{Cita web|url=https://www.freebsd.org/doc/en/books/developers-handbook/secure-bufferov.html|titolo=3.3. Buffer Overflows|accesso=31 agosto 2016}}</ref> Libsafe, ad esempio, implementa una tecnica di protezione dallo stack buffer overflow basata sul controllo di eventuali alterazioni dello stack quando una funzione termina di eseguire: se lo stack risulta modificato, il processo termina con un [[errore di segmentazione]].<ref>{{Cita web|url=https://directory.fsf.org/wiki/Libsafe|titolo=Libsafe - Free Software Directory|sito=directory.fsf.org|accesso=4 settembre 2016}}</ref>
 
=== Difese a livello di codice sorgente ===
Esistono tool in grado di rilevare vulnerabilità al buffer overflow all'interno del codice sorgente effettuando analisi più o meno complesse sullo stesso, sia statiche che dinamiche.
 
"Its4" è un semplicissimo esempio di analizzatore statico che effettua la ricerca di eventuali chiamate di funzioni vulnerabili note (come ''strcpy'' o ''popen''), pensato come sostituzione alla ricerca tramite ''grep'': data la sua semplicità e la rudimentale analisi del codice che realizza è molto facile incappare in falsi positivi e negativi.<ref>{{Cita web|url=http://seclab.cs.ucdavis.edu/projects/testing/tools/its4.html|titolo=Its4}}</ref>
 
In alternativa esistono tool più complessi in grado di effettuare l'analisi dinamica del programma, come "Rational Purify", un debugger di memoria realizzato da IBM in grado di individuare eventuali anomalie nella gestione della memoria durante l'esecuzione del programma (accesso a variabili non inizializzate, ''buffer overflow'', deallocazione impropria di memoria, ecc...).<ref>{{Cita web|url=https://www-01.ibm.com/software/awdtools/purify/compare.html|titolo=Rational Purify}}</ref>
 
=== Difese a livello di compilatore ===
Linguaggi di medio/basso livello come il C forniscono alte prestazioni proprio perché "risparmiano" su certi controlli che non vengono automaticamente gestiti a livello di linguaggio lasciando tale responsabilità al programmatore, e gettando dunque le basi a vulnerabilità come il buffer overflow in caso di mancanza dei controlli sulle dimensioni dei buffer durante gli accessi.
 
Una delle tecniche di difesa da queste anomalie è prevedere che sia il compilatore ad inserire le verifiche sulla dimensione di tutti i buffer nel codice compilato senza richiedere alcuna modifica al codice sorgente, ma solo al compilatore, a scapito però dei tempi che possono aumentare anche di più del 200%.<ref name=":1" /> Questa fu la direzione intrapresa da due differenti progetti di patching al compilatore ''gcc'' scritti da Herman ten Brugge e Greg McGary.<ref>{{Cita web|url=ftp://ftp.tuwien.ac.at/.vhost/www.gnu.org/software/gcc.old/extensions.html|titolo=Gcc old extensions|urlmorto=sì}}</ref>
 
Approccio differente è invece quello di "StackShield", un'estensione del compilatore ''gcc'' per la protezione dallo stack smashing nei sistemi Linux; anziché inserire a tempo di compilazione i controlli per il ''bounds checking'' dei buffer, l'obiettivo di StackShield è quello di impedire la sovrascrittura dei ''return address'' memorizzandone una copia in una zona sicura non sovrascrivibile (all'inizio del segmento dati) all'inizio di ogni chiamata di funzione, copia che viene poi confrontata al termine dell'esecuzione della funzione con il valore memorizzato nello stack: se i valori non combaciano StackShield può terminare l'esecuzione del programma o tentare di proseguire ignorando l'attacco e rischiando al massimo il crash del programma.<ref>{{Cita web|url=http://www.angelfire.com/sk/stackshield/info.html|titolo=StackShield}}</ref>
 
Un'altra estensione del compilatore ''gcc'', "StackGuard", consente sia la rivelazione di eventuali ''stack buffer'' overflow sia la prevenzione degli stessi: la prima difesa tuttavia risulta molto più efficiente e portabile della seconda, in generale meno affidabile e sicura. La rivelazione si basa sulla scrittura nello ''stack frame'' di una ''canary word'' fra le variabili locali e il ''return address'' memorizzato e sull'assunto che non sia possibile sovrascrivere il RA senza alterare la ''canary word'', che prende quindi questo nome proprio in analogia all'uso dei [[Canarino domestico|canarini nelle miniere di carbone]] come primo sistema di allarme. Prima di restituire il controllo all'istruzione puntata dal RA, si controlla se la ''canary word'' ha subito alterazioni: eventuali modifiche vengono considerate come un potenziale tentativo di alterare il controllo dell'esecuzione del programma e quindi di attacco. La tecnica adottata da StackGuard è efficace solo se l'attaccante non è in grado di prevedere la ''canary word'', in questo caso sarebbe infatti in grado di progettare l'overflow in modo da sovrascrivere la ''canary word'' con il suo valore originale: StackGuard a questo scopo esegue la randomizzazione del ''canary''.<ref>{{Cita web|url=https://www.usenix.org/legacy/publications/library/proceedings/sec98/full_papers/cowan/cowan.pdf|titolo=StackGuard: Automatic Adaptive Detection and Prevention of Buffer-Overflow Attacks}}</ref>
 
=== Difese a livello di sistema operativo ===
Molti sistemi operativi hanno tentato di rispondere al problema del buffer overflow imponendo delle restrizioni sull'uso della memoria e rendendo quindi più complessi gli attacchi.
 
Un meccanismo di difesa a livello di sistema operativo molto diffuso si basa sul rendere certe pagine di memoria, come quelle contenenti ''stack'' e ''heap'', non eseguibili: ogni tentativo di trasferire il controllo dell'esecuzione a codice all'interno di queste aree solleva quindi un'eccezione, impedendone l'esecuzione. Ciò può essere realizzato sfruttando certe funzionalità hardware dei processori note come "[[NX-bit|NX]]" ("No eXecute") bit o "XD" ("eXecute Disabled") bit, oppure tramite tecniche software che emulano questo funzionamento.
 
Alcuni sistemi operativi basati su UNIX come [[OpenBSD]] e [[MacOS|OS X]] supportano direttamente lo ''executable space protection'', per altri SO è invece disponibile attraverso estensioni opzionali come:
* PaX<ref>{{Cita web|url=https://pax.grsecurity.net/|titolo=Homepage of PaX|sito=pax.grsecurity.net|accesso=4 settembre 2016|urlarchivio=https://web.archive.org/web/20161027061231/http://pax.grsecurity.net/|dataarchivio=27 ottobre 2016|urlmorto=sì}}</ref>
* Exec Shield<ref>{{Cita web|url=https://lwn.net/Articles/31032/|titolo="Exec Shield", new Linux security feature [LWN.net]|sito=lwn.net|accesso=4 settembre 2016}}</ref>
* OpenWall<ref>{{Cita web|url=https://www.openwall.com/|titolo=Openwall - bringing security into open computing environments|accesso=4 settembre 2016}}</ref>
Le versioni più recenti di [[Microsoft Windows]] lo supportano sotto il nome di Data Execution Prevention (DEP) (o protezione esecuzione programmi).<ref>{{Cita web|url=https://kc.mcafee.com/corporate/index?page=content&id=KB58554&locale=it_IT&viewlocale=it_IT|titolo=McAfee KnowledgeBase - Prevenzione esecuzione programmi e Protezione da overflow del buffer|sito=kc.mcafee.com|accesso=4 settembre 2016}}</ref>
 
Un'altra tecnica di difesa a livello di sistema operativo è l'[[ASLR|''address space layout randomization'' (ASLR)]] che consiste nel rendere parzialmente casuale l'indirizzo delle funzioni di libreria e delle aree di memoria più importanti; ciò rende più complessa (ma non impossibile) l'esecuzione di codice tramite exploit perché costringe l'attaccante a cercare l'indirizzo del codice da eseguire tramite una serie di tentativi rilevabili sia dalla vittima, sia da eventuali SW di protezione.<ref>{{Cita web|url=https://www.symantec.com/avcenter/reference/Address_Space_Layout_Randomization.pdf|titolo=Address Space Layout Randomization|accesso=30 aprile 2019|urlarchivio=https://web.archive.org/web/20190715102700/http://www.symantec.com/avcenter/reference/Address_Space_Layout_Randomization.pdf|dataarchivio=15 luglio 2019|urlmorto=sì}}</ref>
 
== Note ==
<references />
 
== Bibliografia ==
* William Stallings, Lawrie Brown, ''Computer Security - Principles and Practice'', Pearson, 2015, ISBN 978-0-133-77392-7
* Jon Erickson, ''Hacking - The Art of Exploitation'', No Starch Press, 2008, ISBN 978-1-59327-144-2
 
== Voci correlate ==
* [[Heap overflow]]
* [[Stack overflow]]
* [[Sicurezza informatica]]
 
== Collegamenti esterni ==
* {{FOLDOC||buffer overflow}}
* [https://www.sans.org/reading-room/whitepapers/securecode/buffer-overflow-attack-mechanism-method-prevention-386 Inside the Buffer Overflow Attack:Mechanism, Method, & Prevention]
* [https://cwe.mitre.org/top25/ CWE - 2011 CWE/SANS Top 25 Most Dangerous Software Errors]
* [https://www.kb.cert.org/vuls/id/363715 Vulnerability Note VU#363715 - Microsoft Internet Information Server (IIS) vulnerable to heap overflow during processing of crafted ".htr" request by "ISM.DLL" ISAPI filter]
* [https://www.sans.org/reading-room/whitepapers/threats/buffer-overflows-dummies-481 Buffer Overflows for Dummies - SANS Institute]
* [http://www.preserve-it-all.org/emc-plus/rsa-labs/historical/countermeasures-against-buffer-overflow-attacks.htm RSA Laboratories - Countermeasures against Buffer Overflow Attacks] {{Webarchive|url=https://web.archive.org/web/20160914092946/http://www.preserve-it-all.org/emc-plus/rsa-labs/historical/countermeasures-against-buffer-overflow-attacks.htm |date=14 settembre 2016 }}
* [https://www.freebsd.org/doc/en/books/developers-handbook/secure-bufferov.html 3.3. Buffer Overflows]
* [https://directory.fsf.org/wiki/Libsafe Libsafe - Free Software Directory]
* [http://seclab.cs.ucdavis.edu/projects/testing/tools/its4.html Its4]
* [https://www-01.ibm.com/software/awdtools/purify/compare.html Rational Purify]
* {{collegamento interrotto|1=[ftp://ftp.tuwien.ac.at/.vhost/www.gnu.org/software/gcc.old/extensions.html Gcc old extensions] |data=febbraio 2018 |bot=InternetArchiveBot }}
* [http://www.angelfire.com/sk/stackshield/info.html StackShield]
* [https://www.usenix.org/legacy/publications/library/proceedings/sec98/full_papers/cowan/cowan.pdf StackGuard: Automatic Adaptive Detection and Prevention of Buffer-Overflow Attacks]
* [https://web.archive.org/web/20161027061231/http://pax.grsecurity.net/ Homepage of PaX]
* [https://lwn.net/Articles/31032/ "Exec Shield", new Linux security feature]
* [https://www.openwall.com/ Openwall - bringing security into open computing environments]
* [https://kc.mcafee.com/corporate/index?page=content&id=KB58554&locale=it_IT&viewlocale=it_IT McAfee KnowledgeBase - Prevenzione esecuzione programmi e Protezione da overflow del buffer]
* [https://web.archive.org/web/20110721060319/http://csrc.nist.gov/publications/history/ande72.pdf "Computer Security Technology Planning Study" - Pag. 61]
* [https://rdist.root.org/2010/05/03/why-buffer-overflow-exploitation-took-so-long-to-mature/ Why buffer overflow exploitation took so long to mature]
* [http://seclists.org/bugtraq/1995/Feb/109 Thomas Lopatic, Bugtraq: Vulnerability in NCSA HTTPD 1.3]
* [https://www.sans.org/reading-room/whitepapers/malicious/code-red-worm-45 What is Code Red Worm?]
* [http://pen-testing.sans.org/resources/papers/gcih/sql-slammer-worm-101033 SQL Slammer worm] {{Webarchive|url=https://web.archive.org/web/20160913082805/http://pen-testing.sans.org/resources/papers/gcih/sql-slammer-worm-101033 |date=13 settembre 2016 }}
* [https://security.googleblog.com/2016/02/cve-2015-7547-glibc-getaddrinfo-stack.html CVE-2015-7547: glibc getaddrinfo stack-based buffer overflow]
* [https://access.redhat.com/it/node/2171131 Falla di sicurezza critica: glibc stack-based buffer overflow in getaddrinfo() (CVE-2015-7547) - Red Hat Customer Portal]
* [https://web.archive.org/web/20190715102700/http://www.symantec.com/avcenter/reference/Address_Space_Layout_Randomization.pdf Address Space Layout Randomization]
 
{{Controllo di autorità}}
{{Portale|Sicurezza informatica}}
 
[[Categoria:Software malevoli]]
[[Categoria:Tecniche di attacco informatico]]
[[Categoria:Hacking]]