Chrome corrige vulnerabilidade de heap buffer overflow no WebP
(chromereleases.googleblog.com)- A atualização dos canais Chrome Stable e Extended Stable para desktop foi distribuída com correção para a vulnerabilidade de heap buffer overflow no WebP
- As novas builds são 116.0.5845.187 no Mac e Linux, e 116.0.5845.187/.188 no Windows, com aplicação gradual ao longo de alguns dias a algumas semanas
- Esta versão inclui 1 correção de segurança, e CVE-2023-4863 foi classificada como Critical
- A vulnerabilidade foi reportada em 6 de setembro de 2023 pela Apple SEAR e pelo The Citizen Lab da Munk School da University of Toronto
- O Google informou que há casos de exploração no mundo real, e o acesso aos detalhes do bug pode ser restrito até que a versão corrigida seja aplicada
Atualização do canal do Chrome para desktop
- Os canais Stable e Extended Stable foram atualizados para novas builds de desktop
- As versões do canal Stable por plataforma são as seguintes
- Mac: 116.0.5845.187
- Linux: 116.0.5845.187
- Windows: 116.0.5845.187/.188
- O canal Extended Stable também foi distribuído em versões separadas
- Windows: 116.0.5845.188
- Mac: 116.0.5845.187
- A atualização será distribuída gradualmente ao longo de alguns dias a algumas semanas
- A lista completa de mudanças desta build pode ser consultada no log
Correção de segurança: CVE-2023-4863
- Esta versão inclui 1 correção de segurança
- A principal correção contribuída por pesquisadores externos é a seguinte vulnerabilidade
- Critical CVE-2023-4863: heap buffer overflow no WebP
- Número do bug: 1479274
- Reportado por: Apple Security Engineering and Architecture(SEAR), The Citizen Lab da Munk School da University of Toronto
- Data do relatório: 6 de setembro de 2023
- Valor da recompensa: $NA
Exploração no mundo real e restrição de divulgação de informações
- O Google informou que existe um exploit para a CVE-2023-4863 em ambiente real
- O acesso aos detalhes e links do bug pode ser restringido até que a maioria dos usuários atualize para a versão corrigida
- A restrição também pode ser mantida se o mesmo bug existir em uma biblioteca de terceiros da qual outros projetos dependem e que ainda não tenha sido corrigida
Caminhos para detecção e reporte de bugs de segurança
- Muitos bugs de segurança são detectados com as seguintes ferramentas
- As instruções para trocar de canal de release podem ser vistas no guia de canais de release do Chromium
- Novos problemas podem ser reportados em crbug.com, e ajuda pode ser obtida no fórum de ajuda da comunidade do Chrome
1 comentários
Opiniões no Hacker News
No Google Chrome, imagens WebP são decodificadas no processo do renderizador, então, mesmo que o exploit seja bem-sucedido, ele só permite executar código do renderizador dentro do sandbox.
O renderizador é extremamente complexo, e muitos exploits são descobertos todos os anos, mas obter execução de código no renderizador não dá muito mais permissões do que uma página web comum já tem.
Em especial, não é possível ver nem deixar arquivos no sistema de arquivos local, e também não é possível ler cookies de outros domínios.
Não é uma prioridade máxima imediata, mas, se um exploit desses ainda não estiver circulando in the wild, é algo que deve ser corrigido o mais rápido possível em um momento que não cause grande transtorno.
Por não ficar preso a um site ou front-end específico, isso se aproxima de um XSS reforçado.
Ah, comentei na thread errada; eu queria responder ao “jpeg is good enough” de https://news.ycombinator.com/item?id=37479576.
E, mesmo que o JavaScript esteja desativado, o site não passaria de repente a ainda conseguir executar código?
Por isso fico mais compreensivo com a lentidão dos desenvolvedores de navegadores para adotar novos formatos.
O WebP não traz grandes vantagens em relação ao JPEG; é mais pela transparência, e mesmo assim teve sucesso limitado.
Mas agora levou a vários buracos de segurança de alta prioridade, e todo lugar linkado à libwebp vai ter que distribuir patches durante o próximo mês.
Não estou dizendo para não fazer nada novo, mas acho que desenvolvedores tendem a subestimar bastante os custos.
É verdade que o ecossistema WebP é muito menos maduro, mas tenho certeza de que também houve muitos problemas de segurança em código de processamento de formatos mais antigos.
Ainda assim, a lógica é válida. Até poucas semanas atrás, o clima entre internautas era de que o JPEG XL deveria ser adotado o mais rápido possível e que, para isso, bastaria os desenvolvedores de navegadores “incluírem o código do decodificador de referência na base de código”, com “custo praticamente zero”.
Outros formatos de imagem e bibliotecas provavelmente também estão cheios de bugs, mas, como não são usados em softwares importantes, ninguém se importa.
Especialmente porque, para quem tem capacidade de encontrar e explorar esse tipo de bug, a recompensa pelo tempo investido é ruim.
O fato de algo não ser usado há muito tempo não reduz a quantidade de bugs.
Se encoders e decoders de imagem, assim como outros encoders/decoders, não usassem linguagens inseguras, a chance de criar bugs desse tipo seria menor.
Separadamente, também acho que são problemas a cultura de tornar o código mais complexo do que precisa e desenvolvedores que não entendem direito os detalhes.
Esta correção entrou no Firefox 117.0.1 e no Fenix 117.1.0 de hoje: https://hg.mozilla.org/releases/mozilla-release/rev/e245ca21....
Para referência, a crate image tem uma implementação de decodificador WebP escrita em Rust seguro: https://github.com/image-rs/image
Por muito tempo ela ficou bastante incompleta, mas no ano passado muitos recursos de WebP foram implementados.
Como o Chromium agora tem uma política que permite usar dependências em Rust, será que ele também não poderia começar a adotá-la?
Commit original do problema: https://github.com/webmproject/libwebp/commit/f75dfbf23d1df1...
Commit que corrige este bug: https://github.com/webmproject/libwebp/commit/902bc919033134...
O commit original otimizou o decodificador de Huffman. Esse decodificador usa uma otimização bem conhecida: lê N bits antecipadamente e decide quantos bits de fato precisa consumir e qual símbolo deve decodificar. Ou, se for um prefixo de N bits de vários símbolos, decide qual tabela consultar para os bits restantes
A versão antiga usava uma tabela de consulta para símbolos curtos, mas símbolos longos exigiam percorrer um grafo. A nova versão melhorou isso usando um array de tabelas de consulta. Cada entrada contém
(nbits, value), em quenbitsé o número de bits a consumir evaluenormalmente é um símbolo. Mas, quandonbitspassa de N,valueé interpretado como um índice de tabela, enbitspassa a ser reinterpretado como o comprimento do código mais longo nessa subárvore. Portanto, cada tabela seguinte precisa ter2^(nbits - N)entradas. A tabela raiz é sempre fixa em2^NentradasA nova versão calculava o número máximo de entradas (
kTableSize) com base no número de símbolos. Naturalmente, a árvore de Huffman vem de uma entrada não confiável, e é fácil imaginar casos em quenbitsfique muito grande. O VP8 Lossless permite especificamente até 15 bits, então, se todas as LUTs forem mapeadas para tabelas auxiliares separadas, a maior tabela possível terá2^N + 2^15entradas. Nem são necessários tantos símbolos para criar isso;16-Nsímbolos para cada tabela já bastamCuriosamente, o próprio código tinha um modo que apenas calculava o tamanho da tabela (chamando
VP8LBuildHuffmanTablecomroot_table == NULL), mas, por algum motivo, ele não era usado e assumia-se um tamanho máximo fixo. Assim, ao construir uma árvore de Huffman para maximizar o número de entradas, acabava-se escrevendo além da área alocadaDá para entender por que isso aconteceu. A etapa de decodificação de Huffman é uma das partes mais custosas em termos de computação em muitos formatos de compressão, então até pequenas melhorias importam. A otimização acima é bem conhecida, mas o caminho de códigos longos geralmente é considerado raro, então tinha baixa prioridade de otimização. A mensagem do commit original contestou essa suposição e conseguiu ser mesclada. É difícil ter certeza de que uma linguagem com segurança de memória teria evitado esse problema. Isso porque, raramente, este é um caso em que dá vontade de evitar ativamente verificações de overflow
[1] Ainda assim, como a corrupção de memória acontece durante a construção da tabela, e não no loop apertado, verificações parciais de overflow teriam ajudado bastante. A correção real não mudou em nada a função
ReadSymbol. Mesmo assim, a segurança de loops apertados precisa ser justificada, e uma justificativa errada pode estragar tudoSe for verdade que não são necessárias verificações de limites, tudo bem. WUFFS não emite verificações de limites em tempo de execução
Mas, se o software ultrapassar os limites e estiver errado, como neste caso, ele não compila em WUFFS
Você pode pensar “isso é impossível”, e estaria certo se WUFFS fosse uma linguagem de programação de uso geral. Pelo teorema de Rice, qualquer propriedade semântica não trivial é indecidível
Felizmente, WUFFS não é uma linguagem de uso geral. A maior parte dos softwares não pode ser escrita em WUFFS, mas codecs de imagem podem
Ainda assim, fico me perguntando se teria sido possível criar testes automatizados que pegassem esse tipo de problema
No código com que lido pessoalmente, algumas contas podem ser extraídas para funções separadas e testadas de forma independente. Aqui talvez isso fosse difícil por causa de desempenho, mas não tenho certeza
Correção de escrita fora dos limites em
BuildHuffmanTablehttps://github.com/webmproject/libwebp/commit/902bc919033134...
Isso pode significar que o Google otimizou o fuzzer para libwebp depois de encontrar esse bug e, por isso, está encontrando mais bugs
Parece ter sido reportado pela Apple, e se parece muito com esta atualização de segurança: https://support.apple.com/en-us/HT213906
Por isso, parece bastante provável. A Apple pode estar usando libwebp internamente no ImageIO, ou pode ter cometido um erro parecido
Codecs de imagem têm uma longa história de vulnerabilidades
O processamento real de imagens pode ser um código linear limpo o bastante para ser escrito até em FORTRAN IV com segurança de memória, mas, quando entra compressão, aparecem muitas estruturas de dados de comprimento variável, rastreamento de ponteiros etc.
Soma-se a isso a pressão para executar rapidamente
Isso também afeta o Electron? Se sim, quais versões?
O interessante é que o Signal Desktop, que usa Electron internamente, é executado no Linux sem sandbox [1][2]
[0] https://github.com/electron/electron/pull/39824
[1] https://github.com/signalapp/Signal-Desktop/issues/5195
[2] https://github.com/signalapp/Signal-Desktop/pull/4381
Existe algum caminho realista para explorar isso?
Pelo que ouvi, em 64 bits, heap spraying não é mais prático
Há algum objeto previsível na memória que possa ser sobrescrito?
Mesmo em 64 bits, heap spraying ainda é claramente usado em exploits de kernel. Não sei bem quais primitivas as pessoas usam em exploits do V8