Come far funzionare CRL e OSCP Checking su iOS?


9

Non riesco a far funzionare i CRL su iOS. Ho creato due casi di test. Ho un certificato valido, rilasciato da una CA. Ho un altro certificato valido, rilasciato da una CA, ma la CA ha aggiunto quel certificato al suo CRL.

Ho quindi impostato una politica di revoca che abilita il controllo CRL e richiede che abbia esito positivo.

func crlValidationTest(trustedCert: SecCertificate, certToVerify: SecCertificate) -> Bool {

    let basicPolicy = SecPolicyCreateBasicX509()

    let crlPolicy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod | kSecRevocationCRLMethod | kSecRevocationRequirePositiveResponse)!

    var trust: SecTrust?

    SecTrustCreateWithCertificates(NSArray(object: certToVerify), NSArray(objects: basicPolicy, crlPolicy), &trust)
    SecTrustSetAnchorCertificates(trust!, NSArray(object: trustedCert))
    SecTrustSetNetworkFetchAllowed(trust!, true)

    var trustResult = SecTrustResultType.invalid

    guard SecTrustEvaluate(trust!, &trustResult) == errSecSuccess else {
        return false
    }

    return trustResult == SecTrustResultType.proceed || trustResult == SecTrustResultType.unspecified
}

La mia aspettativa è che il certificato che si trova sul CRL non sia attendibile e che il certificato pulito sia attendibile.

Data la configurazione di cui sopra, entrambi falliscono perché non attendibili. Se rimuovo la kSecRevocationRequirePositiveResponsebandiera, entrambi riescono. Ho provato tutte le diverse permutazioni di usare solo OSCP o solo CRL e niente funziona come mi aspetterei.

Documentazione sulle mele per gli SecPolicyCreateRevocationstati:

Di solito non è necessario creare autonomamente una politica di revoca a meno che non si desideri ignorare il comportamento predefinito del sistema, ad esempio per forzare un metodo particolare o disabilitare del tutto il controllo di revoca.

L'utilizzo della sola SecPolicyCreateBasicX509politica consente ad entrambi di avere successo (quando la seconda certificazione dovrebbe fallire), quindi il comportamento predefinito di Apple non prevede affatto il controllo CRL?

Ho collegato CharlesProxy al mio dispositivo e ho eseguito il codice più volte durante l'ascolto di tutto il traffico di rete, e nessuna richiesta in uscita è mai andata al CRL, il che spiega perché tutti falliscono quando RequirePositiveResponseviene spuntato il flag.

Ho anche provato a navigare direttamente dal dispositivo al CRL utilizzando un URLRequeste sono stato in grado di ottenere i dati CRL sul dispositivo senza problemi.

Il controllo CRL non è supportato tramite la libreria Apple Security? Se lo è, qualcuno ha capito la configurazione per farlo rispondere correttamente? Quali alternative vengono utilizzate da Bing per eseguire la convalida CRL, presumo che le applicazioni mobili ad alta sicurezza che operano nel distretto finanziario o in altre aree sensibili non consentirebbero questo gap di copertura.

AGGIORNAMENTO Per il confronto, ho eseguitocertutil -f -urlfetch -verify MYCERT.cerutilizzando certutil e ho collegato Fiddler alla casella che esegue il comando. Ricevo i risultati attesi che iOS non mi sta dando e vedo una richiesta in uscita al CRL via HTTP tramite fiddler.

Ho creato una taglia per generare un po 'più di interesse in questo. Spero che qualcuno abbia maggiori dettagli su ciò che viene fatto di sbagliato sopra o sul perché questo non funziona su iOS.

Risposte:


7

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.comotteniamo 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.

Wireshark

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.


Grandi informazioni qui. Grazie per la risposta premurosa. Dato che ho continuato a studiare questo argomento, ho visto lo stesso di te, il supporto CRL è stato abbandonato dai principali browser / sistemi operativi e la pinzatura OCSP sembra essere il nuovo meccanismo di sicurezza raccomandato. Nel video del WWDC il rappresentante di Apple afferma: "Purtroppo le nostre piattaforme NON verificano attualmente la revoca per impostazione predefinita". Quello che ho scoperto attraverso i miei esperimenti è che non solo non è supportato per impostazione predefinita, ma non è supportato affatto (anche se imponi le impostazioni) @Stephan Schlecht
Unome
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.