Quali sono i rischi / le vulnerabilità di sicurezza che ogni programmatore C deve conoscere? [chiuso]


13

Esistono molti rischi per la sicurezza derivanti dallo stretto contatto con l'hardware anziché dall'utilizzo di API ben collaudate e comprovate da linguaggi di programmazione di alto livello. È molto più facile causare un overflow del buffer in C che in un linguaggio come Java.

Quali sono i rischi o le vulnerabilità (ad es. Buffer overflow) di cui ogni programmatore C dovrebbe essere a conoscenza (vulnerabilità IE relative ai programmatori C)? A quali problemi potrebbero comportare? Come evitarli e quali sono gli errori comuni che causano che si verifichino nei programmi?


Che ne pensi di questo elenco: owasp.org/index.php/Category:OWASP_Top_Ten_Project Cosa serve di più di questo?
S.Lott

2
@ S.Lott: sembra che si tratti di problemi di sicurezza nello sviluppo web. Sembra che ci siano più risorse su questo in generale di quello che sto effettivamente chiedendo, a quanto pare.
Anto,

@Anto: aggiorna la domanda per distinguere tra tutte le risorse sulla sicurezza e la sicurezza che stai chiedendo.
S.Lott

@ S.Lott: non sono sicuro di cosa intendi. Chiedo la sicurezza che è importante per la maggior parte dei programmatori C, vale a dire cose come buffer overflow e altre cose che sono possibili in C.
Anto

@Anto: "Sembra che ci siano più risorse su quella [sicurezza web?] In generale di quello che sto effettivamente chiedendo" Sembra dire che stai chiedendo una sicurezza che non è la sicurezza web. Vero? In tal caso, ti preghiamo di aggiornare la domanda per spiegare cosa stai cercando. Falso? Poi si sta chiedendo per la sicurezza web, in questo caso, perché non è la lista OWASP menzionato nella tua domanda?
S.Lott

Risposte:


13

Gli overflow del buffer sono importanti. Per impostazione predefinita, nulla in C è controllato per intervallo, quindi è molto semplice sovrascrivere un buffer. C'è una funzione di libreria standard gets(), che non può essere fermata dall'overflow del buffer e che non dovrebbe quasi mai essere usata.

Esistono alcune tecniche a livello di implementazione per ostacolare lo sfruttamento, come la confusione dei blocchi di heap, ma ciò non bloccherà gli overflow del buffer nei buffer locali, che spesso possono fare cose interessanti come cambiare l'indirizzo a cui tornerà una funzione.

Non esiste una buona soluzione generale in C. Molte funzioni di libreria hanno versioni che limiteranno la quantità che scriveranno. anche se il calcolo può essere goffo. Esistono software in grado di rilevare overflow del buffer di heap nei test, purché venga eseguito il test appropriato e lo overflow dello stack verrà spesso visualizzato come arresto anomalo nei test. Oltre a ciò, è una questione di attenta codifica e revisione del codice.

Un problema correlato è il problema di scrivere in un buffer troppo piccolo di un carattere, dimenticando che una stringa C che è lunga n caratteri richiede n + 1 caratteri in memoria, a causa del '\0'terminatore. Se l'attaccante riesce a memorizzare una stringa senza il terminatore, qualsiasi funzione C che si aspetta che una stringa continui l'elaborazione fino a quando non colpisce un byte zero, il che potrebbe comportare la copia o l'output di più informazioni di quanto si desideri (o colpire la memoria protetta per un attacco DOS ). La soluzione, ancora una volta, è la consapevolezza, la cura e la revisione del codice.

C'è un altro rischio con la printf()famiglia. Se mai scrivi char * str; ... printf(str);, ti stai preparando per problemi se strcontiene un '%' quando viene stampato. La %ndirettiva di formato consente printf()di scrivere in memoria. La soluzione è printf("%s", str);o puts(str);. (Inoltre, utilizzare C99 snprintf()anziché sprintf().)

L'uso di numeri interi senza segno, in particolare come indici di loop, può causare problemi. Se si assegna un valore negativo piccolo a un segno senza segno, si ottiene un valore positivo elevato. Ciò può minare cose come l'elaborazione di N istanze di qualcosa o in funzioni limitate come strncpy(). Esamina tutti i numeri interi senza segno. Potresti voler evitare unsigned short, poiché un grande valore in uno di questi si convertirà in un grande valore positivo in un int.

Non dimenticare che una costante di carattere, in C, è in realtà un int. Scrivere qualcosa di simile char c; while((c = getchar()) != EOF) ...può facilmente fallire, poiché EOFnon sarà rappresentabile in a char.

Ci sono molti più errori caratteristici C che mi vengono in mente, ma questi potrebbero causare problemi di sicurezza.


Non è necessario utilizzare printf("%s", str)una stringa nuda quando puts(str)farà lo stesso lavoro.
Blrfl,

