На платформах Apple клиенты не проверяют список отзыва сертификатов (CRL) ЦС и не используют OCSP по умолчанию.
Однако платформы Apple поддерживают сшивание OCSP и, в качестве альтернативы, предоставляют механизм, который они вызываютУлучшение отзыва, которое действительно может привести к вызову OCSP, см. Подробности ниже.
Сшивание OCSP
Сначала объяснение сшивания OCSP:
Сшивание Онлайновый протокол статуса сертификата (OCSP) , формально известный как Запрос статуса сертификата TLS , является стандартом для проверки статуса отзыва цифровых сертификатов X.509. 1 Позволяет предъявителю сертификата нести затраты ресурсов, связанные с предоставлением ответов OCSP, путем добавления («сшивания») ответа OCSP с меткой времени, подписанного СА, к исходному TLS. рукопожатие, устраняя необходимость для клиентов, чтобы связаться с ЦС, с целью улучшенияи безопасность, и производительность.
см. https://en.wikipedia.org/wiki/OCSP_stapling
Различия между OCSP и OCSP Сшивание
Если клиент подключается к серверу втрадиционный поток OCSP и извлекает сертификат, он проверяет, был ли отозван полученный сертификат, отправляя запрос в ЦС. Это имеет некоторые недостатки, например, требуется дополнительное сетевое соединение, информация не зашифрована и, следовательно, представляет проблему с конфиденциальностью данных.
При сшивании OCSP сервер запрашивает у CA подписанную информацию об отзыве и добавляет еена рукопожатие TLS.
Это также означает, что при использовании сшивания OCSP вы не видите запрос OCSP от iOS к серверу CA.
Недостатки сшивания OCSP
Сервер, к которому вы подключаетесь, должен поддерживать сшивание OCSP. Это также не защищает от вредоносных серверов.
Это основные причины, по которым Apple предоставляет улучшение отзыва.
Улучшение отзыва Apple
Вот как это работает:
- Записи журналов прозрачности сертификатов собираются Apple
- с помощьюэта информация Apple собирает информацию об отзыве из ЦС
- , после чего эта обобщенная информация автоматически становится доступной для всех клиентов Apple на регулярной основе
- на основе этой информации, когда приложение iOS пытается подключитьсяк серверу с отозванным сертификатом, он выполняет дополнительную проверку через OCSP.
Требование
Единственное требование к приложению для поддержки этого заключается в том, чтоиспользуемый сертификат сервера добавляется в журнал прозрачности сертификата. Обычно ЦС уже делает это, но вы должны проверить, что сертификат домена находится в журналах активной прозрачности для открытых сертификатов, например, используя следующую ссылку: https://transparencyreport.google.com/https/certificates
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.
Тест revoked.badssl.com
revoked.badssl.com не поддерживает сшивание OCSP.
Если мы посмотрим на детали сертификатаиз https://revoked.badssl.com, мы можем узнать:
Если загрузить файл .crl (2,5 МБ) и выдать
openssl crl -inform DER -text -in ssca-sha2-g6.crl | grep 0371B58A86F6CE9C3ECB7BF42F9208FC
, можно увидеть, что этот сертификат отозван через CRL.
Интересно, что ни Safari, ни Chrome, ни iOS не распознаютэто аннулированный статус. Только Mozilla Firefox отображает сообщение об ошибке ( Сертификат партнера был отозван. Код ошибки: SEC_ERROR_REVOKED_CERTIFICATE ).
Причиной может быть то, что сертификат был обновлен всего несколько дней назад и поэтому еще не попал во все локальные списки отзыва браузеров и операционных систем.