Sobre o autor Eric Rescorla - Diretor Técnico, Grupo Firefox na MozillaRecentemente, ocorreu um incidente no Firefox quando a maioria dos complementos (extensões, complementos) parou de funcionar. Isso ocorre devido a um erro de nossa parte: não notamos que um dos certificados, usado para assinar os complementos, expirou, o que levou à desconexão da grande maioria deles. Agora que corrigimos o problema e a maioria dos complementos foi restaurada, gostaria de contar em detalhes o que aconteceu, por que e como o corrigimos.
Para referência: extensões e sua assinatura
Embora muitos usem o Firefox pronto para uso, o navegador também suporta um poderoso mecanismo de extensão. Eles adicionam recursos de terceiros ao Firefox que estendem os recursos que oferecemos por padrão. Atualmente, existem mais de 15.000 complementos para o Firefox: do
bloqueio de anúncios ao
gerenciamento de centenas de guias .
O Firefox requer que todos os complementos instalados sejam
assinados digitalmente . Este requisito destina-se a proteger os usuários de extensões maliciosas, exigindo um padrão mínimo de verificação pelos funcionários da Mozilla. Antes de introduzirmos esse requisito em 2015, tivemos
sérios problemas com extensões maliciosas.
A assinatura funciona através do "certificado raiz" pré-instalado do Firefox. Ele é armazenado offline no
módulo de segurança de hardware (HSM) . A cada poucos anos, é usado para assinar um novo "certificado intermediário", que é armazenado on-line e usado no processo de assinatura. Quando a extensão é enviada para assinatura, geramos um novo "certificado de entidade final" temporário e o assinamos com um certificado intermediário. O certificado de destino é então usado para assinar a extensão. Visualmente, fica assim:
Observe que cada certificado tem um "assunto" (ao qual o certificado pertence) e um "editor" (signatário). No caso de um certificado raiz, esse é o mesmo, mas, para outros certificados, o editor é o sujeito que o assinou.
O ponto importante aqui é que cada complemento é assinado com seu próprio certificado do objeto final, mas quase todos os complementos têm o mesmo certificado intermediário (vários complementos muito antigos foram assinados por outro link intermediário). Foi aí que surgiu o problema: cada certificado tem uma data de validade fixa. Antes ou depois dessa janela, o certificado não será aceito e a extensão assinada por este certificado não poderá ser carregada no Firefox. Infelizmente, o certificado intermediário que usamos expirou em 4 de maio após as 13:00 UTC e imediatamente todos os complementos assinados por este certificado não foram verificados e não puderam ser carregados no Firefox.
Embora todos os complementos tenham expirado por volta da uma da manhã, as consequências não foram sentidas imediatamente. O motivo é que o Firefox não verifica constantemente os complementos quanto à validade. Eles são verificados aproximadamente a cada 24 horas e o tempo de verificação é diferente para cada usuário. Como resultado, algumas pessoas tiveram problemas imediatamente, outras muito mais tarde. Nós, na Mozilla, aprendemos sobre o problema por volta das 18:00 PST na sexta-feira, 3 de maio e imediatamente reunimos uma equipe para corrigir a situação.
Limite de danos
Assim que entendemos o que estávamos enfrentando, demos vários passos para evitar a deterioração da situação.
Primeiro, desativamos a assinatura de novas adições. Naquele momento, era razoável, porque a assinatura colocava um certificado inválido. Olhando para trás, parece que foi possível deixar essa função, mas descobriu-se que ela também entra em conflito com o amolecimento do “firmware para data difícil”, que discutiremos abaixo (embora no final não a tenhamos usado). Portanto, é bom que tenhamos mantido essa opção. Portanto, a assinatura de novas adições está atrasada.
Em segundo lugar, lançamos imediatamente uma correção rápida que suprime a nova verificação de assinaturas de extensão. A idéia era proteger os usuários que ainda não foram testados novamente. Fizemos isso antes de ter qualquer outra correção e agora removemos quando a correção está disponível.
Trabalho paralelo
Teoricamente, a solução para esse problema parece simples: faça um certificado novo e válido e emita novamente cada adição com esse certificado. Infelizmente, rapidamente determinamos que isso não funcionaria por vários motivos:
- Existem muitas extensões (mais de 15.000) e o serviço não é otimizado para assinatura em massa; portanto, a nova assinatura de cada complemento levará mais tempo do que o esperado.
- Após a assinatura dos complementos, os usuários precisarão obter um novo complemento. Alguns estão hospedados em servidores Mozilla e o Firefox os atualizará em 24 horas, mas os usuários terão que atualizar manualmente quaisquer complementos instalados de outras fontes, o que é muito inconveniente.
Em vez disso, nos concentramos em tentar desenvolver uma correção que resolvesse a situação com pouca ou nenhuma intervenção manual dos usuários.
Tendo considerado várias abordagens, rapidamente concordamos em duas estratégias principais que executamos em paralelo:
- Patch do Firefox para alterar a data usada para verificar o certificado. Nesse caso, os complementos existentes funcionarão magicamente novamente, mas será necessária a entrega de uma nova compilação do Firefox.
- Gere um novo certificado válido e de alguma forma convença o Firefox a aceitá-lo, em vez do já expirado.
Como não tínhamos certeza do que exatamente funcionaria, decidimos realizar o trabalho em paralelo e implementar o primeiro, que pareceria uma solução funcional. No final do dia, concluímos a implantação da segunda correção - um novo certificado, que descreverei em mais detalhes.
Certificado de substituição
Como mencionado acima, havia duas etapas principais a seguir:
- Crie um novo certificado válido.
- Instale-o remotamente no Firefox.
Para entender por que isso funciona, você precisa saber um pouco mais sobre como o Firefox verifica se há complementos. O complemento em si vem na forma de um pacote de arquivos, que inclui a cadeia de certificados usada para assiná-lo. Como resultado, o complemento é verificado independentemente se o certificado raiz é conhecido, configurado no Firefox durante a compilação. No entanto, como eu disse, o certificado intermediário foi quebrado, portanto o complemento não era realmente verificável.
Mas acontece que, quando o Firefox tenta verificar a extensão, não se limita a usar apenas certificados na própria extensão. Em vez disso, ele tenta criar uma cadeia de certificados válida, começando com o certificado do nó de extremidade e continuando no diretório raiz. O algoritmo é complexo, mas em um nível alto, você começa com um certificado do objeto final e, em seguida, encontra um certificado cujo assunto é igual ao editor do certificado do objeto final (ou seja, um certificado intermediário). No caso simples, esse é apenas um link intermediário que acompanha o suplemento, mas pode ser qualquer certificado que o navegador conheça. Se pudermos adicionar remotamente um certificado novo e válido, o Firefox também tentará criar essa cadeia. A figura abaixo mostra a situação antes e depois da instalação de um novo certificado.

