Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
freebsd-dirent-info-leak-bugs — CVE-2020-25578 e CVE-2020-25579: Alguns bugs de vazamento de informação no FreeBSD que encontrei em 2020. | Kitploit
Ferramentas/GitHubGitHub/farazsth98/freebsd-dirent-info-leak-bugs
Forensia de MemóriaAnálise de VulnerabilidadesExploraçãoColeta de InformaçõesAnálise de Binários
GitHubfarazsth98/freebsd-dirent-info-leak-bugs

freebsd-dirent-info-leak-bugs

CVE-2020-25578 e CVE-2020-25579: Alguns bugs de vazamento de informação no FreeBSD que encontrei em 2020.

Ver Repositório

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
722há 5 anosAinda não revisado

Como encontrei os bugs?

  1. Decidi aleatoriamente auditar os sistemas de arquivos do FreeBSD
  2. Pesquisei um pouco e descobri que o sistema de arquivos padrão em uso é uma combinação de FFS e UFS
  3. Passei algum tempo auditando ufs_create e não encontrei bugs
  4. Fui aqui e examinei o histórico de commits das funções do sistema de arquivos UFS
  5. Encontrei este commit sobre vazamento de informações através de bytes de preenchimento em objetos struct dirent alocados na pilha
  6. Analisei o patch e descobri que o patch para msdosfs_readdir está incompleto. Eles corrigiram uma instância do bug, mas não uma segunda.
  7. Escrevi um PoC para confirmar que posso vazar 3 bytes do preenchimento. Depois comecei a procurar variantes.
  8. Encontrei as variantes em mqueuefs, autofs, smbfs e tmpfs que me permitem vazar um ponteiro completo de 8 bytes. Escrevi PoC para confirmar.

Bug original

Como mencionado acima, o bug original que encontrei estava em msdosfs_readdir enquanto analisava o patch do commit vinculado acima.

O fluxo básico para chamar readdir no FreeBSD é o seguinte:

root@kitploit:~
#include <dirent.h>

int main(void) {
    struct dirent *dp;
    DIR *dirp;

    dirp = opendir("./somedir");
    dp = readdir(dirp);
}

Dependendo do sistema de arquivos onde somedir reside, qualquer uma das várias funções *_readdir do kernel do FreeBSD pode ser chamada.

O patch acima adiciona uma função chamada dirent_terminate que tem a intenção de ser chamada antes que um objeto struct dirent seja retornado ao espaço do usuário (geralmente feito usando a função uiomove). Essa função zerará os bytes de preenchimento, bem como quaisquer bytes restantes no campo d_name da estrutura. A definição de struct dirent está aqui.

Olhando o patch, na linha 1562, você pode ver dirent_terminate sendo chamada com a variável dirbuf como argumento. Em seguida, uiomove é chamado para copiar o conteúdo de dirbuf de volta ao espaço do usuário. No entanto, observe que essas linhas de código estão dentro do bloco desta instrução if. O comentário acima desta instrução if explica que este ramo só é executado se readdir for chamado na raiz do sistema de arquivos MSDOS, então podemos simplesmente pular esta instrução if chamando readdir em qualquer subdiretório além da raiz do sistema de arquivos.

Mais abaixo, vemos outra chamada para uiomove na linha 1691. No entanto, lendo o código atentamente, você verá que dirent_terminate não é chamada nesta instância, o que significa que os bytes de preenchimento permanecerão não inicializados. Infelizmente, o campo d_name foi zerado no início desta função (aqui), então não conseguimos um vazamento maior.

PoC

Primeiro, eu não tinha um pendrive, então tive que descobrir uma maneira de montar um sistema de arquivos MSDOS. O seguinte funciona:

root@kitploit:~
$ dd if=/dev/zero of=test.img bs=512 count=256000
$ sudo mdconfig -a -t vnode -f test.img
$ sudo newfs_msdos -s 131072000 /dev/md1 # Meu mdconfig retornou md1
$ mkdir ./temp
$ sudo mount -t msdosfs /dev/md1 ./temp
$ mkdir ./temp/test_dir

O PoC pode ser encontrado em original_poc.c. Basta compilar com clang e executá-lo no mesmo diretório dos comandos acima, e você verá os bytes vazados sendo impressos.

Variantes

Comecei a procurar variantes disso. Acho que apenas usei grep para uiomove\(&.*, que retornou cerca de 15-20 resultados, e verifiquei todos manualmente. Infelizmente, nenhuma das variantes existe no FreeBSD por padrão (os sistemas de arquivos precisam ser ativados manualmente / compilados no kernel). As funções com as variantes são as seguintes:

  1. mqfs_readdir
  2. tmpfs_dir_getdotdent
  3. tmpfs_dir_getdotdotdent
  4. smbfs_readvdir
  5. autofs_readdir_one

O bug é exatamente o mesmo em todas essas funções, então vou cobrir apenas mqfs_readdir.

  1. Primeiro, uma struct dirent entry é alocada na pilha
  2. Em seguida, dirent_terminate é chamada para zerar o preenchimento + os campos d_name da estrutura
  3. Finalmente, vfs_read_dirent é chamada. Esta função chamará uiomove para copiar a estrutura para o espaço do usuário

Tudo parece bom até agora, certo? Não necessariamente. Temos que garantir que todos os campos da estrutura estejam inicializados. Se você olhar atentamente o código, verá que o campo d_off fica não inicializado. O tipo deste campo é off_t, que é essencialmente um int64_t. Quando a estrutura é copiada para o espaço do usuário, obtemos dados não inicializados neste campo.

PoC

Este mesmo PoC funcionará para todas as variantes, basta executá-lo em um sistema de arquivos diferente. Para mqueuefs, faça o seguinte (precisa que mqueuefs esteja ativado / compilado no kernel primeiro):

root@kitploit:~
$ mkdir ./temp
$ sudo mount -t mqueuefs null ./temp

O PoC em si pode ser encontrado em variants_poc.c. Basta compilar com clang e executá-lo no mesmo diretório dos comandos acima. Você verá ponteiros do kernel sendo impressos (presumivelmente um ponteiro de pilha e um ponteiro de seção de código / heap, não verifiquei).

Baixar ferramenta