Sobre el autor Eric Rescorla - Director técnico, Grupo Firefox en MozillaRecientemente, se produjo un incidente en Firefox cuando la mayoría de los complementos (extensiones, complementos) dejaron de funcionar. Esto se debe a un error de nuestra parte: no notamos que uno de los certificados, que se utiliza para firmar los complementos, ha expirado, lo que ha llevado a la desconexión de la gran mayoría de ellos. Ahora que hemos solucionado el problema y la mayoría de los complementos se han restaurado, me gustaría contar en detalle qué sucedió, por qué y cómo lo solucionamos.
Como referencia: extensiones y su firma
Aunque muchos usan Firefox como está listo para usar, el navegador también admite un poderoso mecanismo de extensión. Añaden funciones de terceros a Firefox que amplían las funciones que ofrecemos de forma predeterminada. Actualmente hay más de 15,000 complementos de Firefox: desde el
bloqueo de anuncios hasta la
administración de cientos de pestañas .
Firefox requiere que todos los complementos instalados estén
firmados digitalmente . Este requisito está destinado a proteger a los usuarios de extensiones maliciosas al exigir un estándar mínimo de verificación por parte de los empleados de Mozilla. Antes de presentar este requisito en 2015, tuvimos
serios problemas con las extensiones maliciosas.
La firma funciona a través del "certificado raíz" preinstalado de Firefox. Se almacena sin conexión en el
módulo de seguridad de hardware (HSM) . Cada pocos años, se utiliza para firmar un nuevo "certificado intermedio", que se almacena en línea y se utiliza en el proceso de firma. Cuando la extensión se envía para su firma, generamos un nuevo "certificado de entidad final" temporal y lo firmamos con un certificado intermedio. El certificado de destino se utiliza para firmar la extensión. Visualmente, se ve así:
Tenga en cuenta que cada certificado tiene un "asunto" (al que pertenece el certificado) y un "editor" (signatario). En el caso de un certificado raíz, este es el mismo, pero para otros certificados, el editor es el sujeto que lo firmó.
El punto importante aquí es que cada complemento está firmado con su propio certificado del objeto final, pero casi todos los complementos tienen el mismo certificado intermedio (varios complementos muy antiguos fueron firmados por otro enlace intermedio). Aquí es donde surgió el problema: cada certificado tiene una fecha de vencimiento fija. Antes o después de esta ventana, el certificado no será aceptado y la extensión firmada por este certificado no se puede cargar en Firefox. Desafortunadamente, el certificado intermedio que utilizamos expiró el 4 de mayo después de la 1:00 UTC, e inmediatamente todos los complementos firmados por este certificado quedaron sin verificar y no se pudieron cargar en Firefox.
Aunque todos los complementos expiraron aproximadamente a la una de la mañana, las consecuencias no se sintieron de inmediato. La razón es que Firefox no comprueba constantemente la validez de los complementos. Se verifican aproximadamente cada 24 horas, y el tiempo de verificación es diferente para cada usuario. Como resultado, algunas personas experimentaron problemas de inmediato, algunos mucho más tarde. En Mozilla, nos enteramos por primera vez del problema alrededor de las 6:00 p.m. PST del viernes 3 de mayo e inmediatamente reunimos un equipo para rectificar la situación.
Límite de daño
Tan pronto como entendimos a qué nos enfrentamos, tomamos varias medidas para evitar el deterioro de la situación.
Primero, desactivamos la firma de nuevas incorporaciones. En ese momento era razonable, porque la firma ponía un certificado inválido. Mirando hacia atrás, parece que fue posible abandonar esta función, pero resultó que también entra en conflicto con el ablandamiento del "firmware de fecha fija", que discutiremos a continuación (aunque al final no lo usamos). Por lo tanto, es bueno que hayamos conservado esta opción. Entonces, la firma de nuevas incorporaciones ahora se retrasa.
En segundo lugar, lanzamos inmediatamente una solución rápida que suprime la reverificación de firmas de extensión. La idea era proteger a los usuarios que aún no se han vuelto a probar. Hicimos esto antes de tener cualquier otra solución, y ahora la eliminamos cuando la solución está disponible.
Trabajo paralelo
Teóricamente, la solución a este problema parece simple: hacer un certificado nuevo y válido y volver a emitir cada adición con este certificado. Desafortunadamente, rápidamente determinamos que esto no funcionaría por varias razones:
- Hay muchas extensiones (más de 15,000), y el servicio no está optimizado para la firma masiva, por lo que solo volver a firmar cada complemento llevará más tiempo del que queríamos.
- Después de firmar los complementos, los usuarios deberán obtener un nuevo complemento. Algunos están alojados en servidores Mozilla, y Firefox los actualizará dentro de las 24 horas, pero los usuarios tendrán que actualizar manualmente cualquier complemento que se instale desde otras fuentes, lo cual es muy inconveniente.
En cambio, nos centramos en tratar de desarrollar una solución que solucionara la situación con poca o ninguna intervención manual de los usuarios.
Después de considerar una serie de enfoques, acordamos rápidamente dos estrategias principales que llevamos a cabo en paralelo:
- Parche de Firefox para cambiar la fecha utilizada para verificar el certificado. En este caso, los complementos existentes funcionarán mágicamente de nuevo, pero se requerirá la entrega de una nueva versión de Firefox.
- Genere un nuevo certificado válido y de alguna manera convenza a Firefox para que lo acepte en lugar del existente vencido.
No estábamos seguros de qué funcionaría exactamente, así que decidimos llevar a cabo el trabajo en paralelo e implementar el primero, que se vería como una solución de trabajo. Al final del día, completamos el despliegue de la segunda solución: un nuevo certificado, que describiré con más detalle.
Certificado de reemplazo
Como se mencionó anteriormente, había dos pasos principales a seguir:
- Crea un nuevo certificado válido.
- Instalarlo de forma remota en Firefox.
Para entender por qué esto funciona, necesita saber un poco más sobre cómo Firefox busca complementos. El complemento en sí viene en forma de un paquete de archivos, que incluye la cadena de certificados utilizada para firmarlo. Como resultado, el complemento se verifica de forma independiente si se conoce el certificado raíz, que se configura en Firefox durante la compilación. Sin embargo, como dije, el certificado intermedio estaba roto, por lo que el complemento no era realmente verificable.
Pero resulta que cuando Firefox intenta verificar la extensión, no se limita a usar solo certificados en la extensión misma. En su lugar, intenta crear una cadena de certificados válida, comenzando con el certificado de punto final y continuando con el directorio raíz. El algoritmo es complejo, pero a un nivel alto, comienza con un certificado del objeto final, y luego encuentra un certificado cuyo tema es igual al editor del certificado del objeto final (es decir, un certificado intermedio). En el caso simple, este es solo un enlace intermedio que viene con el complemento, pero puede ser cualquier certificado que el navegador conozca. Si podemos agregar remotamente un nuevo certificado válido, Firefox también intentará construir una cadena de este tipo. La siguiente figura muestra la situación antes y después de instalar un nuevo certificado.

