Comment faire fonctionner la vérification CRL et OSCP sur iOS?

9

Je n'arrive pas à faire fonctionner les CRL sur iOS. J'ai créé deux cas de test. J'ai un certificat valide délivré par une autorité de certification. J'ai un autre certificat valide émis par une autorité de certification, mais l'autorité de certification a ajouté ce certificat à sa liste de révocation de certificats.

J'ai ensuite configuré une stratégie de révocation qui permet la vérification de la liste de révocation de certificats et requiert qu'elle réussisse.

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
}

Je m'attends à ce que le certificat qui se trouve sur la liste de révocation de certificats ne soit pas approuvé et que le certificat qui est propre soit approuvé.

Compte tenu de la configuration ci-dessus, les deux échouent car non fiables. Si je retire le kSecRevocationRequirePositiveResponsedrapeau, les deux réussissent. J'ai essayé toutes les différentes permutations d'utiliser uniquement OSCP ou seulement CRL, et rien ne fonctionne comme je m'y attendais.

Documentation des pommes pour les SecPolicyCreateRevocationétats:

Il n'est généralement pas nécessaire de créer une stratégie de révocation vous-même, sauf si vous souhaitez remplacer le comportement par défaut du système, par exemple pour forcer une méthode particulière, ou pour désactiver complètement la vérification de la révocation.

L'utilisation de la SecPolicyCreateBasicX509stratégie uniquement permet aux deux de réussir (lorsque le deuxième certificat doit échouer), est-ce que le comportement par défaut d'Apple est de ne pas effectuer de vérification CRL?

J'ai attaché CharlesProxy à mon appareil et exécuté le code plusieurs fois tout en écoutant tout le trafic réseau, et aucune demande sortante ne va jamais à la liste de révocation de certificats, ce qui explique pourquoi tous échouent lorsque l' RequirePositiveResponseindicateur est vérifié.

J'ai également essayé de naviguer directement de l'appareil vers la CRL à l'aide d'un URLRequest, et j'ai pu obtenir les données CRL sur l'appareil sans aucun problème.

La vérification CRL n'est-elle pas prise en charge via la bibliothèque de sécurité Apple? Si c'est le cas, quelqu'un a-t-il trouvé la configuration pour qu'elle réponde correctement? Quelles sont les alternatives utilisées par Bing pour effectuer la validation CRL, je suppose que les applications mobiles haute sécurité traitant dans le quartier financier ou d'autres zones sensibles ne permettraient pas cet écart de couverture.

MISE À JOUR Pour comparaison, j'ai couru encertutil -f -urlfetch -verify MYCERT.cerutilisant certutil, et j'ai attaché Fiddler à la boîte exécutant la commande. Je reçois les résultats attendus qu'iOS ne me donne pas et je vois une demande sortante vers la CRL via HTTP via fiddler.

J'ai créé une prime pour générer un peu plus d'intérêt à ce sujet. J'espère que quelqu'un a plus de détails sur ce qui est mal fait ci-dessus, ou pourquoi cela ne fonctionne pas sur iOS.

Unome
la source

Réponses:

7

Sur les plateformes Apple, les clients ne vérifient pas la liste de révocation de certificats (CRL) des autorités de certification, ni n'utilisent OCSP par défaut.

Les plates-formes Apple prennent cependant en charge l'agrafage OCSP et proposent également un mécanisme appelé Revocation Enhancement, qui pourrait en effet conduire à un appel OCSP, voir les détails ci-dessous.

Agrafage OCSP

D'abord une explication de l'agrafage OCSP:

L' agrafage OCSP (Online Certificate Status Protocol) , officiellement connu sous le nom d' extension TLS Certificate Status Request , est une norme de vérification de l'état de révocation des certificats numériques X.509. 1 Il permet au présentateur d'un certificat de supporter les coûts de ressources impliqués dans la fourniture de réponses OCSP (Online Certificate Status Protocol) en ajoutant ("agrafage") une réponse OCSP horodatée signée par l'AC à la prise de contact TLS initiale, éliminant ainsi le besoin pour que les clients contactent l'AC, dans le but d'améliorer à la fois la sécurité et les performances.

voir https://en.wikipedia.org/wiki/OCSP_stapling

Différences entre OCSP et OCSP Stapling

Si un client se connecte à un serveur dans un flux OCSP traditionnel et récupère le certificat, il vérifie si le certificat reçu a été révoqué en faisant une demande à l'autorité de certification. Cela présente certains inconvénients, par exemple, une connexion réseau supplémentaire est requise, les informations ne sont pas cryptées et représentent donc un problème de confidentialité des données.

Grâce à l'agrafage OCSP, le serveur demande à l'autorité de certification des informations de révocation signées et les ajoute à la négociation TLS.

