Voltar à sala de imprensa
Ameaças

Alpine Linux reconstrói o seu GitLab após ataque contra falha de Ruby com CVSS 10.0

Um atacante passou dois dias a bombardear o GitLab auto-alojado do Alpine Linux com configurações de CI desenhadas para a CVE-2026-97229. O projeto não encontrou provas de que o exploit tenha funcionado, mas reconstruiu o servidor na mesma e percebeu que atualizar o GitLab, por si só, deixa a falha do Ruby intacta.

Alpine Linux reconstrói o seu GitLab após ataque contra falha de Ruby com CVSS 10.0

Alpine Linux reconstrói o seu GitLab após ataque contra falha de Ruby com CVSS 10.0

O Alpine Linux reconstruiu de raiz o seu servidor GitLab auto-alojado e repôs a palavra-passe de todos os utilizadores, depois de um atacante ter passado dois dias a tentar explorar a CVE-2026-97229, uma vulnerabilidade de execução remota de código de gravidade máxima, contra a instância que aloja as fontes dos pacotes da distribuição. O projeto divulgou o incidente a 28 de outubro.

O que aconteceu

A CVE-2026-97229 tem uma pontuação CVSS de 10.0. A fraqueza não está no código do GitLab, mas no Onigmo, o motor de expressões regulares integrado no Ruby. O GitLab compila com Ruby as expressões regulares das configurações de CI, pelo que um padrão manipulado num ficheiro .gitlab-ci.yml pode chegar ao motor vulnerável e, em determinadas condições, executar código no servidor. O GitLab lançou a correção a 12 de outubro, corrigindo o Ruby incluído nos seus pacotes Linux e nas imagens oficiais de contentor. No dia seguinte já circulava publicamente um exploit funcional de prova de conceito.

O servidor do Alpine é o que aloja o aports, o repositório a partir do qual são construídos todos os pacotes da distribuição. A 13 de outubro, o projeto atualizou-o para o GitLab 19.3.4 em vez do 19.3.5, algo que a equipa reconhece como um erro: o 19.3.4 constava inicialmente como a versão corrigida para o ramo 19.3, mas o aviso de segurança foi depois alterado para o listar como afetado.

A 20 de outubro, uma conta acabada de registar começou a sondar o servidor. Ao longo de 20 e 21 de outubro enviou configurações de CI manipuladas que derrubaram os processos worker do GitLab oito vezes, provocaram erros 502 e fizeram falhar trabalhos de CI. Em quatro dessas quedas, o atacante percorreu parte da cadeia de exploração antes de falhar no passo seguinte. A mesma conta descarregou ainda a imagem pública de contentor GitLab do Alpine, o que o projeto interpreta como uma tentativa de afinar o exploit para a sua build exata.

O Alpine bloqueou a conta a 23 de outubro. O atacante regressou a 25 e 26 de outubro e tentou voltar a entrar, sem sucesso.

Porque atualizar o GitLab não chegou

A 22 de outubro, o Alpine passou o servidor para o GitLab 19.3.6 e deu o problema por resolvido. A 26 de outubro descobriu que a instância continuava vulnerável. A razão é simples depois de a ver: a correção do GitLab vive no Ruby que o GitLab inclui nos seus próprios pacotes e imagens. A imagem de contentor do Alpine instala separadamente um Ruby padrão, pelo que a atualização do GitLab nunca tocou no motor de expressões regulares vulnerável.

A mesma lacuna aplica-se a qualquer instalação de GitLab compilada manualmente ou a qualquer imagem personalizada que traga o seu próprio Ruby. Esses servidores precisam de Ruby 3.3.13, 3.4.12 ou 4.0.9 (ou posterior), além de uma versão corrigida do GitLab. O Ruby 3.2 chegou ao fim de vida em abril e não receberá a correção; ainda assim, o guia de instalação compilada do GitLab continua a listar o 3.2 como versão mínima, e nenhum dos anúncios de patches do GitLab de outubro diz aos administradores de instalações compiladas para atualizarem o Ruby.

A 27 de outubro, o Alpine fechou o GitLab a todos exceto aos seus programadores e servidores de build, e iniciou a reconstrução. O novo servidor ficou pronto a 28 de outubro com Ruby 3.3.13 ou posterior, novas chaves secretas do GitLab e reposição obrigatória da palavra-passe de todas as contas. Está a ser testado antes de reabrir ao público.

O que o Alpine pode e não pode excluir

O projeto não encontrou sinais de que o código do atacante tenha chegado a ser executado: as sondas de temporização não mostraram atrasos, não surgiram ficheiros, chaves, hooks ou processos inesperados, e nenhum dado privado saiu através de qualquer pedido web ou de API que o Alpine consiga ver.

Isso não é o mesmo que uma prova de segurança. Uma exploração bem-sucedida desta falha não deixa quedas nem rasto nos registos web. Alguns registos dos dias do ataque perderam-se, incluindo os dos trabalhos em segundo plano e o sistema de ficheiros do contentor antigo, e nem o Alpine nem o seu fornecedor de alojamento registavam as ligações de rede de saída. Como a evidência necessária para confirmar ou excluir a execução de código já não existe, o Alpine optou por tratar o servidor como comprometido e reconstruí-lo.

