Su piattaforme Apple, i client non controllano né l'elenco di revoche di certificati (CRL) delle CA né usano OCSP per impostazione predefinita.
Tuttavia, le piattaforme Apple supportano la pinzatura OCSP e in alternativa forniscono un meccanismo che chiamano Revocation Enhancement, che potrebbe effettivamente portare a una chiamata OCSP, vedere i dettagli di seguito.
Pinzatura OCSP
Innanzitutto una spiegazione della pinzatura OCSP:
La pinzatura OCSP (Online Certificate Status Protocol) , formalmente nota come estensione Richiesta stato certificato TLS , è uno standard per il controllo dello stato di revoca dei certificati digitali X.509. 1 Consente al presentatore di un certificato di sostenere il costo delle risorse coinvolto nella fornitura di risposte OCSP (Online Certificate Status Protocol) aggiungendo ("pinzatura") una risposta OCSP timestamp firmata dalla CA all'handshake iniziale TLS, eliminando la necessità per i clienti di contattare la CA, con l'obiettivo di migliorare sia la sicurezza che le prestazioni.
vedi https://en.wikipedia.org/wiki/OCSP_stapling
Differenze tra pinzatura OCSP e OCSP
Se un client si connette a un server in un flusso OCSP tradizionale e recupera il certificato, verifica se il certificato ricevuto è stato revocato facendo una richiesta alla CA. Ciò presenta alcuni svantaggi, ad esempio è necessaria una connessione di rete aggiuntiva, le informazioni non sono crittografate e rappresentano quindi un problema di privacy dei dati.
Tramite la pinzatura OCSP, il server richiede alla CA informazioni di revoca firmate e le aggiunge all'handshake TLS.
Ciò significa anche che, quando si utilizza la pinzatura OCSP, non si vede una richiesta OCSP da iOS a un server CA.
Svantaggi della pinzatura OCSP
Il server a cui ti stai connettendo deve supportare la pinzatura OCSP. Anche questo non protegge da server dannosi.
Questo è il motivo principale per cui Apple fornisce un miglioramento della revoca.
Miglioramento della revoca di Apple
Ecco come funziona:
- le voci dei registri di trasparenza dei certificati vengono raccolte da Apple
- con queste informazioni Apple raccoglie informazioni sulle revoche dalle autorità di certificazione
- queste informazioni aggregate vengono quindi automaticamente rese disponibili a tutti i clienti Apple su base regolare
- sulla base di queste informazioni, quando un'app iOS tenta di connettersi al server con un certificato revocato, esegue un controllo aggiuntivo tramite OCSP.
Requisiti
L'unico requisito per un'app per supportare questo è che il certificato del server utilizzato venga aggiunto a un registro di trasparenza del certificato. Normalmente una CA lo fa già, ma è necessario verificare che il certificato di dominio sia nei registri di trasparenza attivi per i certificati pubblici, ad esempio utilizzando il seguente link: https://transparencyreport.google.com/https/certificates
WWDC 2017, sessione 701
C'è un'eccellente sessione del WWDC in cui questo argomento e i motivi di Apple sono spiegati in dettaglio: WWDC 2017, sessione 701: https://developer.apple.com/videos/play/wwdc2017/701/
Intorno alle 12:10 un ingegnere Apple spiega in dettaglio l'intero argomento della revoca. Verso le 15:30 spiega che il normale OCSP richiederebbe l'uso di API aggiuntive.
Test di pinzatura OCSP su iOS
Per un test abbiamo bisogno di un server che supporti la pinzatura OCSP e utilizzi un certificato revocato: https://revoked.grc.com
(trovato questo server in questa risposta predefinita del server: https://serverfault.com/a/645066 )
Quindi possiamo provare a connetterci da iOS con un piccolo programma di test che tenta di scaricare la risposta HTML e inviarla alla console.
Sulla base delle informazioni della sessione WWDC sopra menzionate, il tentativo di connessione dovrebbe fallire.
...
let session = URLSession(configuration: .default)
...
func onDownloadAction() {
let url = URL(string: "https://revoked.grc.com")!
self.download(from: url) { (result, error) in
if let result = result {
print("result: " + result)
} else {
print("download failed")
if let error = error {
print("error: \(error)")
}
}
}
}
func download(from url: URL, completion: @escaping(String?, Error?)->Void) {
let dataTask = self.session.dataTask(with: url) { data, response, error in
guard let data = data else {
if let error = error {
completion(nil, error)
return
}
completion(nil, NSError(domain: "DownloadFailure", code: 0, userInfo:nil))
return
}
guard let response = response as? HTTPURLResponse else {
completion(nil, NSError(domain: "ResponseFailure", code: 0, userInfo:nil))
return
}
print("http status: \(response.statusCode)")
let res = String(bytes: data, encoding: .utf8)
completion(res, nil)
}
dataTask.resume()
}
Se eseguiamo la routine di cui sopra nel simulatore iOS, possiamo usare Wireshark per verificare se una risposta OCSP timestamp firmata dalla CA viene pinzata con l'handshake TLS.
Con nslookup revoked.grc.com
otteniamo l'indirizzo IP del server e possiamo filtrare in Wireshark conip.addr==4.79.142.205
.
Nello screenshot si può vedere che il certificato ha lo stato revoked
.
Quindi, dando un'occhiata alla console Xcodes, si può vedere il seguente output:
2019-10-12 21:32:25.734382+0200 OCSPTests[6701:156558] ATS failed system trust
2019-10-12 21:32:25.734526+0200 OCSPTests[6701:156558] Connection 1: system TLS Trust evaluation failed(-9802)
2019-10-12 21:32:25.734701+0200 OCSPTests[6701:156558] Connection 1: TLS Trust encountered error 3:-9802
2019-10-12 21:32:25.734787+0200 OCSPTests[6701:156558] Connection 1: encountered error(3:-9802)
2019-10-12 21:32:25.737672+0200 OCSPTests[6701:156558] Task <12408947-689F-4537-9642-C8F95E86CA62>.<1> HTTP load failed, 0/0 bytes (error code: -1200 [3:-9802])
download failed
error: Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x6000037f8510>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=(
"<cert(0x7fda78828200) s: revoked.grc.com i: DigiCert SHA2 Secure Server CA>",
"<cert(0x7fda7882b200) s: DigiCert SHA2 Secure Server CA i: DigiCert Global Root CA>"
), NSUnderlyingError=0x600000be9170 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x6000037f8510>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=(
"<cert(0x7fda78828200) s: revoked.grc.com i: DigiCert SHA2 Secure Server CA>",
"<cert(0x7fda7882b200) s: DigiCert SHA2 Secure Server CA i: DigiCert Global Root CA>"
)}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://revoked.grc.com/, NSErrorFailingURLStringKey=https://revoked.grc.com/, NSErrorClientCertificateStateKey=0}
iOS interrompe il tentativo di connettersi al server con un errore TLS.
Test revoked.badssl.com
revoked.badssl.com non supporta la pinzatura OCSP.
Se diamo un'occhiata ai dettagli del certificato di https://revoked.badssl.com , possiamo scoprire:
Se si scarica il file .crl (2,5 MB) e si emette a
openssl crl -inform DER -text -in ssca-sha2-g6.crl | grep 0371B58A86F6CE9C3ECB7BF42F9208FC
si può vedere che questo certificato è revocato tramite CRL.
È interessante notare che né Safari né Chrome né iOS riconoscono questo stato revocato. Solo Mozilla Firefox visualizza un messaggio di errore ( il certificato del peer è stato revocato. Codice di errore: SEC_ERROR_REVOKED_CERTIFICATE ).
Il motivo potrebbe essere che il certificato è stato rinnovato solo pochi giorni fa e pertanto non ha ancora trovato la sua strada in tutti gli elenchi revoca locali di browser e sistemi operativi.