Cela signifie également que lorsque vous utilisez l'agrafage OCSP, vous ne voyez pas de demande OCSP depuis iOS vers un serveur CA.

Inconvénients de l'agrafage OCSP

Le serveur auquel vous vous connectez doit prendre en charge l'agrafage OCSP. Cela ne protège pas non plus contre les serveurs malveillants.

Ce sont les principales raisons pour lesquelles Apple propose une amélioration de la révocation.

Amélioration de la révocation d'Apple

Voici comment ça fonctionne:

  • les entrées des journaux de transparence des certificats sont collectées par Apple
  • avec ces informations, Apple recueille des informations sur les révocations des autorités de certification
  • ces informations agrégées sont ensuite automatiquement mises à la disposition de tous les clients Apple régulièrement
  • sur la base de ces informations, lorsqu'une application iOS tente de se connecter au serveur avec un certificat révoqué, elle effectue une vérification supplémentaire via OCSP.

Exigence

La seule condition requise pour qu'une application prenne en charge cela est que le certificat de serveur utilisé soit ajouté à un journal de transparence des certificats. Normalement, une autorité de certification le fait déjà, mais vous devez vérifier que le certificat de domaine figure dans les journaux de transparence actifs pour les certificats publics, par exemple en utilisant le lien suivant: https://transparencyreport.google.com/https/certificates

WWDC 2017, session 701

Il y a une excellente session WWDC dans laquelle ce sujet et les motivations d'Apple sont expliqués en détail: WWDC 2017, session 701: https://developer.apple.com/videos/play/wwdc2017/701/

Vers la minute 12 h 10, un ingénieur Apple explique en détail le sujet de la révocation. Vers 15h30, elle explique que l'OCSP normal nécessiterait l'utilisation d'API supplémentaires.

Test d'agrafage OCSP sur iOS

Pour un test, nous avons besoin d'un serveur qui prend en charge l'agrafage OCSP et utilise un certificat révoqué: https://revoked.grc.com (trouvé ce serveur dans cette réponse de défaut de serveur: https://serverfault.com/a/645066 )

Ensuite, nous pouvons essayer de se connecter à partir d'iOS avec un petit programme de test qui essaie de télécharger la réponse HTML et de la produire sur la console.

Sur la base des informations de la session WWDC mentionnées ci-dessus, la tentative de connexion doit échouer.

...
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()
}

Si nous exécutons la routine ci-dessus dans le simulateur iOS, nous pouvons utiliser Wireshark pour vérifier si une réponse OCSP horodatée signée par l'autorité de certification est agrafée à la négociation TLS.

Avec nslookup revoked.grc.comnous obtenons l'adresse IP du serveur et pouvons filtrer dans Wireshark avec ip.addr==4.79.142.205.

Dans la capture d'écran, on peut voir que le certificat a le statut revoked.

Wirehark

Donc, en jetant un œil à la console Xcodes, on peut voir la sortie suivante:

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 abandonne la tentative de connexion au serveur avec une erreur TLS.

Test revoked.badssl.com

revoked.badssl.com ne prend pas en charge l'agrafage OCSP.

Si nous examinons les détails du certificat de https://revoked.badssl.com , nous pouvons découvrir:

Si l'on télécharge le fichier .crl (2,5 Mo) et émet un

openssl crl -inform DER -text -in ssca-sha2-g6.crl | grep 0371B58A86F6CE9C3ECB7BF42F9208FC

on peut voir que ce certificat est révoqué via CRL.

Fait intéressant, ni Safari, ni Chrome, ni iOS ne reconnaissent ce statut révoqué. Seul Mozilla Firefox affiche un message d'erreur ( le certificat du pair a été révoqué. Code d'erreur: SEC_ERROR_REVOKED_CERTIFICATE ).

La raison pourrait être que le certificat a été renouvelé il y a seulement quelques jours et n'a donc pas encore trouvé sa place dans toutes les listes locales de révocation de navigateurs et de systèmes d'exploitation.

Stephan Schlecht
la source
Grande information ici. Merci pour la réponse réfléchie. Comme j'ai continué à rechercher ce sujet, j'ai vu la même chose que vous, le support CRL est abandonné par les principaux navigateurs / OS et l'agrafage OCSP semble être le nouveau mécanisme de sécurité recommandé. Dans la vidéo de la WWDC, le représentant Apple déclare: "Malheureusement, nos plateformes NE vérifient PAS la révocation par défaut actuellement". Ce que j'ai trouvé à travers mes expériences, c'est que non seulement il n'est pas pris en charge par défaut, mais il n'est pas du tout pris en charge (même si vous forcez les paramètres) @Stephan Schlecht
Unome