Як змусити перевірку CRL та OSCP для роботи на iOS?


9

Я не можу заставити CRL працювати на iOS. Я створив два тестові справи. У мене є дійсний сертифікат, виданий ЦА. У мене є ще один справжній сертифікат, виданий ЦО, але КА додав цей сертифікат до свого CRL.

Потім я встановлюю політику відкликання, яка дозволяє перевірити CRL і вимагає, щоб вона була успішною.

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
}

Моє сподівання полягає в тому, що сертифікат, який знаходиться в CRL, буде недовіреним, а чистий сертифікат - довіряти.

Враховуючи вищевказану конфігурацію, обидва виходять з ладу як ненадійні. Якщо я видаляю kSecRevocationRequirePositiveResponseпрапор, обоє досягають успіху. Я спробував усі різні перестановки використання лише OSCP або лише CRL, і нічого не працює так, як я очікував.

Документація щодо яблук для SecPolicyCreateRevocationштатів:

Зазвичай не потрібно самостійно створювати політику відкликання, якщо ви не бажаєте змінити поведінку системи за замовчуванням, наприклад, щоб застосувати певний метод або повністю відключити перевірку скасування.

Використання лише SecPolicyCreateBasicX509політики дозволяє досягти успіху обом (коли другий сертифікат повинен вийти з ладу), то чи поведінка Apple за замовчуванням взагалі не проводить перевірку CRL?

Я приєднав CharlesProxy до свого пристрою і кілька разів запускав код під час прослуховування всього мережевого трафіку, і жоден вихідний запит не надходив до CRL, що пояснює, чому все не вдається, коли RequirePositiveResponseпрапор перевіряється.

Я також намагався переходити безпосередньо з пристрою до CRL за допомогою a URLRequest, і міг отримати дані CRL на пристрої без проблем.

Чи не підтримується перевірка CRL через бібліотеку безпеки Apple? Якщо це так, чи хтось придумав конфігурацію, щоб змусити її правильно відповідати? Які альтернативи використовуються для перевірки CRL, я припускаю, що мобільні додатки високої безпеки, що працюють у фінансовому районі чи інших чутливих районах, не дозволять цього розриву в покритті.

ОНОВЛЕННЯ Для порівняння, я побігcertutil -f -urlfetch -verify MYCERT.cerза допомогою certutil, і я приєднав Fiddler до поля, що виконує команду. Я отримую очікувані результати, які iOS не дає мені, і я бачу вихідний запит до CRL через HTTP через fiddler.

Я створив щедрості, щоб викликати ще якийсь інтерес до цього. Я сподіваюся, що хтось має більш детальну інформацію про те, що робиться неправильно вище, або чому це не працює на iOS.

Відповіді:


7

На платформах Apple клієнти не перевіряють Список відкликань сертифікатів (CRL) ЦС, а також не використовують OCSP за замовчуванням.

Платформи Apple, однак, підтримують з'єднання OCSP, і, як альтернатива, вони забезпечують механізм, який вони називають Revocation Enhancement, який дійсно може призвести до виклику OCSP, див. Деталі нижче.

Зшивання OCSP

Спочатку пояснення зшивання OCSP:

Статус Online Certificate Protocol (OCSP) зшивання , офіційно відоме як запит статусу TLS сертифікат розширення, є стандартом для перевірки стану анулювання X.509 цифрових сертифікатів. 1 Це дозволяє доповідачеві сертифіката нести витрати на ресурси, пов'язані з наданням відповідей на протокол статусу онлайнового сертифіката (OCSP), додавши ("зшиваючи") відповідь OCSP з печаткою часу, підписану ЦА, до початкового рукостискання TLS, усуваючи необхідність щоб клієнти могли звертатися в ЦА з метою підвищення як безпеки, так і ефективності.

див. https://en.wikipedia.org/wiki/OCSP_stapling

Відмінності між OCSP та OCSP Stapling

Якщо клієнт підключається до сервера в традиційному потоці OCSP і отримує сертифікат, він перевіряє, чи був відкликаний отриманий сертифікат, подавши запит до адміністративного центру. Це має деякі недоліки, наприклад, потрібне додаткове підключення до мережі, інформація незашифрована і тому представляє проблему конфіденційності даних.