Se o ataque tivesse tido sucesso, os dados expostos poderiam incluir nomes, endereços de e-mail e IP dos utilizadores, hashes de palavras-passe, segredos de autenticação de dois fatores, variáveis de CI/CD, tokens de runner, credenciais de webhooks e de push mirror, tokens de acesso pessoal (guardados como hash), repositórios privados e issues e merge requests confidenciais. Para além da reposição de palavras-passe e das novas chaves secretas, o Alpine ainda não disse se os tokens de runner, as variáveis de CI/CD, os tokens de acesso ou as credenciais de integração guardadas no servidor foram substituídos.

Os pacotes parecem limpos

A maior preocupação para o ecossistema é a manipulação da cadeia de abastecimento, e aqui as notícias são melhores. O Alpine verificou que todas as alterações ao aports recebidas entre 20 e 22 de outubro chegaram através de um push registado de um programador conhecido, e confrontou-o com registos fora do alcance do atacante: a cópia local do repositório de um programador e os 45 servidores de build. Todos os pacotes construídos de 20 a 24 de outubro, e os lançamentos de 21 de outubro, incluindo os ficheiros minirootfs a partir dos quais são construídas as imagens oficiais do Alpine para Docker, correspondem a essas alterações verificadas. As verificações estão a ser alargadas até 27 de outubro, o dia em que o servidor foi fechado. As chaves que assinam os pacotes e os lançamentos do Alpine nunca estiveram no servidor GitLab.

Que servidores GitLab estão expostos

O GitLab.com e o GitLab Dedicated já estão corrigidos. Para servidores auto-geridos, as versões corrigidas são a 19.4.2, 19.3.5 e 19.2.8, e os lançamentos de 21 de outubro (19.5.1, 19.4.3, 19.3.6, 19.2.9, 19.1.9, 19.0.10 e 18.11.13) são os mais recentes de cada ramo; corrigem também a CVE-2026-110264, uma falha distinta de expressões regulares. Os ramos 19.5, 19.1, 19.0 e 18.11 não constam como afetados.

A prova de conceito pública precisa primeiro de acesso de escrita: o atacante envia um ficheiro de CI malicioso e um caminho de ficheiro com carateres UTF-8 para um ramo de um projeto público, e só o pedido final de CI lint fica sem autenticação. Essa barreira desaparece em servidores onde novos utilizadores se podem registar sozinhos e criar projetos. Ainda não se sabe como o relatório original enviado ao GitLab, ainda privado, evita o passo de escrita, e o Alpine não explicou como as configurações de CI do seu atacante chegaram ao servidor. A CVE não constava do catálogo de vulnerabilidades exploradas conhecidas da CISA a 28 de outubro.

O que fazer

  • Pacote Linux ou imagem oficial de contentor: atualize para a versão mais recente do seu ramo.
  • Instalação compilada ou imagem personalizada com Ruby próprio: atualize o GitLab e passe o Ruby para 3.3.13, 3.4.12, 4.0.9 ou posterior. Servidores ainda em 19.3.4 devem passar para 19.3.6.
  • Se não puder atualizar de imediato: restrinja o acesso anónimo a projetos públicos, impeça utilizadores não confiáveis de criar ou escrever em projetos públicos, ou bloqueie a rota de CI lint. Estas medidas cobrem apenas a via de exploração conhecida e não corrigem o motor em si.
  • Procure sinais de exploração: o GitLab publicou seis regras de deteção em formato Sigma que cobrem padrões hostis nos avisos de regexp do CI e em pedidos GraphQL ciLint, caminhos de ficheiro invulgarmente longos com carateres não ASCII e relatórios de falha do Ruby que apontam para o Onigmo. Verifique também ficheiros pertencentes ao utilizador git em /tmp, processos filho inesperados do Puma ou do Sidekiq, ligações de saída e alterações a crontabs ou chaves SSH. Qualquer indício de execução implica tratar o servidor como comprometido e rodar o gitlab-secrets.json, todas as variáveis de CI/CD, os tokens de runner e os tokens de acesso.
  • Reduza a superfície de ataque: limite quem pode criar contas e tokens de acesso pessoal.
  • Utilizadores do Alpine: definam uma nova palavra-passe através de "Forgot your password?" quando o servidor reabrir e mudem-na em qualquer outro sítio onde a tenham reutilizado; o Alpine detetou tentativas de credential stuffing com palavras-passe divulgadas noutros sites. Quem usa a imagem alpinelinux/gitlab deve voltar a descarregar a tag 19.3.6, já que só a imagem publicada a 27 de outubro inclui o Ruby 3.3.13. Os pacotes de Ruby do próprio Alpine já estão corrigidos (3.4.12 no Alpine 3.22, 3.23, 3.24 e edge; 3.3.13 no 3.21) e o apk upgrade instala-os.

Os responsáveis pelo Ruby sublinham que o bug só importa para programas que compilam uma expressão regular a partir de texto controlado por um atacante, e que a definição Regexp.timeout não oferece qualquer proteção.

A lição que o Alpine aprendeu da pior maneira é que atualizar uma aplicação nada diz sobre o runtime que está por baixo. Uma simples verificação da versão do GitLab exposto teria passado; só um teste do comportamento real, ou um inventário que inclua a build do Ruby, o teria apanhado. É precisamente essa distância entre "corrigido no papel" e "corrigido na prática" que o nosso serviço de scanning de vulnerabilidades foi concebido para revelar na sua infraestrutura exposta à internet, antes que o ficheiro de CI manipulado de outra pessoa o faça por si.

PARTILHAR