Bagaimana agar Pemeriksaan CRL dan OSCP berfungsi di iOS?

9

Saya tidak bisa mengaktifkan CRL di iOS. Saya telah membuat dua test case. Saya memiliki sertifikat yang valid, dikeluarkan oleh CA. Saya memiliki sertifikat lain yang valid, dikeluarkan oleh CA, tetapi CA telah menambahkan sertifikat itu ke CRL-nya.

Saya kemudian menyiapkan kebijakan pencabutan yang memungkinkan pemeriksaan CRL, dan mengharuskan itu berhasil.

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
}

Harapan saya adalah bahwa sertifikat yang ada di CRL akan tidak dipercaya, dan sertifikat yang bersih akan dipercaya.

Dengan konfigurasi di atas, keduanya gagal karena tidak dipercaya. Jika saya menghapus kSecRevocationRequirePositiveResponsebendera, keduanya berhasil. Saya sudah mencoba semua permutasi yang berbeda hanya menggunakan OSCP atau hanya CRL, dan tidak ada yang bekerja seperti yang saya harapkan.

Dokumentasi apel untuk SecPolicyCreateRevocationnegara:

Biasanya tidak perlu membuat sendiri kebijakan pencabutan, kecuali jika Anda ingin mengesampingkan perilaku sistem default, misalnya untuk memaksa metode tertentu, atau untuk menonaktifkan pemeriksaan pencabutan seluruhnya.

Dengan hanya menggunakan SecPolicyCreateBasicX509kebijakan, keduanya memungkinkan untuk berhasil (ketika sertifikat kedua harus gagal), jadi apakah perilaku default Apple tidak melakukan pengecekan CRL sama sekali?

Saya memasang CharlesProxy ke perangkat saya, dan menjalankan kode beberapa kali sambil mendengarkan semua lalu lintas jaringan, dan tidak ada permintaan keluar yang pergi ke CRL yang menjelaskan mengapa semua gagal ketika RequirePositiveResponsebendera diperiksa.

Saya juga mencoba menavigasi langsung dari perangkat ke CRL menggunakan URLRequest, dan bisa mendapatkan data CRL di perangkat tanpa masalah.

Apakah pemeriksaan CRL tidak didukung melalui perpustakaan Apple Security? Jika ya, adakah yang tahu konfigurasi untuk membuatnya merespons dengan benar? Apa alternatif yang digunakan untuk melakukan validasi CRL, saya berasumsi aplikasi mobile dengan keamanan tinggi yang berurusan di distrik keuangan atau area sensitif lainnya tidak akan mengizinkan celah cakupan ini.

PEMBARUAN Sebagai perbandingan, saya berlaricertutil -f -urlfetch -verify MYCERT.cermenggunakan certutil, dan saya menempelkan Fiddler ke kotak yang menjalankan perintah. Saya menerima hasil yang diharapkan yang tidak diberikan iOS kepada saya, dan saya melihat permintaan keluar ke CRL melalui HTTP melalui fiddler.

Saya telah membuat hadiah untuk menghasilkan lebih banyak minat dalam hal ini. Saya berharap seseorang memiliki rincian lebih lanjut tentang apa yang dilakukan salah di atas, atau mengapa ini tidak berfungsi di iOS.

Unome
sumber

Jawaban:

7

Pada platform Apple, klien tidak memeriksa Daftar Pencabutan Sertifikat (CRL) CA, juga tidak menggunakan OCSP secara default.

Namun platform Apple mendukung stapel OCSP dan sebagai alternatif mereka menyediakan mekanisme yang mereka sebut Peningkatan Pencabutan, yang memang bisa mengarah pada panggilan OCSP, lihat detail di bawah.

Stapel OCSP

Pertama penjelasan tentang stapel OCSP:

Stapel Online Certificate Status Protocol (OCSP) , yang secara resmi dikenal sebagai ekstensi Permintaan Status Sertifikat TLS , adalah standar untuk memeriksa status pencabutan sertifikat digital X.509. 1 Memungkinkan presenter sertifikat menanggung biaya sumber daya yang terlibat dalam menyediakan respons Online Certificate Status Protocol (OCSP) dengan menambahkan ("penjepretan") respons OCSP bertanda waktu yang ditandatangani oleh CA ke jabat tangan TLS awal, menghilangkan kebutuhan. bagi klien untuk menghubungi CA, dengan tujuan meningkatkan keamanan dan kinerja.

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

Perbedaan antara OCSP dan Stapel OCSP

Jika klien terhubung ke server dalam aliran OCSP tradisional dan mengambil sertifikat, itu memeriksa apakah sertifikat yang diterima telah dicabut dengan membuat permintaan ke CA. Ini memiliki beberapa kelemahan, misalnya, koneksi jaringan tambahan diperlukan, informasi tidak dienkripsi dan karena itu merupakan masalah privasi data.