Через з'єднання OCSP, сервер запитує підписану інформацію про відкликання від ЦА та додає її до рукостискання TLS.

Це також означає, що при використанні зшивання OCSP ви не бачите запит OCSP з iOS на сервер CA.

Недоліки зшивання OCSP

Сервер, до якого ви підключаєтесь, повинен підтримувати з'єднання OCSP. Це також не захищає від шкідливих серверів.

Це основні причини, чому Apple надає посилення відкликання.

Підвищення відкликання Apple

Ось як це працює:

  • Записи журналів прозорості сертифікатів збираються компанією Apple
  • з цією інформацією Apple збирає інформацію про відкликання у ЦА
  • потім ця зведена інформація автоматично автоматично стає доступною для всіх клієнтів Apple
  • виходячи з цієї інформації, коли програма iOS намагається підключитися до сервера відкликаним сертифікатом, вона здійснює додаткову перевірку через OCSP.

Вимога

Єдина вимога програми, яка це підтримує, - це те, щоб використаний сертифікат сервера був доданий до журналу прозорості сертифікатів. Зазвичай ЦА вже робить це, але ви повинні перевірити, чи сертифікат домену є в активних журналах прозорості для публічних сертифікатів, наприклад, використовуючи наступне посилання: https://transparencyreport.google.com/https/certificate

WWDC 2017, сесія 701

Існує чудова сесія WWDC, в якій ця тема та мотиви Apple детально пояснені: WWDC 2017, сесія 701: https://developer.apple.com/videos/play/wwdc2017/701/

Близько хвилини 12:10 інженер Apple детально пояснює всю тему відкликання. Близько 15:30 вона пояснює, що звичайний OCSP вимагатиме використання додаткових API.

Тест зшивання OCSP на iOS

Для тесту нам потрібен сервер, який підтримує з'єднання OCSP і використовує відкликаний сертифікат: https://revoked.grc.com (знайдений сервер у цій відповіді сервера за замовчуванням: https://serverfault.com/a/645066 )

Тоді ми можемо спробувати підключитися з iOS за допомогою невеликої тестової програми, яка намагається завантажити відповідь HTML і вивести його на консоль.

На підставі згаданої вище інформації з сесії WWDC спроба підключення повинна бути невдалою.

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

Якщо ми виконаємо вищевказану процедуру в iOS Simulator, ми можемо використовувати Wireshark, щоб перевірити, чи відповідна OCSP відмітка часу, підписана CA, прив'язана до рукостискання TLS.

З nslookup revoked.grc.comми отримуємо IP - адреса сервера і може фільтрувати в Wireshark з ip.addr==4.79.142.205.

На скріншоті видно, що сертифікат має статус revoked.

проводка

Отже, заглянувши в консоль Xcodes, можна побачити наступний вихід:

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 припиняє спробу підключення до сервера з помилкою TLS.

Тест відкликаний.badssl.com

revoked.badssl.com не підтримує з'єднання OCSP.

Якщо ми подивимося на деталі сертифіката https://revoked.badssl.com , ми можемо дізнатися:

Якщо ви завантажите файл .crl (2,5 Мб) і видаєте a

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

видно, що цей сертифікат відкликаний через CRL.

Цікаво, що ні Safari, ні Chrome, ні iOS не визнають цей статус відкликаного. Лише Mozilla Firefox відображає повідомлення про помилку ( сертифікат Peer було відкликано. Код помилки: SEC_ERROR_REVOKED_CERTIFICATE ).

Причиною може бути те, що сертифікат було поновлено лише кілька днів тому, і тому він ще не знайшов шлях до всіх місцевих списків відкликання браузерів та операційних систем.


Чудова інформація тут. Дякую за продуману відповідь. Оскільки я продовжував досліджувати цю тему, я бачив те саме, що і ви, підтримка CRL відміняється основними браузерами / ОС, а зшивання OCSP є новим рекомендованим механізмом безпеки. У відеозаписі WWDC Apple представив: "На жаль, наші платформи НЕ перевіряють скасування скасування за замовчуванням". Що я виявив у своїх експериментах, це те, що він не лише не підтримується за замовчуванням, але він взагалі не підтримується (навіть якщо ввімкнути налаштування) @Stephan Schlecht
Unome
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.