CVE-2021-39935
Priorize a correção. Ela está sob exploração confirmada pelo CISA.
Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.
Resumo
Falha de SSRF (CWE-918) na API CI Lint do GitLab CE/EE, que permite a usuários do tipo "external" (categoria de conta com acesso restrito, sem vínculo a grupos/projetos) forçar o servidor a fazer requisições HTTP para endereços arbitrários, inclusive redes internas. É uma correção incompleta de uma SSRF anterior na mesma API (report H1 #1110131) e está no catálogo KEV da CISA, mas o AC:H do CVSS reflete corretamente que ela só se manifesta sob uma configuração específica de cadastro de usuários — não é um SSRF anônimo genérico.
Detalhamento técnico
O endpoint CI Lint (usado para validar sintaxe de `.gitlab-ci.yml` antes de rodar um pipeline) processa diretivas de include que podem apontar para recursos remotos. Uma correção anterior tentou restringir esse comportamento para usuários externos, mas o bloqueio dependia de checagens de pertencimento a grupo/projeto que não cobriam todos os caminhos de autorização do endpoint.
O cenário documentado no HackerOne #1236965 (issue 346187) descreve uma instância com self sign-up habilitado e a opção "Newly registered users will by default be external" ativa. Nesse caso, qualquer pessoa que se autocadastra recebe automaticamente a flag de usuário externo — que, por definição, não tem acesso a nenhum grupo/projeto até um admin atribuir manualmente. A expectativa de segurança é que esse usuário não consiga interagir com nada sensível, mas a API CI Lint continuava aceitando chamadas desse usuário e processando o conteúdo do YAML enviado, incluindo diretivas que disparam requisições HTTP feitas pelo servidor GitLab.
O atacante controla o corpo do YAML submetido ao lint, e portanto controla a URL/host de destino da requisição SSRF. O impacto declarado no CVSS é apenas de confidencialidade (C:H, I:N, A:N) — o servidor GitLab faz a requisição e algum resultado (erro de validação, conteúdo retornado, tempo de resposta) pode ser observado pelo atacante através da resposta da API, permitindo scanning de rede interna e, potencialmente, acesso a serviços de metadata de cloud ou endpoints administrativos não expostos externamente.
Como é explorada
Pré-requisito real: uma conta no GitLab classificada como "external user", tipicamente obtida por self sign-up quando a instância tem cadastro aberto e a opção de tornar novos usuários externos por padrão está ativa. Não é um SSRF totalmente não autenticado — é preciso ter uma conta, mesmo que mínima e sem acesso a projeto algum. Isso explica o AC:H no vetor CVSS: a condição de configuração (sign-up aberto + default external) não é universal, e instâncias com cadastro fechado ou sem essa opção não expõem esse caminho.
Com a conta em mãos, o atacante chama a API CI Lint (endpoint de validação de pipeline) submetendo um `.gitlab-ci.yml` cujo conteúdo referencia um recurso remoto controlado pelo atacante quanto ao destino. O servidor GitLab processa esse conteúdo do lado servidor, fazendo a requisição de rede em nome da aplicação — não do navegador do atacante — permitindo alcançar hosts internos inacessíveis externamente (rede interna do provedor de hospedagem, serviços de metadata, outros serviços atrás do firewall).
A vulnerabilidade está no catálogo KEV da CISA, o que indica exploração confirmada em ambientes reais, mas as fontes disponíveis não detalham campanha específica, atores ou se houve uso em ransomware (a própria entrada do KEV marca isso como "Unknown"). Trate a listagem no KEV como confirmação de risco prático, não como evidência de exploração massiva ou automatizada generalizada.
Versões
Como se proteger
A correção definitiva é atualizar para GitLab 14.3.6, 14.4.4 ou 14.5.2 (ou qualquer versão posterior dentro desses branches), que fecham a lacuna de autorização no endpoint CI Lint para usuários externos. Instâncias em versões anteriores a 10.5 não são listadas como afetadas pelo advisory, mas qualquer instância entre 10.5 e as versões corrigidas está exposta se a pré-condição de configuração existir.
Se a atualização imediata não for viável, o paliativo real é eliminar a pré-condição: desabilitar self sign-up (cadastro aberto de novos usuários) ou, pelo menos, desativar a opção que torna novos usuários externos por padrão, revisando manualmente atribuições de grupo/projeto. Isso não corrige a falha de autorização em si, mas remove o vetor de entrada mais acessível descrito no relatório. Como controle compensatório adicional, restringir egress de rede do host que executa o GitLab (bloquear acesso a faixas internas/RFC1918 e a endpoints de metadata de cloud a partir do processo da aplicação) reduz o impacto de qualquer SSRF residual nessa ou em outras APIs.
Não adianta apenas revogar acesso de usuários externos a projetos específicos ou confiar na flag "external" como controle de segurança suficiente — é exatamente essa suposição que a falha quebra. Monitorar/restringir manualmente contas externas sem atualizar o GitLab deixa o vetor da API CI Lint aberto.
Como detectar
Procurar nos logs da API por chamadas ao endpoint CI Lint (`/api/v4/projects/:id/ci/lint` ou `/api/v4/ci/lint`) originadas de contas marcadas como usuário externo, especialmente quando o corpo do YAML enviado contém diretivas de include apontando para hosts fora do domínio esperado, endereços link-local (ex.: 169.254.169.254) ou faixas internas RFC1918. Também vale correlacionar com logs de rede de saída (egress) do servidor GitLab buscando conexões incomuns originadas do processo da aplicação/Sidekiq para destinos internos ou de metadata de nuvem.
Não há assinatura única confiável, porque o tráfego malicioso passa por um endpoint legítimo (lint de pipeline) usado normalmente por qualquer desenvolvedor; a diferenciação depende do contexto — conta sem vínculo a projeto, payload de include incomum e destino de rede fora do padrão da organização.