Sta usando stack separati per gli indirizzi di ritorno e gli argomenti delle funzioni una misura di sicurezza valida?

10

Per quanto ne so, molti exploit si basano sulla sovrascrittura dell'indirizzo di ritorno della funzione che cercano di sfruttare. Lo fanno per eccesso di buffer. Ma cosa succede se il compilatore imposta due stack separati l'uno dall'altro nello spazio degli indirizzi e ne usa uno (forse quello di sistema, come esp / rsp -driven uno su sistemi x86 *) per gli indirizzi di ritorno e l'altro per passare argomenti di funzione? In questo caso, qualsiasi overrun del buffer sovrascriverà alcuni locali, magari includendo quelli delle funzioni del chiamante, ma continuerà a lasciare intatti gli indirizzi di ritorno.

Inoltre, lo stack per gli indirizzi di ritorno potrebbe essere usato per memorizzare tutti i puntatori di funzione e entità simili che consentono di saltare / chiamare indirettamente, in modo che siano protetti.

Questa opzione è già stata presa in considerazione? È praticabile? Se sì, perché non è stato implementato (o ce l'ha?)?

    
posta Ruslan 07.08.2015 - 21:52
fonte

2 risposte

4

Il problema con la maggior parte dei sistemi operativi è che seguono una specifica "convenzione di chiamata". Questa convenzione richiede l'inserimento di parametri di funzione nello stack, essendo una derivata della convenzione di chiamata in stile C. devi usare questa convenzione per la compatibilità ABI (Application Binary Interface) con quel SO. Pertanto, senza il supporto del sistema operativo, è possibile utilizzare questa funzione solo per le chiamate effettuate all'interno dell'applicazione.

Ciò complicherebbe un po 'i compilatori e probabilmente richiederebbe una buona dose di lavoro. In breve, potresti proteggere i tuoi programmi se avessi un compilatore che supportava questa convenzione di chiamata, ma saresti comunque in balia del sistema operativo ogni volta che dovessi fare cose come leggere / scrivere un file, ecc. Un sovraccarico del buffer in una DLL, ad esempio, non può essere risolto modificando la convenzione di chiamata.

In secondo luogo, fino a poco tempo fa, con l'avvento della virtualizzazione, non era davvero fattibile creare un'area separata come questa, perché la segmentazione era costosa e la virtualizzazione della memoria ancora di più. Oggi, questo sarebbe praticamente un non-problema, ma dal momento che abbiamo a che fare con software storici (ad esempio roba scritta dieci anni fa che richiedono ancora i metodi di chiamata convenzionali), il sistema operativo sarebbe quindi costretto a supportare entrambi i modelli per un periodo indefinito di tempo.

Se un sistema operativo nuovo senza problemi di compatibilità fosse scritto, potrebbe certamente farlo, ma probabilmente non accadrà, perché ci sono metodi più validi. Il sistema operativo Microsoft Singularity è completamente immune ai sovraccarichi del buffer (secondo loro), poiché il sistema operativo convalida staticamente che ogni programma non può possibilmente comportarsi male. È interessante notare che questo sistema operativo non usa "protezione della memoria" come utilizzato da Windows, Linux, Mac OS, ecc. I programmi sono convalidati per il comportamento corretto prima vengono eseguiti, non mentre vengono eseguiti . Naturalmente, se un virus fosse in grado per questo sistema, avrebbe un controllo di sistema illimitato a causa della mancanza di protezione a livello di hardware.

In breve, anche senza una seria ricerca sull'argomento, è chiaramente possibile che questo approccio potrebbe funzionare, ma al di fuori di FOSS (software libero e open source), non sarebbe possibile questo approccio al lavoro da un punto di vista finanziario. Linux potrebbe essere riscritto dal kernel fino a supportare il nuovo modello, compilato un compilatore per questo, e quindi tutto il software potrebbe essere ricompilato senza troppi sforzi (nota: "troppo" essere relativo a, dimmi, Microsoft).

Microsoft, Apple e così via non hanno questo vantaggio, perché il codice è già compilato da milioni di sviluppatori diversi, quindi tutto ciò che non può essere aggiornato sarebbe istantaneamente obsoleto, o avrebbero dovuto scrivere emulatori per supporta il vecchio software. Fondamentalmente, fino a quando qualcuno non ha un SO con questa caratteristica integrata, con compilatori compatibili (almeno C e C ++, più probabilmente Cocoa e Win32 C ++), e guadagna abbastanza supporto per diventare un contendente contro Linux, Microsoft e Mac OS, sarebbe piuttosto difficile giustificare il passaggio a un nuovo modello. Linux sarebbe il più facile da spostare, anche se tutto il software dovrebbe essere compilato finché RPM e altri tipi di pacchetti non supportano il nuovo modello di chiamata.

Infine, DEP (Data Execution Prevention) risolve praticamente il problema nella maggior parte dei casi, rendendo più difficile l'esecuzione di codice che non dovrebbe. Ciò riduce anche la necessità di passare a un nuovo modello, sebbene, come dimostra Singularity, l'hardware potrebbe essere molto più veloce se non fosse costantemente costretto a proteggersi dai bug dei programmatori e dagli exploit che presentano.

    
risposta data 07.08.2015 - 22:30
fonte
2

Sì, questo è già stato implementato. Nel questo post sul blog, Erin Ptacek menziona brevemente in che modo AVR ha diversi programmi e memoria di dati e come questo rende lo sfruttamento più difficile.

A Harvard Architecture has two distinct memories; there is program memory (imem, typically flash) and data memory (dmem, typically SRAM). They live in two different address spaces. The CPU reads instructions from imem, but instructions themselves read and write dmem. This is neat because makes exploits harder to write. You can’t simply upload code in a buffer and somehow point the PC at it; that buffer is in dmem, not imem. You’ll see what I mean in a few weeks.

Sebbene ciò possa aiutare a impedire a un utente malintenzionato di sfruttare un overflow del buffer, non impedisce totalmente che un buffer overflow possa essere sfruttato. La sovrascrittura delle variabili locali può fare molto per ottenere il controllo su un processo. Phyrfox ha anche fatto ottimi punti sul perché questo non sarebbe stato all'altezza delle aspettative dei moderni sistemi operativi.

    
risposta data 07.08.2015 - 22:39
fonte

Leggi altre domande sui tag