2013-06-24 10 views
6

Voglio garantire che le librerie client (attualmente in Python, Ruby, PHP, Java e .NET) siano configurate correttamente e non funzionino correttamente quando i certificati SSL non sono validi. Il documento di Shmatikov, The Most Dangerous Code in the World: Validating SSL Certificates in Non-Browser Software, rivela quanto sia confusa la convalida SSL, quindi voglio testare accuratamente i possibili errori.Come si può verificare che una libreria client SSL stia verificando correttamente il certificato del server a cui si connette?

Basato su una ricerca di un certificato non è valido se:

  • Viene utilizzato prima della sua data di attivazione
  • Viene utilizzato dopo la data di scadenza
  • E 'stato revocato
  • Certificate hostname don' t corrisponde al nome host del sito
  • La catena del certificato non contiene un'autorità di certificazione attendibile

Idealmente, penso che avrei un caso di test per ciascuno dei casi non validi. A tal fine Attualmente sto testando un HTTP sito accessibili su HTTPS, che porta ad un fallimento che posso verificare in un test in questo modo:

self.assertRaises(SSLHandshakeError, lambda: api.call_to_unmatched_hostname()) 

Questo è incompleto (solo copre un caso) e potenzialmente sbagliato, così ...

Come è possibile verificare che il software non del browser convalidi correttamente i certificati SSL?

+2

https://badssl.com/ offre un'ottima selezione di certificati scadenti. Dovrebbero fornire un buon inizio ai casi di test. –

risposta

5

Prima di tutto, avrete bisogno di una raccolta di certificati SSL, in cui ognuno ha solo una cosa sbagliata. È possibile generare questi utilizzando lo strumento da riga di comando openssl. Ovviamente, non è possibile firmarli con una CA radice affidabile. Dovrai utilizzare la tua CA. Per fare in modo che la convalida correttamente, è necessario installare il certificato CA nelle librerie client. È possibile farlo in Java, ad esempio, utilizzando il pannello di controllo.

Una volta ottenuti i certificati, è possibile utilizzare lo strumento "openssl s_server" per servire un socket SSL utilizzando ciascuno di essi. Ti suggerisco di mettere un certificato su ogni porta.

Ora è necessario utilizzare la libreria client per connettersi a una porta e verificare che venga visualizzato il messaggio di errore corretto.

So che Python per impostazione predefinita non esegue la convalida del certificato (consultare il manuale per httplib.HTTPSConnection). Tuttavia, m2crypto fa la convalida. Java per impostazione predefinita esegue la convalida. Non so altre lingue.

Altri casi che è possibile verificare: 1) Nomi host con caratteri jolly. 2) Concatenamento certificato. So che c'era un bug nei vecchi browser dove se avevi un certificato A firmato dalla radice, A poteva quindi firmare B, e B apparirebbe valido. Si suppone che SSL si fermi con i flag sui certificati e A non avrebbe il flag "can". Tuttavia, questo non è stato verificato in alcuni vecchi browser.

Buona fortuna! Sarei interessato a sentire come vai avantihostname

Paul

4
  • certificato non corrispondono sito hostname

    Questo è probabilmente il più facile da controllare, e il fallimento (per fallire) v'è certamente una buona indicazione che qualcosa è sbagliato. La maggior parte dei certificati per servizi noti utilizza solo nomi host per la propria identità, non gli indirizzi IP. Se, invece di chiedere https://www.google.com/, si chiede https://173.194.67.99/ (ad esempio) e funziona, c'è qualcosa di sbagliato.

