Per difendersi contro vulnerabilità da Buffer Overflow si possono scegliere diverse strade: scrivere codice sicuro, non rendere eseguibile l'area di memoria che contiene le variabili, controllare la dimensione degli array ogni volta che vengono inseriti oppure verificare l'integrità dei puntatori.
Vediamo in dettaglio ogni metodo, con relativi vantaggi e difetti.
Scrivere codice sicuro
E' sicuramente la scelta migliore anche se la più costosa, in quanto bisogna controllare ogni singola parte del codice, procedimento noioso e molto lungo. Esistono dei veri e propri gruppi di persone che controllano pezzi di codice per verificarne la sicurezza. Bisogna fare particolare attenzione a chiamate a funzioni di libreria molto vulnerabili, che non controllano la lunghezza degli argomenti che manipolano.
Per prima cosa bisogna scrivere codice semplice, evitare programmi troppo lunghi e pesanti, dato che sicuramente presenteranno un buco.
Un'altra cosa da guardare è che il programma abbia privilegio necessario solamente per quello che deve fare. A volte il programma richiede privilegi elevati per eseguire operazioni altrimenti non effettuabili: una volta eseguita l'operazione bisogna riportare i privilegi allo stato iniziale, per evitare che l'intruso possa causare troppi danni.
Per ultimo, ma non meno importante, controllare tutti i dati che vengono immessi prima di essere utilizzati.
Per controllare il codice si utilizzano programmi di debug, che immettendo a caso nei buffer utilizzati codice d'attacco servono per individuare eventuali vulnerabilità.
Buffer non eseguibile
Con questo metodo si dovrebbe rendere non eseguibile l'area di memoria utilizzata dalle variabili, in modo da impedire all'attaccante di eseguire il codice inserito. Sui sistemi operativi recenti (sia Windows che Unix) una soluzione del genere è ormai impensabile, dato che per ottimizzare la loro esecuzione deve esserci la possibilità di inserire codice dinamico in memoria.
Tuttavia sono presenti delle patch per Linux e Solaris con cui è possibile rendere lo stack non eseguibile e preservare la compatibilità della maggior parte dei programmi.
La protezione offerta da questo procedimento permette di difendersi dall'inserimento di codice eseguibile nelle variabili automatiche, ma non protegge da altre forme d'attacco.
Controllo della dimensione degli array
Non basta inserire codice per realizzare un buffer overflow, ma è anche necessario modificare il flusso del programma in esecuzione. Controllando la dimensione degli array si previene da questo tipo d'attacco. Se in un array non si può scrivere oltre la sua dimensione non è possibile corrompere i dati adiacenti nello stack: ogni lettura e scrittura in un array è quindi riferita ad uno spazio di memoria pari alla dimensione dell'array stesso.
Controllo dell'integrità dei puntatori
Con questo metodo si controlla se un puntatore è stato sovrascritto prima di essere usato: se un attaccante riuscisse in qualche modo a modificare un puntatore, questo non verrebbe utilizzato.
Tuttavia anche questa è una soluzione parziale al problema, in quanto tutti gli attacchi che non riguardano puntatori andranno a segno.
In conclusione, si possono utilizzare tutti i metodi qui descritti per creare del codice sicuro: limitare i problemi alla radice è molto più facile che trovare soluzioni.