На платформах 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 ).
Причиною може бути те, що сертифікат було поновлено лише кілька днів тому, і тому він ще не знайшов шлях до всіх місцевих списків відкликання браузерів та операційних систем.