Per gli altri, è possibile che si desideri generare la propria CA di prova.

  • catena certificato non contiene un'autorità di certificazione attendibile

    È possibile generare un certificato di prova utilizzando il test CA (o un certificato auto-firmato), ma lasciare che la lista di CA di sistema predefinito essere utilizzato per la verifica. Il client di test non dovrebbe riuscire a verificare quel certificato.

  • Viene utilizzato prima della sua data di attivazione, Viene utilizzato dopo la data di scadenza

    È possibile generare i certificati di prova utilizzando il test CA, con notBefore/notAfter date che compongono la data corrente non valida. Quindi, utilizzare la CA di prova come CA attendibile per la verifica: il client di test non deve convalidare il certificato a causa delle date.

  • E 'stato revocato

    Questa è probabilmente la più difficile da impostare, a seconda di come la revoca è pubblicata. Ancora una volta, genera alcuni certificati di test che hai revocato immediatamente, utilizzando la tua CA di prova. Alcuni strumenti prevedono di essere configurati con un set di file CRL accanto al set di CA attendibili. Ciò richiede alcune impostazioni per il test stesso, ma pochissime impostazioni online: questo è probabilmente il più semplice. È anche possibile configurare un repository di revoca online locale, ad es. utilizzando punti di distribuzione CRL o OCSP.

Il test PKI può essere più complesso di quello in generale. Una suite di test completa richiederebbe una buona conoscenza delle specifiche (RFC 5280). In effetti, potrebbe essere necessario verificare le date per tutti i certificati intermedi, nonché vari attributi per ciascun certificato nella catena (ad esempio utilizzo delle chiavi, vincoli di base, ...).

In generale, le librerie client separano il processo di verifica in due operazioni: verificando che il certificato sia attendibile (la parte PKI) e verificando che sia stato rilasciato all'entità a cui si desidera connettersi (la parte di verifica del nome host). Ciò è certamente dovuto al fatto che questi sono specificati in documenti diversi (RFC 3280/5280 e RFC 2818/6125, rispettivamente).

Da un punto di vista pratico, i primi due punti per verificare quando si utilizza una libreria SSL sono:

  • Che cosa succede quando ci si connette a un host noto, ma con un identificatore diverso per il quale l'isn certificato valido (come il suo indirizzo IP invece dell'host)?
  • Cosa accade quando ci si connette a un certificato che si sa non può essere verificato da alcun gruppo predefinito di ancore affidabili (ad esempio, un certificato autofirmato o dalla propria CA).

La mancata connessione/verifica deve avvenire in entrambi i casi. Se tutto funziona, a meno di implementare una suite di test PKI completa (che richiede una certa esperienza), spesso è necessario controllare la documentazione di tale libreria SSL per vedere come queste verifiche possono essere attivate.

A parte gli errori, un buon numero di problemi menzionati in questo documento sono dovuti al fatto che alcune implementazioni di libreria hanno fatto supporre che spettasse ai propri utenti sapere cosa stavano facendo, mentre la maggior parte dei loro utenti sembra ho ipotizzato che la biblioteca stesse facendo la cosa giusta per impostazione predefinita. (Infatti, anche quando la libreria sta facendo la cosa giusta per impostazione predefinita, non c'è certamente carenza di programmatori che vogliono semplicemente sbarazzarsi del messaggio di errore, anche se rende la loro applicazione non sicura.) Mi sembra giusto dire che assicurarsi che le funzionalità di verifica siano attivate sarebbe sufficiente nella maggior parte dei casi.

Per quanto riguarda lo stato di alcune implementazioni esistenti:

  • Python: c'è stato un cambiamento tra il Python 2.xe Python 3.x. Il modulo ssl di Python 3.2 ha un metodo match_hostname che Python 2.7 non ha. urllib.request.urlopen in Python 3.2 ha anche un'opzione per configurare i file CA, che il suo equivalente Python 2.7 non ha. (Detto questo, se non è impostato, la verifica non verrà eseguita. Non sono sicuro della verifica del nome host.)

  • Java: la verifica è attivata per impostazione predefinita sia per PKI che per nome host per HttpsUrlConnection, ma non per il nome host quando si utilizza direttamente SSLSocket, a meno che non si stia utilizzando Java 7 e si configura il suo SSLParameters utilizzando setEndpointIdentificationAlgorithm("HTTPS") (ad esempio).

  • PHP: per quanto ne so, fopen("https://.../") non eseguirà alcuna verifica.

Problemi correlati