FlawOpen

flawopen.com/Teardowns/cve-2024-7646-ingress-nginx-annotation-code-injection

● CVE-2024-7646 · CVSS 8.8 · Alta
Pesquisa · FlawOpen

CVE-2024-7646: bypass de validação no Ingress-NGINX

Um bypass por retorno de carro permitia injetar comandos e obter credenciais do controlador. Corrigido em 1.11.2/1.10.4; projeto encerrado.

💡 Explicação em Linguagem Simples (ELI5)

Imagine um porteiro que verifica se um formulário contém uma palavra permitida, mas não confere o valor inteiro. Um carriage return pode mudar como o próximo sistema interpreta o texto restante. Aqui, uma anotação passou por uma correspondência parcial e depois foi gravada na configuração NGINX gerada. A correção valida o valor completo e trata carriage returns com segurança.

Conceitos Centrais e Termos

Objeto Ingress
Recurso da API Kubernetes que descreve o roteamento de um host ou caminho para um Service. Usuários podem receber permissão para criá-lo sem serem administradores do cluster.
Bypass de validação de anotação
Uma anotação passou por um validador que encontrou uma substring permitida, sem exigir que o valor inteiro correspondesse a uma opção aceita.
Carriage return (`\r`)
Caractere de controle usado como quebra de linha em alguns formatos. Se validação e geração de configuração o interpretarem de modo diferente, ele pode alterar o início das linhas.
Service account do controlador
Identidade Kubernetes usada pelo controlador ingress-nginx. O aviso upstream diz que, na configuração padrão, suas permissões podem incluir acesso a todos os Secrets do cluster.

Mapeamentos de frameworks

  • Referência CWE para a fraqueza descrita neste guia: CWE-20

Análise de Causa Raiz

CVE-2024-7646 é um bypass de validação de anotações no ingress-nginx, não o uso irrestrito de um snippet Lua personalizado. O validador de auth-tls-verify-client usava uma expressão regular Go sem âncoras de início e fim; por isso, MatchString podia aceitar um valor maior que contivesse uma opção permitida apenas como substring. Um carriage return na anotação podia então ser interpretado de forma diferente durante a limpeza da configuração NGINX gerada. A correção upstream exige correspondência do valor inteiro e trata carriage returns isolados em cleanConf. O aviso de segurança do Kubernetes diz que alguém com permissão para criar Ingress pode contornar a validação, injetar comandos e obter as credenciais do controlador; na configuração padrão, elas podem acessar todos os Secrets do cluster. É um caminho autenticado pela API Kubernetes, de alta gravidade (CVSS 8.8), não uma requisição anônima da rede. O projeto foi aposentado em março de 2026; atualizar para a correção histórica é contenção imediata, mas as implantações devem migrar para um controlador mantido ou uma implementação da Gateway API.

Fluxo de Ataque Passo a Paso

Passo 1

O usuário pode criar um Ingress

O invasor precisa de permissão na API Kubernetes para criar um objeto Ingress. O risco é maior em clusters multi-tenant que delegam essa permissão a equipes de aplicação.

Passo 2

Uma anotação passa por correspondência parcial

A expressão regular vulnerável de auth-tls-verify-client não tinha âncoras. Assim, Go MatchString podia aceitar um valor maior que contivesse uma opção permitida, em vez de exigir o valor exato.

Passo 3

O carriage return atravessa a fronteira da configuração

A anotação é incorporada à configuração NGINX gerada. A série de correções trata tanto a validação do valor inteiro quanto carriage returns isolados durante a limpeza da configuração.

Passo 4

A identidade do controlador fica exposta

O aviso Kubernetes informa que a injeção de comandos pode obter as credenciais do controlador. Na configuração padrão, essa service account pode acessar todos os Secrets; o impacto depende do RBAC implantado.

Código-Fonte: Vulnerável vs. Seguro

Estes são trechos das correções upstream da CVE-2024-7646: a PR #11719 ancora os valores permitidos de auth-tls-verify-client, e a PR #11721 trata carriage returns isolados em cleanConf. A branch 1.10 recebeu as alterações correspondentes nas PRs #11718 e #11722. O código omite a lógica ao redor que não é relevante.

IMPLEMENTAÇÃO VULNERÁVEL
// internal/ingress/annotations/authtls/main.go (antes)
authVerifyClientRegex = regexp.MustCompile(`on|off|optional|optional_no_ca`)

// internal/ingress/controller/template/template.go (antes)
switch c {
case ' ', '\t':
    needOutput = lineStarted
case '\n':
    needOutput = !(!lineStarted && emptyLineWritten)
    nextLineStarted = false
}
PATCH SEGURO E ROBUSTO
// internal/ingress/annotations/authtls/main.go (corrigido)
authVerifyClientRegex = regexp.MustCompile(`^(on|off|optional|optional_no_ca)$`)

// internal/ingress/controller/template/template.go (corrigido)
switch c {
case '\r':
    rest := in.Bytes()
    if len(rest) > 0 && rest[0] != '\n' {
        c = ' '
        needOutput = lineStarted
    }
case '\n':
    needOutput = !(!lineStarted && emptyLineWritten)
    nextLineStarted = false
}

Lista de Verificação de Segurança para Engenharia

Fontes