Recentemente ho letto sull'argomento $.
D: Perché un linguaggio di programmazione ha insicurezza insignificante? O .. era solo nei vecchi tempi? Come potrebbe essere?
Recentemente ho letto sull'argomento $.
D: Perché un linguaggio di programmazione ha insicurezza insignificante? O .. era solo nei vecchi tempi? Come potrebbe essere?
C è stato progettato in un momento in cui la potenza della CPU disponibile era una risorsa scarsa e anche la programmazione era molto inferiore. I tempi moderni hanno cambiato il contesto:
Al giorno d'oggi, la maggior parte del tempo di elaborazione in una CPU viene spesa in attesa di RAM, poiché la velocità della CPU è aumentata molto più rapidamente della diminuzione della latenza della RAM. Quindi la CPU ha un po 'di "tempo libero" e quindi può permettersi controlli extra, ad es. controlli ai limiti sugli array.
Di questi tempi si fa molta più programmazione, il che significa che sono coinvolti molti più programmatori e la competenza media è quindi, meccanicamente, diminuita.
La competenza media dell'attore , d'altra parte, è abbastanza aumentata. Gli exploit di overflow del buffer sono passati, dagli anni '70, da "debolezza teorica" a "attacco generico che può essere regolato automaticamente e programmato".
Questo è il motivo per cui quasi tutti i linguaggi di programmazione più recenti includono "protezioni" intrinseche contro il buffer overflow, ma anche attacchi di cross-typing (quando alcuni byte sono fatti per essere interpretati con un tipo diverso, ad esempio facendo in modo che un codice consideri un intero come se fosse era un puntatore) e problemi di allocazione della memoria ("use-after-free"). Per buffer overflow, la protezione è duplice:
Sfortunatamente, tali protezioni non possono essere genericamente trasferite su C. Ad esempio, la specifica C consente di scrivere un valore di puntatore in un file e poi, in seguito, di leggerlo di nuovo e il puntatore DEVE essere ancora valido. È matematicamente impossibile scrivere un garbage collector in grado di gestire questo caso. Lì è un GC per C e C ++ , ma (per sua natura) non può davvero supportare ogni programma C "legale".
In altre parole, se "modifichi" C in modo che sia più robusto contro i buffer overflow, allora non è più "C", ma qualcos'altro (che potresti chiamare "Java" o "C #"). Il C originale è ancora ampiamente utilizzato, a volte per una buona ragione tecnica (ad esempio per scrivere codice su una piattaforma molto piccola, come una smart card), ma soprattutto per tradizione e per una più facile integrazione con tutte le librerie esistenti.
C è un linguaggio semplice che è abbastanza facile da tradurre in Assembly / Machine Language (rispetto ai linguaggi moderni) quando si trascurano le ottimizzazioni.
C non è tanto incrinato dalle insicurezze, ma solo C non ti obbliga a fare sempre le cose in un modo più sicuro come in altre lingue moderne. Un programma eseguito su un Bell Labs PDP-10 negli anni '70 da ingegneri esperti aveva requisiti diversi rispetto a un moderno server web connesso a Internet che poteva essere attaccato da abili avversari. Allora, volevi che il linguaggio fosse veloce e semplice e che così tanti controlli di sanità fossero lasciati al programmatore.
Una delle parti "insicuri" principali di C è la mancanza di controllo dei limiti. Se vuoi copiare una stringa di caratteri in un nuovo array, la funzione strcpy
copierà una stringa da un buffer ad un altro buffer finché non vedrà un byte NULL che indica la fine della prima stringa. Ciò consente attacchi di buffer overflow se si tenta di spremere 500 caratteri di input in un buffer da 256 byte (il programma continuerà a copiare fino a raggiungere il carattere null). La memoria successiva a quella stringa potrebbe aver avuto dati importanti per l'esecuzione dei programmi, consentendo eventualmente a un utente malintenzionato di immettere nuovi comandi a livello macchina nel programma. Tuttavia, ci sono modi più sicuri per programmare all'interno di C, ad esempio, usa strlcpy che prende come parametro la dimensione del buffer di destinazione e copia solo fino a quel numero di caratteri (e quindi null termina la stringa).
(Inoltre, i moderni sistemi operativi forniscono aiuto attraverso funzionalità come la non esecuzione, i bit senza scrittura e la randomizzazione del layout dello spazio degli indirizzi.)
Certo, è ancora possibile che i programmatori commettano errori.
Quando C fu progettato nei primi anni '70, furono diversi tempi.
A causa di queste circostanze, le prestazioni elevate erano molto più preoccupanti della sicurezza. Ecco perché C omette molti controlli di integrità sulle operazioni e si aspetta che i programmatori li implementino quando ne sentono il bisogno e possono risparmiare le risorse che costa.
Ma al giorno d'oggi, la situazione è cambiata
D'altro canto, le risorse hardware sono diventate molto più abbondanti. I più grandi supercomputer degli anni '70 avevano una potenza di elaborazione che era di diverse grandezze inferiore a quella dei telefoni cellulari di oggi.
Per questi motivi, l'attenzione dei linguaggi di programmazione si è spostata dall'efficienza alla sicurezza.
Leggi altre domande sui tag c buffer-overflow