Come posso autenticare una connessione client in modo sicuro?

6

Diciamo che ho un server in ascolto sulla porta 1234. Ho qualche software client che deve essere in grado di connettersi a questa porta. Ma voglio impedire agli utenti malintenzionati di aggirare il software client e collegarsi alla porta con altri mezzi (come in una console o in un altro software).

Il software client affidabile e il server possono condividere una chiave segreta, se necessario (posso vivere con la possibilità che la chiave possa essere estratta dal binario). Preferirei non inviare una chiave in chiaro, ma i dati dopo l'autenticazione possono essere in chiaro. Nello specifico, sto cercando di capire come sconfiggere un attacco man-in-the-middle in cui l'utente malintenzionato sta utilizzando il software client fidato per calcolare le risposte corrette alle sfide del server.

Posso arrivarci da qui?

Potrei fare in modo che la porta di ascolto del server si leghi solo a localhost e richieda che i client accedano prima alla macchina tramite ssh. Quindi il software client potrebbe utilizzare una libreria ssh per eseguire un comando sul server che si connette alla porta locale (in questo scenario, l'utente malintenzionato non sarebbe in grado di utilizzare ssh per accedere alla macchina perché non avrebbe la password). Ma poi tutto il mio traffico è criptato, che è un sovraccarico aggiuntivo. Forse c'è un programma simile a ssh che fa solo l'autenticazione ma poi lascia il canale in chiaro dopo quello?

Aggiornamento:

Ho eseguito un test per determinare il sovraccarico associato alla crittografia di tutto il traffico.

spew.rb restituisce 10 milioni di righe di 100 caratteri.

CONTROLLO:

fantius@machine> time /home/fantius/spew.rb > /dev/null

real    0m35.015s
user    0m34.934s
sys     0m0.084s

la parte superiore mostra il 25% di utilizzo della CPU (un core completo, di quattro core)

TEST:

fantius@machine> time ssh localhost /home/fantius/spew.rb > /dev/null

real    0m40.704s
user    0m19.981s
sys     0m1.400s

la parte superiore mostra il 45% di utilizzo della CPU (quasi due core completi)

La percentuale di messaggi probabilmente supera la maggior parte delle connessioni tra più macchine.

    
posta Thomas Pornin 13.01.2011 - 20:32
fonte

2 risposte

8

Per prima cosa, suggerisco di evitare ipotesi sul sovraccarico della crittografia. Dovresti misurare . Il mio PC del 2001 era già abbastanza potente per trasferire i dati con SSH alla massima velocità di un collegamento a 100 Mbit / s, con crittografia. Il mio PC attuale, un Core2 comune a 2,4 GHz, può eseguire la crittografia AES a 167 Mbyte al secondo (sì, megabyte , non megabit), più che sufficiente per gigabit ethernet e che utilizza un singolo core - - Ho altri tre core.

Se si desidera autenticare un client, il client deve avere qualcosa di speciale che l'utente malintenzionato previsto non ha. Crittograficamente parlando, qualche pezzo di dati segreti, che chiameremo un chiave perché è quello che sono le chiavi: un pezzo di dati segreti, usato in un algoritmo che si presume non segreto. Si noti che questo comporta un difetto strutturale che non può essere realmente evitato: chiunque abbia accesso in lettura al codice del client può eseguire un reverse engineering e recuperare la chiave. Questo può essere reso un po 'più difficile attraverso tecniche di offuscamento del codice, ma non al punto da renderlo impossibile.

Inoltre, vuoi autenticare la connessione , cioè non solo l'atto di iniziare il tunnel dei dati, ma anche i dati effettivamente trasferiti. In caso contrario, l'utente malintenzionato potrebbe dirottare la connessione una volta eseguita la fase di autenticazione. Ciò implica l'utilizzo di un controllo dell'integrità crittografica, che è chiamato MAC . A quel punto, aggiungere la crittografia è facile. SSH utilizza sia la crittografia simmetrica che un MAC.

Al di fuori dei blocchi predefiniti, suggerisco le seguenti soluzioni:

  1. Usa SSH. Il client si connette tramite SSH e utilizza una password hardcoded per autenticarsi (la password è quindi la chiave di cui parlavo sopra). Man-in-the-middle è evitato dal solito meccanismo di SSH, cioè il client SSH dovrebbe conservare una copia della chiave pubblica del server.

  2. Usa SSL / TLS. Questo è molto simile a quello che succede con SSH. Il client sa che parla al server corretto perché la chiave pubblica del server viene presentata come parte di un certificato X.509, che è firmato e può essere convalidato dal client. Il cliente deve avere conoscenza della chiave pubblica dell'autorità di certificazione. In alternativa, il client potrebbe già conoscere il certificato del server e verificare che questo sia lo stesso certificato rispetto a quello inviato dal server. Una volta stabilito il tunnel, con controlli di crittografia e integrità, il cliente può semplicemente inviare la sua chiave "così com'è" per dimostrare la sua identità.

  3. Usa SSL / TLS con un certificato client. In questa configurazione, il client ha una coppia di chiavi pubblica / privata. La chiave privata è la chiave di cui stavo parlando. La chiave pubblica è codificata in un certificato che il client mostra durante l'handshake SSL. Tutto questo è roba SSL standard, quindi supportata dalle librerie SSL esistenti. Rispetto alla soluzione 2, ciò evita la necessità di includere un messaggio di invio della chiave nel protocollo dell'applicazione e consente anche l'uso di suite di crittografia solo MAC, nel caso in cui risulti che la crittografia è troppo costosa dal punto di vista computazionale (che dubito) .

  4. Utilizza la chiave del client in un Scambio chiavi autenticato tramite password per ottenere una chiave di sessione comune , quindi utilizzato per un MAC (e possibilmente per la crittografia). Il punto dei protocolli PAKE è che possono tollerare i segreti di bassa entropia, cioè le password che si adattano al cervello degli utenti umani. Esecuzione di un tunnel MAC ha alcune sottigliezze quindi il modo corretto è quello di utilizzare un protocollo esistente. Questo quindi richiede TLS con SRP . La "password" è codificata nel client (e sebbene SRP tolleri password brevi, nulla ti impedisce di usare una password lunga e molto casuale). La bellezza della cosa è che questo sopprime qualsiasi mucking con certificati o note chiavi pubbliche. Il client è autenticato in virtù della sua conoscenza della password. Contemporaneamente, il server è anche autenticato tramite password dal client. Come bonus aggiuntivo, con SRP, il server memorizza solo una porzione di dati derivata da password, che non è direttamente utilizzabile dal client, quindi un utente malintenzionato che legge il database del server non ottiene l'accesso automatico come "client".

La mia soluzione preferita è ovviamente quella con SRP. È elegante . Sfortunatamente, SRP è piuttosto nuovo, quindi non tutte le implementazioni SSL / TLS lo supportano. Ma GnuTLS fa.

    
risposta data 13.01.2011 - 21:30
fonte
1

Quando tutto è detto e fatto, non esiste un modo reale per impedire a un client di terze parti di connettersi alla porta se tutto è progettato per funzionare senza interazione umana.

L'unico modo in cui puoi prevenire questo problema è se hai un sistema non hackerabile (o più esattamente, più difficile da hackerare) che fornisce il pezzo di identificazione, cioè un utente, e quelle credenziali vengono trasferite in un hash crittografato modo. Se qualche informazione "segreta" che si intende utilizzare come credenziale viene archiviata nell'applicazione, come un utente malintenzionato sarà in grado di accedere a tali informazioni.

    
risposta data 13.01.2011 - 20:47
fonte

Leggi altre domande sui tag