FlawOpen

flawopen.com/Teardowns/cve-2024-32002-git-submodule-rce

● CVE-2024-32002 · CVSS 9.0 · Crítica
Pesquisa · FlawOpen

CVE-2024-32002: RCE via Links Simbólicos de Submódulos Git

A CVE-2024-32002 permitia que um repositório Git preparado gravasse, por meio de um symlink com colisão de maiúsculas e minúsculas, dentro de .git durante o clone recursivo, possibilitando a execução de um hook antes da inspeção. A correção upstream do Git verifica o destino do submódulo antes e depois do clone e interrompe a operação diante de conteúdo inesperado; atualize para uma versão corrigida.

💡 Explicação em Linguagem Simples (ELI5)

Imagine um depósito em que as placas tratam A e a como a mesma porta. Se o caminho de um submódulo passar por uma placa que redireciona para a sala de registros (.git), arquivos destinados a um setor podem parar nos registros internos do Git. A correção verifica o destino antes e depois do clone e interrompe a operação quando encontra conteúdo inesperado.

Conceitos Centrais e Termos

Submódulo Git
Um repositório Git incorporado como subdiretório dentro de outro repositório pai.
Link Simbólico (Symlink)
Um objeto de sistema de arquivos que redireciona o caminho para outro alvo.
Colisão de Caixa (Case Collision)
Comportamento no NTFS e APFS onde caminhos que diferem apenas em maiúsculas/minúsculas apontam para o mesmo arquivo.
Ganchos do Git (Git Hooks)
Scripts executáveis em .git/hooks/ acionados automaticamente durante operações como post-checkout.

Mapeamentos de frameworks

Análise de Causa Raiz

Em um sistema de arquivos que não diferencia maiúsculas de minúsculas e oferece suporte a symlinks, um repositório preparado podia definir um caminho de submódulo que colidia por diferença de caixa com um symlink. Durante o clone recursivo, o Git podia substituir por esse symlink um diretório criado para o clone e gravar arquivos fora do worktree do submódulo, dentro de .git. Um hook gravado ali podia ser executado antes de o usuário inspecionar o checkout. O patch upstream recusa clonar em um destino de submódulo preexistente e não vazio e, após o clone, rejeita destinos cujo conteúdo não se limite aos metadados .git.

Fluxo de Ataque Passo a Paso

Passo 1

O clone recursivo alcança metadados controlados pelo repositório

Uma pessoa clona recursivamente um repositório não confiável em um sistema de arquivos que não diferencia maiúsculas de minúsculas e no qual o Git oferece suporte a symlinks. O repositório fornece caminhos de submódulos e entradas versionadas que colidem após a conversão de caixa.

Passo 2

A colisão de caminhos atravessa um limite de confiança

O Git pode resolver o caminho colidente do submódulo por meio de um symlink, em vez de dentro do worktree esperado. O limite afetado é o tratamento de caminhos do sistema de arquivos durante o clone recursivo de submódulos.

Passo 3

Arquivos são gravados nos metadados do Git

A gravação redirecionada pode colocar um hook na área .git do repositório. O aviso do projeto Git confirma que um hook pode ser gravado ali e executado enquanto o clone ainda está em andamento.

Passo 4

O clone pode executar código antes da revisão

O Git executa o hook durante o clone, antes de a pessoa inspecionar os arquivos. As versões corrigidas verificam o estado do destino e interrompem a operação diante de arquivos inesperados.

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

Este trecho mostra parte da alteração upstream em C em clone_submodule(); não é uma função independente. Antes da correção, o caminho de clone mostrado não tinha a verificação correspondente do conteúdo do destino. A correção rejeita um diretório de checkout preexistente e não vazio e verifica, após o clone, se somente os metadados .git estão presentes; a função auxiliar examina as entradas do diretório. O commit upstream contém a implementação completa.

IMPLEMENTAÇÃO VULNERÁVEL
if (!file_exists(sm_gitdir)) {
    if (safe_create_leading_directories_const(sm_gitdir) < 0)
        die(_("could not create directory '%s'"), sm_gitdir);

    if (run_command(&cp))
        die(_("clone of '%s' into submodule path '%s' failed"),
            clone_data->url, clone_data_path);
}
PATCH SEGURO E ROBUSTO
struct stat st;

if (!file_exists(sm_gitdir)) {
    if (clone_data->require_init && !stat(clone_data_path, &st) &&
        !is_empty_dir(clone_data_path))
        die(_("directory not empty: '%s'"), clone_data_path);

    if (safe_create_leading_directories_const(sm_gitdir) < 0)
        die(_("could not create directory '%s'"), sm_gitdir);

    if (run_command(&cp))
        die(_("clone of '%s' into submodule path '%s' failed"),
            clone_data->url, clone_data_path);

    if (clone_data->require_init && !stat(clone_data_path, &st) &&
        !dir_contains_only_dotgit(clone_data_path)) {
        char *dot_git = xstrfmt("%s/.git", clone_data_path);
        unlink(dot_git);
        free(dot_git);
        die(_("directory not empty: '%s'"), clone_data_path);
    }
}

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

Fontes