Después de instalar un nuevo certificado, Firefox tiene dos opciones para verificar la cadena de certificados: usar un certificado antiguo no válido (que no funcionará) o usar un nuevo certificado válido (que funcionará). Una característica importante aquí es que el nuevo certificado tiene el mismo nombre de sujeto y clave pública que el certificado anterior, por lo que su firma en el certificado del objeto final es válida. Afortunadamente, Firefox es lo suficientemente inteligente como para probar ambos métodos hasta que encuentre uno que funcione, por lo que la extensión vuelve a ser válida. Tenga en cuenta que esta es la misma lógica que usamos para verificar los certificados TLS, por lo que este es un código relativamente bien entendido que pudimos usar (los lectores familiarizados con WebPKI entenderán que la certificación cruzada funciona de esta manera).
Lo mejor de esta solución es que no requiere un cambio en ninguna extensión existente. Cuando instalamos el nuevo certificado en Firefox, incluso las extensiones con certificados antiguos pasarán la prueba. El truco para entregar un nuevo certificado en Firefox es hacerlo de forma automática y remota, y luego hacer que Firefox verifique dos veces todas las extensiones que pueden haber sido deshabilitadas.
Normandia y sistema de investigación
Irónicamente, la solución al problema fue un tipo especial de extensión llamada
complemento del sistema (SAO). Para los estudios de la audiencia (Estudios), desarrollamos previamente un sistema llamado Normandía, que puede ofrecer SAO a los usuarios de Firefox. Estos SAO se ejecutan automáticamente en el navegador del usuario. Aunque se usan comúnmente para la experimentación, también tienen un amplio acceso a las API internas en Firefox. En este caso, es importante que puedan agregar nuevos certificados a la base de datos de certificados que Firefox usa para verificar extensiones (nota técnica: no agregamos el certificado con ningún privilegio especial; obtiene sus privilegios al firmar con el certificado raíz. Simplemente lo agregamos al grupo de certificados que Firefox puede usar, por lo que no agregamos un nuevo certificado privilegiado en Firefox).
Entonces, la solución aquí es crear un SAO que haga dos cosas:
- Instala el nuevo certificado que hicimos.
- Hace que el navegador vuelva a verificar cada complemento para activar los que se han desconectado.
Pero espera, dices. Los complementos no funcionan, entonces, ¿cómo hacer que SAO funcione? ¡Bueno, lo firmaremos con un nuevo certificado!
Poniendo todo junto ... y ¿por qué tanto tiempo?
Así que ahora tenemos un plan: emitir un nuevo certificado para reemplazar el anterior, crear un complemento del sistema para instalarlo en Firefox e implementarlo en Normandía. Comenzamos a trabajar a las 6:00 p.m. PST del viernes 3 de mayo y enviamos el parche a Normandía a las 2:44 a.m., es decir, menos de 9 horas, y luego pasaron otras 6-12 horas antes de que la mayoría de los usuarios lo recibieran. Este es realmente un muy buen comienzo, pero vi en Twitter una serie de preguntas sobre por qué no podríamos hacerlo más rápido. Hay varios pasos que requieren mucho tiempo.
En primer lugar, tomó un tiempo emitir un nuevo certificado intermedio. Como mencioné anteriormente, el certificado raíz se encuentra en el módulo de seguridad de hardware, que se almacena sin conexión. Esta es una buena práctica de seguridad, ya que rara vez utiliza el certificado raíz y, por lo tanto, desea mantenerlo a salvo. Pero obviamente, esto es algo inconveniente cuando necesita emitir un nuevo certificado en una emergencia. En cualquier caso, uno de nuestros ingenieros tuvo que ir a un lugar seguro donde se almacena HSM. Luego hubo varios comienzos falsos, cuando no pudimos emitir el certificado correcto, y cada intento valió una hora o dos pruebas, antes de saber exactamente qué hacer.
En segundo lugar, el desarrollo del sistema lleva algo de tiempo. Conceptualmente, todo es muy simple, pero incluso los programas simples requieren cierta precaución, y realmente queríamos asegurarnos de no empeorar la situación. Y antes de enviar SAO, era necesario probarlo, y esto lleva tiempo, especialmente teniendo en cuenta que debe firmarse. Pero el sistema de firmas estaba deshabilitado, por lo que tuvimos que buscar soluciones.
Finalmente, una vez que el SAO estuvo listo para enviar, tardó un tiempo en desplegarse. Los clientes de Firefox buscan actualizaciones de Normandía cada 6 horas y, por supuesto, muchos clientes están desconectados, por lo que distribuir la actualización a todos los usuarios de Firefox no fue instantáneo. Sin embargo, en este momento, la mayoría ha recibido una actualización y / o un nuevo lanzamiento, que lanzamos más tarde.
Últimos pasos
Aunque el complemento del sistema, implementado a través del sistema de Estudios, debería corregir la situación para la mayoría de los usuarios, no llegó a todos. En particular, varios tipos de usuarios requieren un enfoque diferente:
- Usuarios que han deshabilitado la telemetría o la investigación.
- Usuarios de Firefox para Android (Fennec), donde no tenemos investigación.
- Usuarios de versiones posteriores de Firefox ESR que no se suscriben a informes de telemetría.
- Usuarios que están detrás de los proxys HTTPS MiTM, porque nuestros sistemas de instalación complementarios fuerzan las claves para estas conexiones, lo que entra en conflicto con el proxy.
- Usuarios de versiones muy antiguas de Firefox, a las que el sistema de Estudios no puede acceder.
No podemos hacer nada con el último grupo: tendrán que actualizar a la nueva versión de Firefox, ya que las versiones anteriores suelen tener vulnerabilidades de seguridad sin parches bastante graves. Sabemos que algunas personas se quedaron con versiones anteriores de Firefox porque querían ejecutar extensiones de estilo antiguo, pero muchas de ellas ahora funcionan con versiones más nuevas de Firefox. Para otros grupos, desarrollamos un parche para Firefox que instalará un nuevo certificado después de la actualización. También se lanzó como una nueva versión de Firefox "punteada", por lo que la gente debería obtenerla, y probablemente ya la recibió, a través del canal de actualización regular. Si tiene una compilación posterior, debe esperar la actualización del mantenedor.
Reconocemos que nada de esto es perfecto. En particular, en algunos casos, los usuarios pierden datos asociados con complementos (por ejemplo, una
extensión como "contenedores con varias cuentas" ).
No pudimos desarrollar un parche que evite este efecto secundario, pero creemos que a corto plazo este es el mejor enfoque para la mayoría de los usuarios. A la larga, buscaremos los mejores enfoques arquitectónicos para resolver tales problemas.
Las lecciones
En primer lugar, quiero decir que el equipo hizo un trabajo increíble aquí: desarrollaron y enviaron la solución en menos de 12 horas desde el momento del informe inicial. Como la persona que asistió a la reunión donde sucedió esto, puedo decir que las personas trabajaron increíblemente duro en una situación difícil y que se perdió muy poco tiempo.
Dado esto, es obvio que esta no es una situación ideal, y esto no debería haber sucedido en absoluto. Claramente necesitamos ajustar nuestros procesos para reducir la probabilidad de este y otros incidentes similares y para facilitar su corrección.
La próxima semana realizaremos un informe formal y publicaremos una lista de los cambios que tenemos la intención de hacer, pero por ahora, aquí están mis pensamientos iniciales sobre este tema. Lo más importante, deberíamos tener una manera mucho mejor de monitorear el estado de todos los sistemas en Firefox que son una bomba de tiempo potencial. Debe asegurarse de que ninguno de ellos deje de funcionar repentinamente. Todavía estamos trabajando en los detalles aquí, pero al menos tenemos que hacer un inventario de dichos sistemas.
En segundo lugar, necesitamos un mecanismo para actualizar rápidamente a los usuarios, incluso cuando,
especialmente cuando , todo lo demás no funciona. Es genial que pudiéramos usar el sistema de Estudios, pero tampoco fue la herramienta más perfecta que pusimos en funcionamiento y que tuvo algunos efectos secundarios indeseables. En particular, sabemos que muchos usuarios tienen activadas las actualizaciones automáticas, pero preferirían no participar en la investigación, y esta es una preferencia razonable (por no decir nada, ¡configuré el navegador de esta manera!), Pero al mismo tiempo, deberíamos poder impulsar actualizaciones Cualesquiera que sean los mecanismos técnicos internos, los usuarios deberían poder seleccionar actualizaciones (incluidas las correcciones), pero abandonar todo lo demás. Además, el canal de actualización debería ser más rápido. Incluso el lunes, todavía teníamos usuarios que no recogieron la solución o la nueva versión, lo que claramente no es perfecto. Ya hemos trabajado en este problema, pero este incidente muestra lo importante que es.
Finalmente, analizaremos de manera más general nuestra arquitectura de seguridad de extensión para garantizar que brinde seguridad correctamente con un riesgo mínimo de falla.
La próxima semana publicaremos los resultados de un análisis más exhaustivo de esta situación.