Melalui stapel OCSP, server meminta informasi pencabutan yang ditandatangani dari CA dan menambahkannya ke jabat tangan TLS.

Ini juga berarti, saat menggunakan stapel OCSP, Anda tidak melihat permintaan OCSP dari iOS ke server CA.

Kerugian dari Stapel OCSP

Server yang Anda hubungkan harus mendukung stapel OCSP. Ini juga tidak melindungi terhadap server jahat.

Itulah alasan utama mengapa Apple memberikan Peningkatan Pencabutan.

Peningkatan Pencabutan Apple

Begini cara kerjanya:

  • entri log sertifikat transparansi dikumpulkan oleh Apple
  • dengan info ini Apple mengumpulkan informasi tentang pencabutan dari CA
  • informasi yang dikumpulkan ini kemudian secara otomatis disediakan untuk semua klien Apple secara teratur
  • berdasarkan informasi ini, ketika aplikasi iOS mencoba terhubung ke server dengan sertifikat yang dicabut, ia melakukan pemeriksaan tambahan melalui OCSP.

Kebutuhan

Satu-satunya persyaratan bagi aplikasi untuk mendukung ini adalah bahwa sertifikat server yang digunakan ditambahkan ke log transparansi sertifikat. Biasanya CA sudah melakukannya, tetapi Anda harus memeriksa bahwa sertifikat domain ada di log transparansi aktif untuk sertifikat publik, misalnya dengan menggunakan tautan berikut: https://transparencyreport.google.com/https/certificates

WWDC 2017, sesi 701

Ada sesi WWDC yang sangat baik di mana topik ini dan motif Apple dijelaskan secara rinci: WWDC 2017, sesi 701: https://developer.apple.com/videos/play/wwdc2017/701/

Sekitar menit 12:10 seorang insinyur Apple menjelaskan seluruh topik pencabutan secara rinci. Sekitar pukul 15:30 dia menjelaskan bahwa OCSP normal akan membutuhkan penggunaan API tambahan.

Uji Stapel OCSP di iOS

Untuk pengujian, kami memerlukan server yang mendukung stapel OCSP dan menggunakan sertifikat yang dicabut: https://revoked.grc.com (temukan server ini dalam jawaban serverfault ini: https://serverfault.com/a/645066 )

Kemudian kita dapat mencoba terhubung dari iOS dengan program uji kecil yang mencoba mengunduh respons HTML dan mengeluarkannya ke konsol.

Berdasarkan informasi dari sesi WWDC yang disebutkan di atas, upaya koneksi harus gagal.

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

Jika kita menjalankan rutinitas di atas dalam Simulator iOS, kita dapat menggunakan Wireshark untuk memeriksa apakah respons OCSP yang bertanda waktu yang ditandatangani oleh CA di-stapler ke jabat tangan TLS.

Dengan nslookup revoked.grc.comkami mendapatkan alamat IP dari server dan dapat menyaring di Wireshark dengan ip.addr==4.79.142.205.

Di tangkapan layar orang dapat melihat, bahwa sertifikat memiliki status revoked.

wireshark

Jadi dengan melihat konsol Xcodes kita dapat melihat output berikut:

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 membatalkan upaya untuk terhubung ke server dengan kesalahan TLS.

Tes dicabut.badssl.com

revoked.badssl.com tidak mendukung stapel OCSP.

Jika kita melihat detail sertifikat https://revoked.badssl.com , kita dapat mengetahui:

Jika seseorang mengunduh file .crl (2.5MB) dan mengeluarkan a

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

orang dapat melihat bahwa sertifikat ini dicabut melalui CRL.

Menariknya, baik Safari, Chrome, maupun iOS tidak mengenali status yang dicabut ini. Hanya Mozilla Firefox yang menampilkan pesan kesalahan ( Sertifikat Peer telah dicabut. Kode kesalahan: SEC_ERROR_REVOKED_CERTIFICATE ).

Alasannya mungkin karena sertifikat itu diperbarui hanya beberapa hari yang lalu dan karena itu belum menemukan jalan ke semua daftar pencabutan browser dan sistem operasi lokal.

Stephan Schlecht
sumber
Informasi hebat di sini. Terima kasih atas jawaban yang bijaksana. Ketika saya terus meneliti topik ini, saya telah melihat hal yang sama dengan Anda, dukungan CRL sedang dijatuhkan oleh browser utama / OS dan stapel OCSP tampaknya menjadi mekanisme keamanan baru yang direkomendasikan. Dalam video WWDC perwakilan Apple menyatakan: "Sayangnya platform kami JANGAN memeriksa pencabutan secara default saat ini". Apa yang saya temukan melalui eksperimen saya adalah bahwa tidak hanya itu tidak didukung secara default, tetapi tidak didukung sama sekali (bahkan jika Anda memaksakan pengaturan) @Stephan Schlecht
Unome