Inserire un "canary" (canarino)

Un canary è un valore nello stack il cui valore viene verificato prima del ritorno.

void funzione(...) {
   int canary;
   char buf[MAX_SIZE]; // seguono altre dichiarazioni
   canary = VALORE_CANARY;
   gets(buf);    // o qualche altra operazione pericolosa
   ...
   if(canary != VALORE_CANARY)
      exit;
   return;
}

Ruolo del canary: Il canary funge da segnaposto. Prima del ritorno dalla funzione, viene verificato se il valore del canary è rimasto invariato. Se il canary è stato alterato, può indicare un overflow di buffer. In tal caso, il programma può decidere di terminare l'esecuzione (exit).

Un canary è un valore casuale (difficile da indovinare per l'attaccante) o un valore composto da diversi terminatori di stringa (CR, LF, Null, -1). L'obiettivo è rendere difficile per un attaccante indovinare il valore del canary durante un attacco.

Implementazioni per i compilatori GCC e Microsoft Visual C++ Esistono attacchi noti (vedi Pincus/Baker)


Programmazione difensiva

BUG Non utilizzare mai gets(). Poiché è impossibile stabilire senza conoscere i dati in anticipo quanti caratteri gets() leggerà e poiché gets() continuerà a memorizzare caratteri oltre la fine del buffer, è estremamente pericoloso usarlo. È stato utilizzato per violare la sicurezza informatica. Utilizzare invece fgets(). — Dalla pagina del manuale di gets(3)

Verifica automatica dei limiti degli array

Approccio: il compilatore aggiunge automaticamente un controllo esplicito ad ogni accesso a un array

I controlli vengono inseriti durante la generazione del codice. Esempio: miglioramenti di GCC di Jones&Kelly.

Svantaggi


Evita C (++)