2015-05-20 17 views
6

sto imparando circa gli attacchi di overflow heap e il mio libro di testo fornisce il seguente codice C vulnerabili:heap overflow Attacco

/* record type to allocate on heap */ 
typedef struct chunk { 
    char inp[64];   /* vulnerable input buffer */ 
    void (*process)(char *); /* pointer to function to process inp */ 
} chunk_t; 

void showlen(char *buf) 
{ 
    int len; 
    len = strlen(buf); 
    printf("buffer5 read %d chars\n", len); 
} 

int main(int argc, char *argv[]) 
{ 
    chunk_t *next; 

    setbuf(stdin, NULL); 
    next = malloc(sizeof(chunk_t)); 
    next->process = showlen; 
    printf("Enter value: "); 
    gets(next->inp); 
    next->process(next->inp); 
    printf("buffer5 done\n"); 
} 

Tuttavia, il libro di testo non spiega come si potrebbe risolvere questa vulnerabilità. Se qualcuno potesse spiegare la vulnerabilità e un modo (i) per risolverlo sarebbe fantastico. (Parte del problema è che vengo da Java, non C)

+4

il tuo 'inp' è 64 byte. quindi inserisci 65 byte e hai overflow ... –

+4

E per risolvere il problema, [usa fgets()] (http://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous -che non dovrebbe essere usato) –

+0

@orangesoda quale libro è questo? –

risposta

5

Il problema è che gets() manterrà la lettura nel buffer finché non legge una nuova riga o raggiunge EOF. Non conosce la dimensione del buffer, quindi non sa che dovrebbe fermarsi quando raggiunge il limite. Se la linea è di 64 byte o più lunga, questa passerà fuori dal buffer e sovrascriverà process. Se l'utente che immette l'input lo sa, può digitare solo i caratteri giusti nella posizione 64 per sostituire il puntatore della funzione con un puntatore ad un'altra funzione che desidera invece effettuare la chiamata al programma.

La correzione consiste nell'utilizzare una funzione diversa da gets(), quindi è possibile specificare un limite per la quantità di input che verrà letto. Invece di

gets(next->inp); 

è possibile utilizzare:

fgets(next->inp, sizeof(next->inp), stdin); 

Il secondo argomento di fgets() dice di scrivere al massimo 64 byte in next->inp. Quindi leggerà al massimo 63 byte da stdin (è necessario consentire un byte per il terminatore di stringa null).

5

Il codice utilizza gets, che è noto per il suo potenziale problema di sicurezza: non c'è modo di specificare la lunghezza del buffer che si passa ad esso, Continueremo a leggere da stdin finché non incontra \n o EOF. Potrebbe quindi traboccare il tuo buffer e scrivere in memoria al di fuori di esso, e poi accadranno cose brutte - potrebbe crashare, potrebbe continuare a funzionare, potrebbe iniziare a giocare al porno.

Per risolvere questo problema, è necessario utilizzare fgets.

1

È possibile riempire in seguito con più di 64 byte impostando l'indirizzo per process. In tal modo si consente di inserire qualsiasi indirizzo desiderato. L'indirizzo potrebbe essere un puntatore a qualsiasi funzione.

Per risolvere semplice garantire che soltanto 63 byte (una per nulla) vengono letti nella matrice inp - utilizzare fgets

0

La funzione get non limita la quantità di testo proveniente da stdin. Se più di 63 caratteri provengono da stdin, ci sarà un overflow. Il get scarta il carattere LF, che sarebbe un tasto [Invio], ma aggiunge un carattere null alla fine, quindi il limite di 63 caratteri.

Se il valore alla inp è riempito con 64 caratteri non nulli, come si può accedere direttamente, la funzione showlen attiveranno una violazione di accesso, come strlen cercherà per la null-char oltre inp per determinare la sua dimensione.

Utilizzare fgets sarebbe una buona soluzione al primo problema ma aggiungerà anche un carattere LF e il valore null, quindi il nuovo limite di testo leggibile sarà 62.

Per il secondo, basta fare attenzione a ciò che è scritto su inp.