Canali heap per proteggere i puntatori di funzione negli oggetti heap

4

Mi chiedo se qualcuno abbia precedentemente proposto, valutato o implementato la seguente misura per rafforzare i sistemi contro sovraccarichi di buffer basati su heap: fondamentalmente, stack di canarini, ma applicati prima dei puntatori di funzione negli oggetti memorizzati nell'heap piuttosto che prima del ritorno indirizzi memorizzati nello stack.

Considera una struttura come

struct whatever {
    int blah;
    char buf[256];
    void (*fp)(); // a function pointer
}

Notare che se c'è un sovraccarico che scrive oltre la fine del campo buf , sarà possibile sovrascrivere il campo del puntatore della funzione fp .

Un compilatore potrebbe plausibilmente difendersi introducendo un canarino - un valore casuale segreto - memorizzato tra il buffer e il puntatore della funzione. Fondamentalmente, il compilatore trasformerebbe il layout della struttura in

struct whatever {
    int blah;
    char buf[256];
    unsigned int canary; // inserted by compiler; not exposed to source code
    void (*fp)(); // a function pointer
}

Ad esempio, il compilatore potrebbe organizzare la scrittura del campo canary con un valore segreto globale ogni volta che il programma scrive su fp , e potrebbe verificare che il valore di canary rimanga invariato ogni volta che il programma legge da fp .

Questo è fondamentalmente l'analogo dei canarini dello stack, ma dove ora ci concentriamo sulla protezione dei puntatori di funzione nell'heap invece degli indirizzi di ritorno nello stack. Sembra un'idea naturale.

Qualcuno ha proposto questo prima? Qualcuno ha prototipato o valutato il costo delle prestazioni di fare qualcosa del genere? Esistono ostacoli non evidenti alla distribuzione (oltre al fatto che richiede modifiche ai compilatori, proprio come fanno i canarini)?

Ricerca che ho fatto: sono a conoscenza dell'idea di inserire le pagine di protezione tra gli oggetti nell'heap, ma è diverso (protegge da overflow di heap che vanno oltre i limiti di un singolo oggetto, mentre sto parlando su qualcosa da proteggere dagli overflow dell'heap che rimangono all'interno dell'area di un singolo oggetto heap). Ho familiarità con Cruiser e ContraPolice , che posiziona i canarini tra gli oggetti nell'heap, ma che si focalizza anche sugli overflow degli oggetti incrociati piuttosto che sugli overflow degli oggetti interni. Ho anche familiarità con l'uso dei canarini dello stack o con la crittografia puntatore per proteggere i metadati di malloc, ma, ancora una volta, non protegge contro gli overflow degli oggetti e serve a proteggere i metadati di malloc piuttosto che i puntatori di funzione.

    
posta D.W. 05.06.2014 - 01:57
fonte

2 risposte

2

I canarini all'interno di un oggetto si imbattono in un problema pratico: cambia il layout in memoria di questi oggetti. Questo layout deve essere coerente quando viene passato tra, ad esempio, il programma e le librerie. Se hai passato un puntatore di tipo struct whatever * da un programma compilato con questa strumentazione, ad una libreria compilata senza questa strumentazione (ma con la stessa dichiarazione di struct whatever ) , quindi le cose si spezzerebbero, perché alcuni dei campi sarebbero in un offset diverso. Di conseguenza, l'uso di canarini interni per scopi diversi dalla ricerca teorica potrebbe rompere la compatibilità con quasi tutti i codici e le librerie esistenti.

    
risposta data 05.06.2014 - 07:28
fonte
1

Un approccio simile è la funzione di crittografia puntatore, simile a quella utilizzata per proteggere i metadati malloc. Questo è proposto in sezione 2.4 di" Protezione contro gli attacchi di overflow "

L'analisi del libro è favorevole. C'è anche un vecchio articolo su questa tecnica (e altro uno ). Tuttavia, per quanto ne so, questa tecnica non è un uso attivo. Non ho assolutamente idea del perché no; forse sono i problemi di prestazioni e compatibilità; o forse l'NSA ha messo a tacere le persone che lo hanno proposto.

    
risposta data 05.06.2014 - 07:40
fonte

Leggi altre domande sui tag