Codice ingannevole per rendere la memoria sicura

16

Sto progettando una sfida per i compiti a casa per gli studenti che stanno imparando sulla sicurezza della memoria e scrivendo codice C sicuro. Come parte di questo, sto cercando un piccolo compito di programmazione in cui non è banale scrivere codice C privo di sovraccarichi del buffer, errori di matrice fuori limite e / o altri errori di sicurezza della memoria. Quale sarebbe un buon esempio di tale compito?

In altre parole: specificherò la funzionalità desiderata; lo implementano in C; e se non stanno attenti durante l'implementazione, c'è una possibilità significativa che il loro codice abbia una vulnerabilità di sicurezza della memoria. Idealmente, preferirei qualcosa che possa essere implementato in modo conciso (alcune centinaia di righe di codice, al massimo) per mantenere il compito di dimensioni gestibili, e sarebbe straordinariamente bello se il compito fosse in qualche modo industrialmente o praticamente rilevante o realistico o rappresentante della programmazione del mondo reale.

Per dare un esempio da un dominio diverso, l'implementazione della ricerca binaria su un elenco ordinato è un classico esempio di un'attività di programmazione facilmente specificata in cui, se non si presta attenzione quando si implementa, c'è una possibilità significativa che si avrà una sorta di bug di logica (ad esempio, un errore off-by-one, un loop infinito su alcuni input, quel genere di cose). Esiste un buon compito corrispondente, per sicurezza, e in particolare vulnerabilità di sicurezza della memoria?

    
posta D.W. 10.12.2013 - 09:12
fonte

4 risposte

12

Un tipico esempio di gestione non banale del buffer è l'analisi di file binari (o pacchetti di rete) che possono contenere stringhe di lunghezza arbitraria. (C'è qualche parser ASN.1 che non ha buffer trabocca bug a un certo punto?)

Ad esempio, considera il formato dei blocchi di dati testuali nei file PNG :

The keyword and text string are separated by a zero byte (null character). Neither the keyword nor the text string may contain a null character. The text string is not null-terminated (the length of the chunk defines the ending).

Quindi i compiti a casa potrebbero essere uno strumento che emette tutti i dati testuali in un file PNG.

Anche il testo semplice non può essere abbastanza banale se devi gestire arbitrariamente lunghe righe e quindi devi ridimensionare un buffer in modo dinamico. Ad esempio:

Implement tail without parameters. (Lines can be longer than any static buffer. The entire file can be larger than available memory.)

    
risposta data 10.12.2013 - 14:18
fonte
7

Vedo molti problemi quando le persone devono analizzare i dati dei caratteri dalle strutture, specialmente quando si tratta di un buffer che normalmente termina con null, ma può essere la dimensione del buffer senza un terminatore.

short canary = 0x5678;
struct customer {
    char name[4];
    char suffix[3];
};
short fencepost = 0x1234;

Fagli riempire il cliente con dati come "Joe" e "Jr". Chiedi loro di stampare tutti i dati in questo formato esatto:

canary: 0x5678
name: Joe
suffix: Jr
fencepost: 0x1234

Quindi invitali a riempire il cliente con "John" ed "Esq". Il loro output dovrebbe assomigliare a questo:

canary: 0x5678
name: John
suffix: Esq
fencepost: 0x1234

È un compito semplice e comune. Questo dovrebbe insegnare loro che non possono semplicemente strcpy ("Esq") nel buffer, perché ucciderà il canarino. Dovrebbe essere necessario che copino i dati dal buffer per annullarli e stamparli.

Ti consiglio di testarlo per primo, e controlla le impostazioni del compilatore. Nelle versioni precedenti di Microsoft Visual C ++ di Microsoft, una build di debug si collegava in una versione di debug dell'allocatore di memoria che aggiungeva fenceposts attorno alla memoria allocata. Abilita il debugger a segnalare un errore di memoria sovrascritta. Non so se le versioni più recenti lo fanno ancora, ma so che le versioni di rilascio non lo fanno.

Se vuoi dare loro un "perché", mostra come inserire un nome come Fred @@@@@@@@ può causare un arresto anomalo e consentire a un hacker di assumere il controllo del programma.

    
risposta data 10.12.2013 - 16:33
fonte
5

è difficile perché i moderni kernel Linux non hanno stack eseguibili, quindi non saranno in grado di testare i loro programmi su una normale distribuzione linux. (Ricordo di aver avuto problemi nel testare il codice elencato nel foglio Alef One sulla mia macchina debian)

Quello che potresti fare è fornirgli un vm personalizzato (come linux dannatamente vulnerabile) che ha disabilitato le impostazioni di sicurezza e dire loro di testare il loro codice lì.

Più precisamente la soluzione sarebbe quella di farli scrivere un programma ottiene un nome file come argomento della riga di comando o come input dell'utente

  • apre il file
  • legge alcune configurazioni da esso
  • lo analizza / cerca qualcosa di specifico
  • inserisce la parte rilevante in un socket di rete
  • un altro processo legge i dati e deve stampare alcune parti rilevanti.

Il tuo scenario potrebbe essere:

You have to write a program in c which reads airline flight schedules from a file provided by the user and pushes it via a tcp socket to another process which then displays it.

Per rendere le cose un po 'più semplici, puoi fornire una struttura in cui tutto deve essere gestito.

È semplice poiché la maggior parte del codice può essere trovata online (leggi dal file, scrivi sul socket) e gli studenti devono solo occuparsi della gestione della memoria

    
risposta data 16.12.2013 - 17:08
fonte
4

A seconda dei vincoli della piattaforma, suggerirei di implementare alcuni DCOM .

L'implementazione delle chiamate DCOM coinvolge molte aree problematiche diverse: chiamate di rete, gestione dell'interfaccia, marshalling, conteggio dei riferimenti distribuiti e gestione della durata degli oggetti, sicurezza della memoria condivisa e altro - se fatto bene, include anche un controllo ACL di basso livello e simili. Un sacco di piccoli pezzi e strutture complesse che volano in giro.

Ho mai visto alcun codice DCOM - sia che chiami client o server - NON abbia bug significativi (a meno che non sia implementato in un linguaggio "sicuro", come VB, e anche allora è comune).

    
risposta data 23.12.2013 - 10:22
fonte

Leggi altre domande sui tag