In che modo un buffer underflow può portare all'esecuzione di codice in modalità remota su 64 bit?

6

Ho il seguente pseudo-codice riepilogato in C89 da una libreria server ssh che fornisce solo l'accesso a cose come git-shell ( /bin/bash è sostituito con il programma da eseguire, quindi non è possibile fare qualcos'altro ) :

struct _raw_uncapped_ssh_string { // no limit on the size of the string;
    uint32_t len;
    char non_null_terminated_string[]; // by protocol design it have a minimum length of 1
};
typedef struct _raw_uncapped_ssh_string raw_ssh_string;
union buffer {
       void * uncapped_zlib_decompressed_network_data; 
       // yes, the size is uncapped, so it’s possible to put 4Gb of
       // data in it that would be copied later into memory. zlib 
       // allow easily to turn some Mb in Gb of data, but it’s not 
       // the point of the question.

       raw_ssh_string st;
};
get_command (compressed_network_data) {
    size_t len;
    char * command;
    buffer string=uncompress_to_buffer(compressed_network_data);
    len=ntohl(string.st.len)+1;
    command=malloc(len+1);
    command[len]=0;

    // here’s the point, both the string length and content as 
    // well it’s supplied size is controlled by the attacker.
    memcpy(command,string.st.data,len); 

    return command;
}

Ecco come viene eseguito il comando più tardi (la stringa command è invariata dopo get_command() ) .

const char *args[]={"/bin/bash",command,NULL}; // /bin/bash isn’t the shell, it has been replaced by git‑shell.

// redirect the program output to the network.
dup2(stdin, 0);
dup2(stdout,1);
dup2(stdout,2);
close(stdin);
close(stdout);

//if this return execution failed and print an error message
return execv(args[0],(char * const *)args); // I don’t know which is the system, so I can’t know about the libc behaviour.

Non posso fare memcpy(command,string.st.data,0) dal momento che il terzo membro di memcpy ha una dimensione minima di 1, e nel mio contesto, size_t usa un intero a 64 bit, non posso eseguire un buffer overflow, poiché c'è len .

Tutto quello che posso fare è impostare len su un valore maggiore di quello assegnato a string.st.data . Questo è un underflow del buffer che mi consente di leggere la memoria non allocata.
Posso leggere la memoria del server, tuttavia, non riesco a vedere quali dati sensibili un server ssh pubblico può contenere (nel mio caso l'elenco di utenti che possono eseguire ssh è pubblico) .

Così un underflow del buffer su memcpy consente l'esecuzione di codice in modalità remota?

    
posta user2284570 30.10.2015 - 15:31
fonte

2 risposte

2

In generale, no, non è possibile utilizzare un buffer underflow per l'esecuzione di codice in modalità remota. Dato che i dati controllati dagli aggressori non lasciano mai lo spazio allocato, non ha mai la capacità di prendere il controllo del flusso di esecuzione del programma.

Un buffer underflow ha il potenziale per altri tipi di attacchi, come la divulgazione di informazioni (se il programma sta contando sul contenuto originale del buffer cancellato dai nuovi dati).

    
risposta data 17.12.2015 - 07:53
fonte
0

does a buffer underflow on memcpy allow remote code execution ?

Un underflow del buffer può consentire a un utente malintenzionato di sovrascrivere i puntatori di funzioni situati nelle regioni della memoria prima dell'array in questione. Se quei puntatori di funzione sono fatti per puntare allo shellcode, quel codice shell può essere eseguito quando vengono richiamati in seguito.

Inoltre, l'espressione array[-u] in cui u ha un tipo non firmato può comportare un accesso oltre la fine dell'array (un overflow del buffer ) quando -u è uguale o maggiore del numero di elementi.

In questo pezzo di codice un po 'oscuro, sembra che ci sia solo il rischio di underflow del buffer quando int ha un dominio più ampio di uint32_t , poiché ntohl(string.st.len)+1 causerebbe il valore uint32_t da convertire in un int genere. Se stai cercando una garanzia contro underflow del buffer , utilizza il suffisso letterale intero U (cioè ntohl(string.st.len)+1U ).

Se ritieni che ntohl(string.st.len) possa restituire un valore inferiore al valore massimo per quel tipo di unsigned, quindi len=ntohl(string.st.len)+1 risulterà nel valore massimo, malloc(len+1) causerà wrapping non firmato così tu finiremo invocando malloc(0) e poi command[len]=0 scriverà bene e veramente oltre la fine dell'array. Quindi, naturalmente, anche ha un problema con memcpy(command,string.st.data,len); .

Gli underflow e gli overflow del buffer non sono l'unico rischio. Se non controlli il valore restituito di malloc e malloc restituisce NULL , allora un dereferenziamento puntatore nullo può essere utilizzato per causare l'esecuzione arbitraria di codice. Ciò implica che dovresti avere un metodo per comunicare malloc di errori al chiamante. Implica inoltre che è possibile utilizzare lo stesso metodo per verificare e comunicare il problema del wrapping al chiamante.

    
risposta data 18.04.2017 - 06:28
fonte

Leggi altre domande sui tag