flawopen.com/Teardowns/cve-2024-32002-git-submodule-rce
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.
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 comopost-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
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.
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.
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.
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.
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);
}
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
- ✓Atualize o Git para 2.45.1, 2.44.1, 2.43.4 ou posterior, que contêm proteções contra colisão de submódulos.
- ✓Desative o clone recursivo automático de submódulos em repositórios não confiáveis (git clone --no-recurse-submodules).
- ✓Imponha verificações de colisão de caminhos de arquivo nos runners de integração contínua e bots de build.
- ✓Configure core.protectNTFS e core.protectHFS como true em ambientes de desenvolvimento multiplataforma.
- ✓Audite os checkouts de repositório em busca de symlinks suspeitos que apontem para diretórios .git internos.