En las plataformas de Apple, los clientes no verifican la Lista de revocación de certificados (CRL) de las CA ni utilizan OCSP de manera predeterminada.
Sin embargo, las plataformas de Apple son compatibles con el engrapado OCSP y, alternativamente, proporcionan un mecanismo que llaman Mejora de la revocación, que de hecho podría conducir a una llamada OCSP, consulte los detalles a continuación.
Grapado OCSP
Primero una explicación de grapado OCSP:
El grapado del Protocolo de estado de certificado en línea (OCSP) , formalmente conocido como la extensión de Solicitud de estado de certificado TLS , es un estándar para verificar el estado de revocación de los certificados digitales X.509. 1 Permite al presentador de un certificado asumir el costo de los recursos involucrados en proporcionar respuestas del Protocolo de estado de certificado en línea (OCSP) al agregar ("grapar") una respuesta OCSP con sello de tiempo firmado por la CA al protocolo de enlace TLS inicial, eliminando la necesidad para que los clientes se comuniquen con la CA, con el objetivo de mejorar tanto la seguridad como el rendimiento.
ver https://en.wikipedia.org/wiki/OCSP_stapling
Diferencias entre grapado OCSP y OCSP
Si un cliente se conecta a un servidor en un flujo OCSP tradicional y recupera el certificado, verifica si el certificado recibido ha sido revocado mediante una solicitud a la CA. Esto tiene algunas desventajas, por ejemplo, se requiere una conexión de red adicional, la información no está encriptada y, por lo tanto, representa un problema de privacidad de datos.
A través del engrapado OCSP, el servidor solicita una información de revocación firmada de la CA y la agrega al protocolo de enlace TLS.
Esto también significa que, al usar el engrapado OCSP, no ve una solicitud OCSP de iOS a un servidor de CA.
Inconvenientes del grapado OCSP
El servidor al que se está conectando debe admitir el engrapado OCSP. Esto tampoco protege contra servidores maliciosos.
Esas son las razones principales por las que Apple está proporcionando una mejora de revocación.
Mejora de la revocación de Apple
Así es como funciona:
- Apple registra las entradas de los registros de transparencia del certificado
- con esta información, Apple recopila información sobre las revocaciones de las AC
- esta información agregada se pone automáticamente a disposición de todos los clientes de Apple de forma regular
- según esta información, cuando una aplicación de iOS intenta conectarse al servidor con un certificado revocado, realiza una verificación adicional a través de OCSP.
Requisito
El único requisito para que una aplicación lo admita es que el certificado del servidor utilizado se agregue a un registro de transparencia del certificado. Normalmente, una CA ya lo hace, pero debe verificar que el certificado de dominio esté en los registros de transparencia activos para certificados públicos, por ejemplo, utilizando el siguiente enlace: https://transparencyreport.google.com/https/certificates
WWDC 2017, sesión 701
Hay una excelente sesión de WWDC en la que se explican en detalle este tema y los motivos de Apple: WWDC 2017, sesión 701: https://developer.apple.com/videos/play/wwdc2017/701/
Alrededor del minuto 12:10, un ingeniero de Apple explica todo el tema de revocación en detalle. Alrededor de las 15:30, explica que el OCSP normal requeriría el uso de API adicionales.
Prueba de grapado OCSP en iOS
Para una prueba, necesitamos un servidor que admita el engrapado OCSP y utilice un certificado revocado: https://revoked.grc.com
(encontró este servidor en la respuesta predeterminada de este servidor: https://serverfault.com/a/645066 )
Luego podemos intentar conectarnos desde iOS con un pequeño programa de prueba que intenta descargar la respuesta HTML y enviarla a la consola.
Según la información de la sesión de WWDC mencionada anteriormente, el intento de conexión debería fallar.
...
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 ejecutamos la rutina anterior en el simulador de iOS, podemos usar Wireshark para verificar si una respuesta OCSP con marca de tiempo firmada por la CA está grapada al apretón de manos TLS.
Con nslookup revoked.grc.com
nosotros obtenemos la dirección IP del servidor y podemos filtrar en Wireshark con ip.addr==4.79.142.205
.
En la captura de pantalla se puede ver que el certificado tiene el estado revoked
.
Echando un vistazo a la consola Xcodes, se puede ver el siguiente resultado:
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 cancela el intento de conectarse al servidor con un error de TLS.
Prueba revocada.badssl.com
revoked.badssl.com no admite el engrapado OCSP.
Si echamos un vistazo a los detalles del certificado de https://revoked.badssl.com , podemos descubrir:
Si uno descarga el archivo .crl (2.5MB) y emite un
openssl crl -inform DER -text -in ssca-sha2-g6.crl | grep 0371B58A86F6CE9C3ECB7BF42F9208FC
se puede ver que este certificado se revoca a través de CRL.
Curiosamente, ni Safari ni Chrome ni iOS reconocen este estado revocado. Solo Mozilla Firefox muestra un mensaje de error ( se ha revocado el certificado de igual. Código de error: SEC_ERROR_REVOKED_CERTIFICATE ).
La razón podría ser que el certificado se renovó hace solo unos días y, por lo tanto, aún no ha llegado a todas las listas locales de revocación de navegadores y sistemas operativos.