WorstFit: Revelando transformadores ocultos no Windows ANSI
TL;DR
- Descobriu-se uma nova superfície de ataque explorando o recurso interno de conversão de conjunto de caracteres do Windows chamado Best-Fit.
- Esse recurso foi convertido em ataques práticos, como path traversal, injeção de argumentos e execução remota de código (RCE).
- As causas raiz estão no comportamento do compilador, no runtime de C/C++ e em erros dos desenvolvedores.
- Também discute-se a dificuldade de inserir correções no ecossistema de código aberto.
Decodificando codificação do Windows
Inicial: ANSI e code pages
- No início, o Windows usava codificação ANSI, que era eficaz para idiomas específicos, mas não conseguia lidar com conjuntos de caracteres mistos.
- Existem diversas code pages, e cada uma suporta idiomas específicos.
Era Unicode: UTF-16
- O Windows migrou para Unicode em meados da década de 1990, permitindo representar praticamente todos os caracteres de praticamente todos os idiomas em um único padrão.
- Inicialmente ele usava UCS-2, mas logo foi atualizado para UTF-16.
Era de codificação dupla
- Para manter compatibilidade com as code pages ANSI antigas, o Windows implementou duas versões de API.
- Há API ANSI e API Unicode, e os desenvolvedores podem obter facilmente o formato de dados desejado.
Vantagens do Best-Fit
- A conversão de caracteres "Best-Fit" do Windows é uma forma de tratar caracteres ausentes na code page de destino durante a conversão de UTF-16 para ANSI.
- Por exemplo, como o símbolo
∞ não existe na code page Windows-1252, a Microsoft o mapeia para 8.
WorstFit: nova superfície de ataque no Windows
🔥 O pesadelo do Leste Asiático - CVE-2024-4577
- CVE-2024-4577 é uma vulnerabilidade que pode comprometer um servidor PHP-CGI configurado com code pages chinesas ou japonesas por meio de uma requisição simples
?%ADs.
- Devido ao comportamento do Best-Fit, U+00AD (hífen suave) é mapeado para hífen (
-), permitindo bypass.
🔥 Smuggling de nome de arquivo
- É possível abusar do WorstFit no tratamento de nomes de arquivos e transformá-los em payloads de path traversal.
- Por exemplo, o Developer Shell do Chrome V8 (
d8.exe) obtém o diretório de trabalho atual usando a API ANSI.
🔥 Divisão de argumentos
- É possível manipular a saída de
GetCommandLineA e explorar o comportamento do WorstFit no parsing da linha de comando.
- Por exemplo, a entrada
" --use-askpass=calc " pode fazer o sistema executar calc.exe.
Conclusão
- O comportamento do Best-Fit oferece uma superfície de ataque no processo de conversão em nível de sistema, o que pode causar vulnerabilidades em diversas ferramentas.
- Nem funções de bibliotecas padrão nem funções de linguagens de programação conseguem bloquear completamente esse tipo de ataque.
1 comentários
Opinião do Hacker News
A Microsoft sabia desse problema há pelo menos um ano. Pela regra de análise de código específica CA2101, ela já não recomenda o uso de mapeamento best-fit. A vulnerabilidade de segurança foi mencionada, mas os detalhes ficaram vagos.
Isso é sistêmico. A Microsoft fornece o mapeamento de código "best fit" para converter Unicode para ASCII. Esse mapeamento é usado em muitos lugares, e como a Microsoft prioriza compatibilidade com versões anteriores, precisa continuar incluído. Está fundamentalmente acoplado em todo lugar por padrão.
É explorado principalmente convertendo pontos de código anormais em slash, hífen, aspas etc. Em linguagens de programação modernas isso é avaliado corretamente, mas gera problemas ao ser passado para comandos de shell ou para a API Win32.
O mantenedor do curl diz que "o curl é a vítima", mas a causa do problema está em outro lugar. Ele ocorre quando a entrada do usuário é validada de uma maneira e o sistema é aplicado de outra forma na biblioteca do sistema.
Desativar seletivamente a conversão "best fit" no espaço Win32 pode ser uma solução. Provedores de código aberto podem adicionar isso como uma boa prática.
O Windows pode ser como um jogo de cartas Munchkin: recursos se combinam de forma inadvertida e criam uma vulnerabilidade poderosa. Converter a subsistema ANSI para UTF-8 pode mitigar esse problema.
A Microsoft vinha descontinuando o ANSI gradualmente desde o NT 3.5 e incentivando o uso da API de caracteres largos. No entanto, a forma de implementação da runtime da biblioteca C/C++ da Microsoft é um obstáculo importante.
É improvável que a Microsoft ative UTF-8 por padrão em todas as edições do Windows. Isso porque aplicativos antigos dependem de certas páginas de código ou de caracteres de 1 byte.
Existem duas maneiras de forçar a página de código "Ansi" para UTF-8 em uma aplicação: usar um arquivo Manifest ou usar a ferramenta "App Locale".
Em uma máquina Windows pessoal, fiquei seguro contra esse bug ao configurar o modo UTF-8. Ativei isso porque um jogo antigo estrangeiro exibia texto quebrado.
Resolver o problema não é algo que se arranja trocando simplesmente
main()pela versão wide-character. Seria preciso converter todas as variáveis parawchar_t *, o que é doloroso e propenso a erros.char. Tome cuidado para não misturar strings ANSI ou OEMCP com strings UTF-8.Eu sabia que a API do Windows fornece conversão best-fit, mas não sabia que esse é o comportamento padrão. Esse recurso deveria ser proibido.
Eu tinha curiosidade se a caixa de seleção Beta fazia o mesmo que definir o ActiveCodePage como UTF-8. O GDI não segue a página de códigos por processo, e sim apenas a página de códigos global. É uma pena não poder escolher UTF-8 totalmente.