@Blrfl ma putsaggiunge un carattere di nuova riga mentre printfnon lo fa.
bendaggio

Potrebbe anche fare fputs(str, stdout), il che non lo fa.
Blrfl,

Per quanto riguarda l'overflow dei numeri interi: l'uso di ints firmati non è una soluzione, in quanto l'overflow di questi causerà UB. L'unica soluzione (dolorosa) è dimostrare formalmente che non si verificherà mai il trabocco o verificare in fase di esecuzione (ma controllare correttamente, il che è anche complicato senza traboccare nel controllo).
sleske,

@DavidThornley: C11 e C ++ 14 rimosso dalla funzione standard () della libreria standard a causa della sua pericolosità.
Distruttore

5

Alcuni dei rischi specifici per C includono: overflow del buffer , formattazione degli attacchi di stringa e overflow degli interi .


1
Non c'è nulla di specifico per C nei buffer overflow: qualsiasi linguaggio con puntatori può avere questo. Gli overflow di numeri interi si applicano praticamente a qualsiasi lingua e possono verificarsi facilmente anche nel codice gestito.
Steve,

1
@Steve, non sono proprio i puntatori che causano quel problema, ma come il linguaggio non impone i limiti dell'array.
Doug T.,

2
@Steve la domanda non riguardava cose che riguardano solo C, ma qualcosa di cui i programmatori C dovrebbero essere a conoscenza.
Attacco di

1
@Steve: C è insolitamente suscettibile agli overflow del buffer, in parte a causa della mancanza di supporto per il controllo dell'intervallo e del numero di funzioni di libreria che supereranno felicemente i buffer per te.
David Thornley,

Capisco in particolare la domanda che si pone su C, ma penso che valga la pena chiarire nel caso in cui la risposta venga letta dal contesto che questi rischi sono più generali. In particolare, gli sviluppatori di codice gestito sono (IMHO) troppo compiacenti per quanto riguarda la sicurezza e gli overflow di numeri interi in particolare influenzano la maggior parte delle lingue.
Steve,

4

Ecco un rischio facile da perdere che può causare problemi che richiederanno ore per essere risolti.

Considera il codice seguente, che verrà compilato senza problemi.

if(lpstr_current_state = CONST_EMERGENCY_STATE_HOLY_CRAP)
{
    do_warn_joint_chiefs_of_staff_of_nuclear_attack();
}

Quando controlli per vedere se lpstr_current_stateè CONST_EMERGENCY_STATE_HOLY_CRAPeffettivamente assegnato. È meglio posizionare sempre la variabile costante a sinistra. Quando metti la costante a sinistra, il compilatore fallirà perché non puoi assegnare un valore a una variabile.

if(CONST_EMERGENCY_STATE_HOLY_CRAP = lpstr_current_state)
{
    do_warn_joint_chiefs_of_staff_of_nuclear_attack();
}

Quindi puoi facilmente dire a te stesso "Merda santa, che avrebbe potuto essere cattivo", mentre correggi il codice da leggere ...

if(CONST_EMERGENCY_STATE_HOLY_CRAP == lpstr_current_state)
{
    do_warn_joint_chiefs_of_staff_of_nuclear_attack();
}

7
Questo è facile da catturare e contrassegnare come un avvertimento per un compilatore, a differenza di altri problemi. Sfortunatamente, non tutti i compilatori lo rendono facile da fare.
David Thornley,

2
Ciò può accadere in lingue diverse da C, qualsiasi lingua che utilizza =e ==.
FrustratedWithFormsDesigner

3
Anche questa non è in realtà una vulnerabilità di sicurezza, questo è un bug.
Chris Pitman,

1
Queste sono chiamate condizioni di Yoda.

2
@Kristofer Hoch: se vogliamo considerare un probabile bug C un rischio e considerarlo qui, avremo bisogno di un forum molto più grande.
David Thornley,

0

Esiste solo un rischio per la sicurezza: il fatto che ci siano persone esterne che faranno del loro meglio per rilevare eventuali vulnerabilità nel software e sfruttarlo a proprio vantaggio. Tutto il resto segue da lì.

Quindi, quando pensi che "nessuno nella loro mente giusta lo farebbe ...", allora devi pensare immediatamente "tranne qualcuno che vuole hackerare i computer di altre persone farebbe esattamente questo".

La conseguenza più grande è che ogni volta che reagisci a eventi esterni (ad esempio, elaborando dati forniti dall'esterno), devi presumere che questi dati fossero sotto il controllo del tuo peggior nemico.


Anche se sarei d'accordo con i paragrafi due e tre, dare tutta la colpa all'attaccante è un po 'denso nei miei occhi. Ne bastano sempre due per un attacco riuscito: un programmatore che sbaglia e un attaccante che sorprende il programmatore nell'atto. Tuttavia, la vulnerabilità della sicurezza è presente prima che l'attaccante possa sfruttarla. E per questo, il programmatore deve essere incolpato.
cmaster - ripristina monica il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.