1 pontos por GN⁺ 2023-09-13 | 1 comentários | Compartilhar no WhatsApp
  • 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

1 comentários

 
GN⁺ 2023-09-13
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.

    • Claro que, se houver um exploit de escape do sandbox para combinar com isso, a história muda.
      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.
    • Na internet moderna há uma quantidade enorme de imagens enviadas por usuários, então só obter as permissões do contexto de usuário de um único site já é algo bastante relevante.
      Por não ficar preso a um site ou front-end específico, isso se aproxima de um XSS reforçado.
    • Estou usando WebP sem perdas e ele é muito mais eficiente que PNG.
      Ah, comentei na thread errada; eu queria responder ao “jpeg is good enough” de https://news.ycombinator.com/item?id=37479576.
    • Isso quer dizer que o renderizador não consegue enviar informações de volta para o site?
      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.

    • O Firefox tem uma camada adicional de sandbox que pode ser aplicada a bibliotecas individuais, não ao processo inteiro: https://hacks.mozilla.org/2021/12/webassembly-and-back-again....
    • Para ser justo, problemas em bibliotecas de decodificação de JPEG também já foram usados no passado como vetor de entrega de malware.
      É 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”.
    • Será que esse bug teria sido descoberto se os navegadores não tivessem adotado o novo formato?
      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.
    • A causa dos buracos de segurança não é o novo formato de imagem, e sim a falta de segurança de memória em C/C++.
      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.
    • WebP é um formato muito mais complexo que JPEG, e a complexidade se correlaciona quase diretamente com a densidade de defeitos.
      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?

    • Se o Chrome tivesse uma flag do tipo “usar a versão segura da biblioteca XYZ, mesmo que possa ser mais lenta”, eu a ativaria imediatamente, aceitando a perda de desempenho.
    • Em 2023, parece absurdo que continuem escrevendo código novo em C/C++ para um alvo com uma superfície de ataque tão grande quanto um navegador web.
  • 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 que nbits é o número de bits a consumir e value normalmente é um símbolo. Mas, quando nbits passa de N, value é interpretado como um índice de tabela, e nbits passa a ser reinterpretado como o comprimento do código mais longo nessa subárvore. Portanto, cada tabela seguinte precisa ter 2^(nbits - N) entradas. A tabela raiz é sempre fixa em 2^N entradas
    A 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 que nbits fique 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^15 entradas. Nem são necessários tantos símbolos para criar isso; 16-N símbolos para cada tabela já bastam
    Curiosamente, o próprio código tinha um modo que apenas calculava o tamanho da tabela (chamando VP8LBuildHuffmanTable com root_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 alocada
    Dá 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 tudo

    • Este componente deveria ter sido escrito em WUFFS
      Se 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
    • Faz mais de 10 anos que não trabalho como programador C, e eu nem era tão bom assim, mas, pela explicação, concordo que verificações de limites teriam pegado o problema
      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 BuildHuffmanTable
    https://github.com/webmproject/libwebp/commit/902bc919033134...

  • Parece ter sido reportado pela Apple, e se parece muito com esta atualização de segurança: https://support.apple.com/en-us/HT213906

    • Foi reportado pela Apple e pelo “Citizen Lab da Munk School da UoT”, exatamente como está escrito na página linkada
      Por isso, parece bastante provável. A Apple pode estar usando libwebp internamente no ImageIO, ou pode ter cometido um erro parecido
    • É interessante ver como a reação da semana passada e a de agora são diferentes
  • 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?

  • 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?

    • Como já está sendo explorado in the wild, a resposta é sim
      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