2015-01-12 3 views
5

Per coloro che hanno utilizzato l'implementazione C++ del protocollo Protocollo Google, come si gestiscono messaggi malevoli o malformati? Ad esempio, si blocca o continua a funzionare? La mia app riceverà certamente dati dannosi a un certo punto e non voglio che si blocchi ogni volta che viene ricevuto un messaggio non valido. Questa è l'unica risposta che ho trovato su questo numero (google mailing list).Google Protocol Buffers Stabilità e sicurezza dell'implementazione C++ di fronte a dati dannosi

Esiste una revisione specifica per problemi di sicurezza prima del rilascio del codice. Per almeno le implementazioni C++ e Java, ci sono varie salvaguardie per proteggere da dati corrotti o dannosi. Esistono dei limiti sulla dimensione complessiva del messaggio fornita dalla libreria protobuf (CodedInputStream :: SetTotalBytesLimit); fornisce anche un limite di ricorsione per impedire che messaggi profondamente annidati possano far esplodere lo stack. Esistono altri dettagli di implementazione interna per evitare cose come l'esaurimento della memoria (in particolare la ricezione di messaggi che indicano un enorme valore delimitato dalla lunghezza).

+1

utilizzare [HMAC] (http://en.wikipedia.org/wiki/Hash-based_message_authentication_code) o almeno una qualche forma di checksum. – tumdum

+1

I checksum non sono una difesa contro la malizia. L'autenticazione è, almeno con adeguate implementazioni crittografiche. – MSalters

+0

@MSalters L'autenticazione non è davvero una difesa contro la malvagità ... Permette solo di identificare (supponendo che le tue chiavi/certs non siano state compromesse) chi è malizioso ... – twalberg

risposta

12

Uso i buffer del protocollo google C++ in un'applicazione web-facing molto attenta alla sicurezza.

Osservando il codice generato, tutto il lavoro di deserializzazione è delegato al codice generato automaticamente nel metodo <Message-Type>::MergePartialFromCodedStream di ogni messaggio. Questi metodi sono generati con controlli completi su tipi di dati e lunghezze e finora non abbiamo avuto alcun problema.

Un'area di attacco che potresti voler chiudere tu stesso è nell'inquadratura dei dati di protobuf - i buffer di protocollo stessi non serializzano la dimensione complessiva del messaggio serializzato nello stream in alcun tipo di intestazione standardizzata, quindi potresti volere a (come faccio io) avvolgere tutti i messaggi del protocollo buffer in un frame. Per i miei scopi l'intestazione del frame contiene semplicemente una dimensione del messaggio, il che significa che sono in grado di determinare i requisiti di memoria del messaggio prima di tentare di leggerlo dal cavo, per non parlare di decodificarlo.

A questo punto è possibile effettuare un semplice controllo per rifiutare i messaggi (o rilasciare la connessione) se la dimensione è eccessivamente grande.

È possibile eseguire ulteriori operazioni per avvolgere questo frame in uno schema di inserimento di chiavi pubbliche al fine di prevenire il dirottamento man-in-the-middle della sessione, se questo è un problema.

sovraccarichi di buffer all'interno di un messaggio (ad esempio una stringa diventando troppo lungo) non può succedere perché bytes e string campi sono rappresentati internamente da std::string, che cresce automaticamente la sua impronta memoria, come dati vengono aggiunti ad esso.

Tuttavia:

Non c'è alcuna garanzia che i clienti maligni non cercherà di codificare i messaggi validi che contengono dati non validi. Ad esempio, se l'applicazione server prende un nome di metodo dalla stringa di dati, cerca il suo indirizzo e lo chiama, quindi questo è un vettore ovvio per l'attacco.

Non si dovrebbe mai consentire ai dati client di trovare il codice del server senza un controllo completo che l'operazione sia specificamente consentita.

Alcuni esempi di questo che non si deve mai fare:

  1. consentire al cliente di inviare SQL in un campo di testo
  2. consentire al cliente di inviare righe di comando, che in seguito si passano a system(), exec(), spawn() ecc ...
  3. consentire al cliente di inviare il nome di una libreria condivisa e un nome di funzione all'interno di esso ...

e così via.

+2

Sono d'accordo con questa risposta. Aggiungerò: come errore di sicurezza, non direi mai che il mio codice è sicuro al 100%. Ma come autore della maggior parte delle librerie Protobuf C++ e Java, posso dirti che non sono mai stato messo al corrente di alcuna vulnerabilità di sicurezza in questo codice. :) –

+0

"... i buffer di protocollo stessi non serializzano la dimensione complessiva del messaggio serializzato nello stream in alcun tipo di intestazione standardizzata ..." Sarebbe la dimensione di un oggetto GPB essere registrata, ad esempio, in un'intestazione HTTP? Forse dovrei prima chiedere: gli oggetti GPB sono scambiati via HTTP? –

+1

@RogerCostello è possibile registrarlo in un'intestazione personalizzata, nell'intestazione della lunghezza del contenuto o in qualsiasi altro protocollo desiderato. Trasmetto messaggi protobuf su protocolli via cavo, http, messaggi bus, websocket, ecc. –