Depois de instalar um novo certificado, o Firefox possui duas opções para verificar a cadeia de certificados: use um certificado inválido antigo (que não funcionará) ou use um novo certificado válido (que funcionará). Uma característica importante aqui é que o novo certificado tem o mesmo nome de assunto e chave pública que o certificado antigo, portanto sua assinatura no certificado do objeto final é válida. Felizmente, o Firefox é inteligente o suficiente para tentar os dois métodos até encontrar um que funcione, portanto a extensão se torna válida novamente. Observe que essa é a mesma lógica que usamos para verificar os certificados TLS; portanto, este é um código relativamente bem compreendido que pudemos usar (os leitores familiarizados com o WebPKI entenderão que a certificação cruzada funciona dessa maneira).
O melhor dessa correção é que ela não requer uma alteração em nenhuma extensão existente. Quando instalamos o novo certificado no Firefox, mesmo extensões com certificados antigos passam no teste. O truque para entregar um novo certificado no Firefox é fazê-lo automática e remotamente e, em seguida, fazer com que o Firefox verifique novamente todas as extensões que podem ter sido desativadas.
Normandia e sistema de pesquisa
Ironicamente, a solução para o problema era um tipo especial de extensão chamado
complemento do sistema (SAO). Para estudos do público (Estudos), desenvolvemos anteriormente um sistema chamado Normandia, que pode fornecer SAO para usuários do Firefox. Esses SAOs são executados automaticamente no navegador do usuário. Embora sejam comumente usados para experimentação, eles também têm amplo acesso às APIs internas no Firefox. Nesse caso, é importante que eles possam adicionar novos certificados ao banco de dados de certificados que o Firefox usa para verificar as extensões (nota técnica: não adicionamos o certificado com privilégios especiais; ele obtém seus privilégios assinando com o certificado raiz. ao conjunto de certificados que o Firefox pode usar, para não adicionarmos um novo certificado privilegiado ao Firefox).
Portanto, a solução aqui é criar um SAO que faça duas coisas:
- Instala o novo certificado que criamos.
- Faz com que o navegador verifique novamente cada complemento para ativar aqueles que foram desconectados.
Mas espere, você diz. Os complementos não funcionam, então como fazer o SAO funcionar? Bem, assinaremos com um novo certificado!
Juntando tudo ... e por quanto tempo?
Portanto, agora temos um plano: emitir um novo certificado para substituir o antigo, criar um complemento de sistema para instalá-lo no Firefox e implantá-lo na Normandia. Começamos o trabalho por volta das 18:00 PST na sexta-feira, 3 de maio, e enviamos o patch para a Normandia por volta das 2:44 da manhã, ou seja, menos de 9 horas, e depois demoramos mais 6 a 12 horas para que a maioria dos usuários o recebesse. Este é realmente um começo muito bom, mas vi no Twitter uma série de perguntas, por que não conseguimos fazê-lo mais rapidamente. Há várias etapas demoradas.
Em primeiro lugar, levou algum tempo para emitir um novo certificado intermediário. Como mencionei acima, o certificado raiz está localizado no módulo de segurança de hardware, que é armazenado offline. Essa é uma boa prática de segurança, pois você raramente usa o certificado raiz e, portanto, deseja mantê-lo seguro. Mas, obviamente, isso é um pouco inconveniente quando você precisa emitir um novo certificado em uma emergência. De qualquer forma, um de nossos engenheiros teve que ir para um local seguro onde o HSM está armazenado. Houve várias partidas falsas, quando não foi possível emitir o certificado correto, e cada tentativa valeu uma hora ou dois testes, antes de sabermos exatamente o que fazer.
Em segundo lugar, o desenvolvimento do sistema leva algum tempo. Conceitualmente, tudo é muito simples, mas mesmo programas simples exigem alguma cautela e queríamos realmente garantir que não piorássemos a situação. E antes de enviar o SAO, era necessário testá-lo, e isso leva tempo, principalmente considerando que ele precisa ser assinado. Mas o sistema de assinaturas foi desativado, então tivemos que procurar soluções alternativas.
Por fim, quando o SAO estava pronto para enviar, demorou um pouco para implantar. Os clientes do Firefox verificam as atualizações da Normandia a cada 6 horas e, é claro, muitos clientes estão offline, portanto a atualização não foi distribuída instantaneamente a todos os usuários do Firefox. No entanto, no momento, a maioria recebeu uma atualização e / ou um novo lançamento, que lançamos mais tarde.
Últimos passos
Embora o complemento do sistema, implantado através do sistema de Estudos, deva corrigir a situação para a maioria dos usuários, ele não alcançou todos. Em particular, vários tipos de usuários exigem uma abordagem diferente:
- Usuários que desativaram a telemetria ou a pesquisa.
- Usuários do Firefox para Android (Fennec), onde não temos pesquisas.
- Usuários de versões subseqüentes do Firefox ESR que não assinam relatórios de telemetria.
- Usuários protegidos por proxies HTTPS MiTM, porque nossos sistemas de instalação de complemento forçam chaves para essas conexões, que entram em conflito com o proxy.
- Usuários de versões muito antigas do Firefox, às quais o sistema de Estudos não pode alcançar.
Não podemos fazer nada com o último grupo - eles terão que atualizar para a nova versão do Firefox, porque as versões mais antigas geralmente têm vulnerabilidades de segurança sem patches muito sérias. Sabemos que algumas pessoas permaneceram em versões mais antigas do Firefox porque queriam executar extensões de estilo antigo, mas muitas delas agora trabalham com versões mais recentes do Firefox. Para outros grupos, desenvolvemos um patch para o Firefox que instalará um novo certificado após a atualização. Também é lançada como uma nova versão do Firefox "pontilhada", para que as pessoas possam obtê-lo - e provavelmente já o receberam - através do canal de atualização regular. Se você tem uma compilação a jusante, precisa aguardar a atualização do mantenedor.
Reconhecemos que nada disso é perfeito. Em particular, em alguns casos, os usuários perdem dados associados aos complementos (por exemplo, uma
extensão como "contêineres com várias contas" ).
Não foi possível desenvolver um patch que evita esse efeito colateral, mas acreditamos que, a curto prazo, essa seja a melhor abordagem para a maioria dos usuários. A longo prazo, procuraremos as melhores abordagens arquitetônicas para resolver esses problemas.
As lições
Em primeiro lugar, quero dizer que a equipe fez um trabalho incrível aqui: eles desenvolveram e enviaram a correção em menos de 12 horas a partir do momento do relatório inicial. Como a pessoa que participou da reunião em que isso aconteceu, posso dizer que as pessoas trabalharam incrivelmente duro em uma situação difícil e que pouquíssimo tempo foi desperdiçado.
Diante disso, é óbvio que essa não é uma situação ideal e isso não deveria ter acontecido. Claramente, precisamos ajustar nossos processos para reduzir a probabilidade de incidentes semelhantes e semelhantes e facilitar sua correção.
Na próxima semana, realizaremos um interrogatório formal e publicaremos uma lista de mudanças que pretendemos fazer, mas, por enquanto, aqui estão meus pensamentos iniciais sobre esse assunto. Mais importante, devemos ter uma maneira muito melhor de monitorar o status de todos os sistemas no Firefox que são uma bomba-relógio em potencial. Você precisa garantir que nenhum deles pare de funcionar repentinamente. Ainda estamos trabalhando nos detalhes aqui, mas pelo menos precisamos fazer um inventário desses sistemas.
Em segundo lugar, precisamos de um mecanismo para atualizar rapidamente os usuários, mesmo quando -
especialmente quando - todo o resto não funciona. É ótimo podermos usar o sistema de estudos, mas também não foi a ferramenta mais avançada que colocamos em operação e que teve alguns efeitos colaterais indesejáveis. Em particular, sabemos que muitos usuários têm atualizações automáticas ativadas, mas preferem não participar de pesquisas, e essa é uma preferência razoável (para não dizer nada, eu configuro o navegador dessa maneira!), Mas, ao mesmo tempo, devemos poder pressionar atualizações. Quaisquer que sejam os mecanismos técnicos internos, os usuários devem poder selecionar atualizações (incluindo correções), mas abandonam todo o resto. Além disso, o canal de atualização deve ser mais rápido. Mesmo na segunda-feira, ainda tínhamos usuários que não receberam a correção ou o novo lançamento, o que claramente não é perfeito. Já trabalhamos nesse problema, mas esse incidente mostra o quanto é importante.
Por fim, examinaremos de maneira mais geral nossa arquitetura de segurança de extensão para garantir que ela forneça segurança corretamente com risco mínimo de falha.
Na próxima semana, publicaremos os resultados de uma análise mais aprofundada dessa situação.