Ya hemos hablado de
certificate pinning en el blog (e incluso "en directo"
en la RECSI en estos días).
Chrome era el único navegador que, además de ser el primero,
implementaba el "pinning" de serie. Internet Explorer se apoya por ahora
precariamente en EMET y
Firefox en un addon llamado
Certificate Patrol. Pero desde su versión 32, según los titulares, comenzará a "pinear"... pero esto es solo el comienzo y
aunque ha sido anunciado a bombo y platillo, no es del todo cierto...
|
¿En qué quedamos según estos titulares y la prueba técnica?... ¿Firefox 32 suporta Public Key Pinning o no? |
Brevemente, el "pineo" de certificados propone que el navegador
"recuerde" cuáles son los certificados válidos de una web, para que, en
el caso de robo o creación ilegítima (y posterior MiTM), el usuario sea
alertado de que no se está conectando al sitio correcto
aunque la negociación SSL sea válida. Varios incidentes muy famosos han contribuido a que esta opción sea cada vez más utilizada.
Firefox, en su versión 32,
ha implementado varias mejoras.
Para empezar, ha eliminado de su lista de certificados confiables
varios creados solo con claves de 1024 bits. La lista de
Firefox es
totalmente diferente a la de Windows (y Chrome), y bastante más estricta
a la hora de elegir "certificados de confianza", con lo que, con este
paso,
se vuelve todavía más paranoica. Con respecto al "pinning",
lo que ha hecho es complementar lo que ya tenían (HSTS) con el PKP
(Public Key Pinning). Pero, cuidado, hay dos "tipos" de PKP y
Firefox
solo ha implementado una parte...
de ahí la confusión. Veamos qué es cada cosa.
HSTS
El
estándar HTTP Strict Transport Security o HSTS.
Se trata de una especificación que permite obligar a que, en una
página, se use siempre HTTPS aunque el usuario no lo escriba en la barra
del navegador. Para ello, el servidor que lo desee debe enviarle una
cabecera al navegador, del tipo:
Strict-Transport-Security: max-age=16070400; includeSubDomains
La primera vez que visita la web, recuerda que a partir de entonces y
durante el tiempo especificado en max-age, debe hacerlo por HTTPS. Poco
más que añadir sobre esta tecnología.
Public key pinning dinámico
Esto también son unas cabeceras que
permiten a un servidor indicarle al navegador cuáles son sus certificados "habituales" y por cuánto tiempo debe recordarlos. Si
alguna vez se produce un ataque de hombre en el medio y suplantación de
certificados, el navegador se quejará de que no eran los mismos que
recuerda que le indicó el servidor.
Así, los dueños de los sitios pueden declarar qué certificados son realmente suyos.
|
Ejemplo de cabeceras de HSTS y Public Key Pinning sobre HTTP devuelto por una página |
¿Y cómo funciona exactamente?
Imaginemos que el servidor A mantiene una cadena de certificados
"normal", con su CA1, CAInt, y CRaíz. El administrador es cuidadoso, y
decide hacer uso de PKP. Le indica a su servidor o su página que
devuelva las cabeceras correspondientes declarando sus certificados.
Para ello tiene que calcular la codificación base64 del sha256 del
atributo SubjectPublicKeyInfo del certificado codificado con DER (
parece difícil pero no lo es). Usar
el SubjectPublicKeyInfo (SPKI) permite que el certificado cambie aunque
se mantenga la clave pública dentro, y por tanto es más flexible.
Así que le dice a su servidor web o programa que añada estas cabeceras en sus repuestas HTTP:
Public-Key-Pins: max-age=31536000;
pin-sha256=base64(sha256(SPKI(CA1));
pin-sha256= base64(sha256(SPKI(CAInt);
Donde, en realidad, está "pineando" dos de los tres certificados de su
cadena de certificación, y avisando al mundo de que, si alguno cambia en
otra visita, es necesario sospechar... excepto el "hoja".
En algún momento, un usuario los visita, y el navegador (
si implementa el PKP dinámico)
los recuerda. Pero imaginemos que en algún momento posterior el
usuario es atacado, y visita sin querer A', que resulta pertenecer a un
atacante y que usa otros tres certificados diferentes (CA1', CAint', y
CRaíz') en su cadena de certificación.
El navegador de la víctima, antes de establecer comunicación ni mostrar
nada de ese servidor, se conecta y se trae los certificados de A'.
Calcula los hashes de la cadena, y se mueve por esta regla:
"Si los pines (hashes que representan a los certificados) de la
cadena de certificados del sitio que visito, hace intersección con los
hashes que recuerdo que me envió hace tiempo, todo está correcto. Si no,
mostraré una alerta".
|
Fallo de pinning en Firefox.
Fuente: http://monica-at-mozilla.blogspot.com.es/2014/08/firefox-32-supports-public-key-pinning.html |
O sea, algún elemento de estos dos conjuntos:
- base64(sha256(SPKI(CA1)), base64(sha256(SPKI(CAInt))
- base64(sha256(SPKI(CA1')), base64(sha256(SPKI(CAInt')) , base64(sha256(SPKI(CRaíz'))
Debe ser común para que no haya problemas.
En resumen, todo va bien si el conjunto de certificados de A (legítimo) intersecta con el de A' (atacante).
A partir de aquí, cabe reconocer que
hay escenarios poco probables pero posibles para eludir la seguridad de esta solución,
y que el dueño del servidor debe tener cuidado para no generar
demasiados falsos positivos. PKP, por ejemplo, no protege del compromiso
de claves privadas de certificados intermedios, por ejemplo, puesto que
la intersección se daría en muchos casos. Si el administrador del sitio
es muy paranoico y "pinea" solo el certificado hoja,
el ataque es mucho menos probable, pero se eleva la cantidad de potenciales falsos positivos. Así que habitualmente, lo que hacen es (además está muy recomendado por el
RFC)
meter un certificado de respaldo para no "bloquearse" por si envían una
cabecera que obliga a recordar a los navegadores un certificado durante
demasiado tiempo pero poco después expira o se invalida por lo que sea.
PKP "incrustado"
Pues simplemente, es lo mismo que ya se ha explicado pero en este caso
los pines (la codificación en base64 del sha256 del SPKI del
certificado) no los envía dinámicamente el servidor,
sino que son incrustados en el código del navegador. Así los "recuerda", y el tiempo durante el que los recuerda viene determinado por actualizaciones del programa.
Esto no es ningún problema en sí, solo que a largo plazo es
insostenible y proporciona muy poca flexibilidad y potencia. Y esto es
lo que ha hecho, en su versión 32, Firefox.
Conclusiones
En rigor, es cierto que
Firefox sí ha implementado Public Key Pinning, pero no Public Key Pinning sobre HTTP.
Eso es algo que se menciona en la nota de prensa como posibilidad, pero
no queda totalmente claro que será algo que se hará a futuro. Y si nos
fijamos no solo en que en la versión 32 ha hecho un PKP "no dinámico"
sino que además ha "pineado" solo una pequeña parte de dominios
importantes... la cosa queda en un comienzo prometedor, pero nada
definitivo para Firefox como los titulares parecen comunicar.
Y es que en esta versión 32, solo se "pinean" (incrustados) los dominios
de Twitter y algunos de la propia Mozilla. En el futuro (quizás en su
versión 33) meterán en el código los certificados de Google, Dropbox y
en definitiva, todos los que ya implementa Chronium en su código a
partir de la versión 34, que no son pocos.
En resumen, los titulares inducen a error si no se especifica que el PKP
será "built in" (incrustado) y que por ahora se incrustan muy pocos
dominios. El objetivo final, más adelante (en un futuro no determinado)
es implementar PKP
dinámico, y es el camino que ahora comienza Firefox... la noticia no es, precisamente, que lo haya concluido.