
Exercício de detecção em laboratório para DirtyFrag (CVE-2026-43284) - escalada de privilégio no kernel do Linux via corrupção do cache de página xfrm-ESP. Documentação completa abordando execução de exploit, lacunas de detecção e regras EQL corrigidas usando Elastic Stack
Classificação: Laboratório Interno - CyberLAB
Data: 24 de Maio de 2026
Plataforma: Elastic Stack v9.4.1
Status: Detecção Confirmada
Um exercício controlado de exploração simulando um adversário pós-acesso inicial usando DirtyFrag (CVE-2026-43284), uma vulnerabilidade de escalada de privilégios no kernel Linux. O cenário do atacante simulado: um usuário com privilégios baixos (saskia, uid=1001) obtido via credenciais de phishing tenta escalar para root em um host Linux interno. O laboratório utilizou uma máquina Ubuntu deliberadamente vulnerável (ubuntu-vuln, kernel 6.0.0-22-generic) isolada de redes de produção.
O atacante alcançou acesso total como root (uid=0) dentro do ambiente de laboratório. A pilha de detecção Elastic Security gerou 3 alertas de ALTA gravidade (pontuação de risco 73) identificando corretamente a cadeia de exploração. No entanto, a detecção exigiu ajuste manual - a configuração padrão tinha lacunas que teriam resultado em alertas perdidos.
Conclusão: Hosts Linux não corrigidos executando kernel <= 6.x estão vulneráveis. Se um atacante já possui um ponto de apoio com privilégios baixos, este exploit concede root total de forma silenciosa e rápida, sem deixar rastros visíveis no disco para ferramentas de integridade de arquivos.
auditd não produzem evidências. Sem regras explícitas de syscall para socket, splice e unshare, o exploit é executado silenciosamente - sem logs, sem alertas. A implantação padrão do Elastic Agent não adiciona essas regras automaticamente.process.parent.pid como chave de correlação. Na prática, o DirtyFrag cria processos intermediários (fork), quebrando essa correlação. A correção - correlacionar por auditd.session - foi identificada e implementada durante este exercício./etc/shadow, acessou chaves autorizadas SSH, escreveu um marcador de persistência (/root/pwned.txt) e iniciou reconhecimento de rede via nc. Tudo ocorreu dentro de 30 minutos após o acesso inicial.Objetivo: Validar a cobertura de detecção para exploração do DirtyFrag no SOC do laboratório doméstico, identificar lacunas de detecção e produzir uma regra de detecção corrigida com base no comportamento observado do atacante.
Modelo de ameaça: Adversário simulado pós-acesso inicial com credenciais de phishing para uma conta de usuário com privilégios baixos (saskia, uid=1001). Objetivo: escalada de privilégios para root via DirtyFrag usando o caminho de recebimento xfrm-ESP. Execução em laboratório realizada via console Proxmox - funcionalmente equivalente a SSH pós-acesso.
Dois níveis de capacidade do atacante foram considerados:
Este exercício cobriu o nível vanilla.
DirtyFrag é o terceiro de uma família de bugs relacionados no kernel Linux que todos abusam da mesma causa raiz:
Causa raiz: Os caminhos de anexação de datagramas IPv4/IPv6 não definiam SKBFL_SHARED_FRAG após skb_splice_from_iter() plantar uma página do cache de páginas em um buffer de socket (sk_buff). O caminho de entrada ESP então realizava criptografia in-place em páginas do cache de páginas controladas pelo atacante, tratando-as como skbs não lineares comuns não clonadas.
Primitiva do exploit: Escrita controlada de 4 ou 8 bytes no cache de páginas. Determinístico - nenhuma condição de corrida necessária.
Cadeia do exploit:
/usr/bin/su) no cache de páginassplice() para que a página do arquivo fique em frag[0] de struct sk_buffxfrm-ESPexecve() do kernel - retornam bytes corrompidosPropriedade crítica de evasão: O arquivo no disco nunca é modificado. Ferramentas de monitoramento de integridade de arquivos (AIDE, Tripwire, verificações de hash) todas reportam o arquivo alvo como limpo.
Distribuições vulneráveis confirmadas: Ubuntu 24.04.4, RHEL 10.1, AlmaLinux 10, openSUSE Tumbleweed, CentOS Stream 10, Fedora 44.
Telemetria ativa no momento do exercício:
Rede do laboratório isolada antes do exercício. Firewall alias Cyber_escape_door confirmado desabilitado - impedindo alcance lateral para outras VLANs ou internet.

Kernel vulnerável e conta com privilégios baixos confirmados no ubuntu-vuln:```
saskia@ubuntu-vuln:$ uname -r
6.0.0-22-generic
saskia@ubuntu-vuln:$ whoami
saskia
saskia@ubuntu-vuln:~$ id
uid=1001(saskia) gid=1001(saskia) groups=1001(saskia),27(sudo),100(users)

#### 4.3 Verificação de Integridade da Stack
**Suricata: em execução e capturando (systemctl status)**

**Kibana/Elasticsearch: verde/saudável (verificação de API)**

**Snapshots de VM tirados antes de quaisquer alterações**



#### 4.4 Captura de Rede
tcpdump iniciado no host Suricata (`emp6s19`, comprimento de snapshot 262144 bytes) para captura completa de pacotes do tráfego de `172.66.66.27`.


---
### 5. Fase 2 - Execução do Exploit
#### 5.1 Preparação
Código-fonte do exploit (`exp.c`) do PoC V4bel/dirtyfrag preparado no host vítima.```bash
ubuntu-vuln@ubuntu-vuln:~/dirtyfrag$ ls
exp exp.c README.md
ubuntu-vuln@ubuntu-vuln:~/dirtyfrag$ cp exp.c /tmp/exp/
Compilado como root via sudo gcc (o usuário saskia está no sudoers):

Terminal à direita mostra a cópia preparada visível para o usuário saskia.```
saskia@ubuntu-vuln:$ sudo gcc -o /tmp/exp/clean_frag /tmp/exp/exp.c
saskia@ubuntu-vuln:$ ls -la /tmp/exp/
-rwxr-xr-x 1 root root 62320 May 24 12:18 clean_frag
-rw-rw-r-- 1 ubuntu-vuln ubuntu-vuln 67803 May 24 12:13 exp.c
saskia@ubuntu-vuln:~$ id
uid=1001(saskia) gid=1001(saskia) groups=1001(saskia),27(sudo),100(users)
Binary: ELF 64-bit LSB executável, x86-64, linked dinamicamente.

#### 5.3 Execução - Root Obtido
Exploit executado como `saskia` (uid=1001). O processo (`clean_frag`, pid=4326) abriu sockets `AF_RXRPC` e `AF_ALG`, depois chamou `splice()` para plantar a página do cache de páginas no buffer de rede. A criptografia in-place no caminho ESP escreveu bytes controlados pelo atacante no cache de páginas. Um processo filho (pid=4327) chamou `unshare` com `a0=50000000` (CLONE_NEWUSER | CLONE_NEWNET) para obter capacidades com escopo de namespace.```
saskia@ubuntu-vuln:~$ /tmp/exp/clean_frag
...
root@ubuntu-vuln:~# id
uid=0(root) gid=0(root) groups=0(root)
root@ubuntu-vuln:~# ls
Shell completo obtido às 12:22 CEST (10:22 UTC), 24 de maio de 2026.
Sequência de syscalls do auditd capturada (UTC):
Todos os eventos compartilham auditd.session=2.

Todas as ações executadas como root em ubuntu-vuln a partir de ~12:22 CEST.
root@ubuntu-vuln:# echo "Dirty Frag PoC executed at $(date)" > /root/pwned.txt
root@ubuntu-vuln:# cat /root/pwned.txt
Dirty Frag PoC executed at Sun May 24 12:28:05 PM CEST 2026

#### 6.2 Acesso a Credenciais```bash
root@ubuntu-vuln:~# cat /etc/shadow | head -2
root:*:19823:0:99999:7:::
daemon:*:19823:0:99999:7:::
root@ubuntu-vuln:~# cat /home/ubuntu-vuln/.ssh/authorized_keys
ssh-ed25519 AAAA[...]
Ficheiro shadow e chaves autorizadas SSH acedidos. Num compromisso real, isto permite a quebra de palavras-passe offline e acesso persistente de backdoor SSH.

root@ubuntu-vuln:~# nc -vz 172.66.66.1 100-8000
Varredura de portas do gateway do laboratório (`172.66.66.1`, portas 100-8000) executada a partir do contexto root às 12:51 CEST. Isso demonstra capacidade de movimentação lateral e mapeamento de rede a partir de uma sessão com privilégios elevados.

#### 6.4 Visibilidade de Rede do Suricata
O Suricata capturou **105 eventos** associados a `172.66.66.27` durante a janela do exercício (88 mdns, 17 flow). No momento em que a captura de tela foi tirada (durante a varredura nc por volta das 12:53 CEST), 29 eventos estavam visíveis no painel.
O próprio exploit DirtyFrag é interno ao kernel e não produz assinatura de rede - a primitiva de escalada não gera tráfego anômalo na rede. O Suricata foi utilizado para coletar pcaps de tráfego pós-exploração e tentativas de enumeração, em vez de detectar o exploit em si.
| Tipo de Evento | Contagem |
| ---------- | ----- |
| mdns | 88 |
| flow | 17 |
| **Total** | **105** |
Os eventos de flow se agrupam em torno da janela de varredura de portas nc (10:50-11:10 UTC / 12:50-13:10 CEST).

---
### 7. Fase 4 - Engenharia de Detecção
#### 7.1 Regras de Detecção Implantadas
Duas regras de sequência EQL foram criadas no Mecanismo de Detecção do Kibana com base no artigo do Elastic Security Labs.
**Regra 1 - Socket AF_RXRPC ou AF_ALG com Splice Seguido de Execução** (não disparou - veja a lacuna abaixo)```eql
sequence with maxspan=60s
[any where host.os.type == "linux" and
(
(event.category == "process" and auditd.data.syscall == "socket"
and auditd.data.a0 in ("26", "21")) or
(event.category == "process" and auditd.data.syscall == "splice") or
(event.category == "network" and event.action == "bound-socket"
and data_stream.dataset == "auditd_manager.auditd"
and auditd.data.socket.family == "38")
)
and user.id != "0"] by process.pid, host.id, user.id with runs=10
[process where host.os.type == "linux" and event.action == "executed" and
(
(user.effective.id == "0" and user.id != "0") or
(process.name in ("bash", "sh", "zsh", "dash", "fish", "ksh", "busybox")
and process.args in ("-c", "--command", "-ic", "-ci", "-cl", "-lc",
"-bash", "-sh", "-zsh", "-dash", "-fish", "-ksh"))
)] by process.parent.pid, host.id, user.id
Regra 2 - Manipulação de Namespace Seguida de Escalação de Privilégios (acionado após correção)```eql sequence by host.id, auditd.session with maxspan=30s [process where host.os.type == "linux" and auditd.data.syscall == "unshare" and auditd.data.a0 in ("10000000", "50000000", "70000000", "10020000", "50020000", "70020000") and user.id != "0" and user.id != null] [process where host.os.type == "linux" and user.id == "0" and user.id != null and (process.name in ("bash", "sh", "zsh", "dash", "fish", "ksh", "su", "sudo", "pkexec", "busybox", "mksh") or process.name like ("python*", "perl*", "ruby*", "php*", "lua*"))]
#### 7.2 Lacuna de Detecção Inicial - Cobertura de Syscall Faltante
A Regra 1 retornou zero resultados. A configuração padrão do auditd em `ubuntu-vuln` capturou apenas: `write`, `bpf`, `openat`, `unshare`.
Faltando: `socket`, `splice`, `bind` - as primitivas principais do exploit.
**Remediação:** Adicionado em `/etc/audit/rules.d/dirtyfrag.rules`:```
-a always,exit -F arch=b64 -S socket -k socket_syscall
-a always,exit -F arch=b32 -S socketcall -k socket_syscall
-a always,exit -F arch=b64 -S splice -k splice-syscall
-a always,exit -F arch=b32 -S splice -k splice-syscall
-a always,exit -F arch=b64 -S unshare -k unshare-syscall
-a always,exit -F arch=b32 -S unshare -k unshare-syscall
272 novos eventos auditd chegaram ao Elasticsearch segundos após a execução do exploit.
Apesar dos eventos serem capturados, a Regra 2 retornou 0 correspondências.
Causa raiz - árvore de processos real (do Elasticsearch):
A regra original correlacionava por process.parent.pid. O evento unshare tinha ppid=4326, mas o shell root tinha um pai diferente - DirtyFrag cria processos intermediários, quebrando a correlação.
Correção: Correlacionar por auditd.session. Todos os eventos na cadeia do exploit compartilhavam session=2, vinculando corretamente a sequência independentemente da profundidade dos forks.
3 alertas de alta severidade, pontuação de risco 73, no Kibana Security - Alertas em 2026-05-24T10:25:57Z UTC (12:25:57 CEST).
| Alerta | Timestamp (UTC) | Sinal |
|---|---|---|
| Correspondência de sequência - evento unshare | 10:25:57.869 | process=clean_frag, user=saskia (uid=1001) |
| Correspondência de sequência - shell root | 10:25:57.881 | process=bash, user=root (uid=0) |
DirtyFrag - Manipulação de Namespace Seguida de Escalação de Privilégiosubuntu-vuln

Todos os eventos auditd relacionados ao dirtyfrag:```kql data_stream.dataset: "auditd_manager.auditd" and auditd.summary.how: dirtyfrag
**Manipulação de namespace por não-root:**```kql
data_stream.dataset: "auditd_manager.auditd" and auditd.data.syscall: "unshare" and auditd.data.a0: "50000000"
Atividade de root pós-escalada na mesma sessão:```kql data_stream.dataset: "auditd_manager.auditd" and user.id: "0" and auditd.session: "2"
**Todos os eventos do auditd durante a janela de exploração:**```kql
data_stream.dataset: "auditd_manager.auditd" and @timestamp >= "2026-05-24T10:20:00Z" and @timestamp <= "2026-05-24T10:30:00Z"
Syscalls de socket e splice do processo de exploit:```kql data_stream.dataset: "auditd_manager.auditd" and auditd.summary.how: "/tmp/exp/clean_frag"
---
### 9. Resumo das Principais Descobertas
| # | Descoberta | Severidade | Remediado |
| - | ------- | -------- | ---------- |
| 1 | As regras padrão do auditd não capturam `socket`, `splice`, `unshare` - nenhuma evidência sem regras explícitas | Crítico | Sim - regras personalizadas implantadas em `/etc/audit/rules.d/dirtyfrag.rules` |
| 2 | A correlação EQL por `process.parent.pid` falha para cadeias de exploração bifurcadas | Alta | Sim - alterado para `auditd.session` |
| 3 | Monitoramento de integridade de arquivos cego para DirtyFrag - arquivos em disco inalterados durante todo o processo | Alta | Nenhuma remediação no escopo - corrigir o kernel é a solução |
| 4 | Pós-exploração: arquivo shadow, chaves SSH e reconhecimento de rede todos executados como root antes de qualquer resposta baseada em alerta | Alta | Detectado via logs do auditd; nenhuma regra dedicada foi acionada para acesso a credenciais ou fase de reconhecimento |
---
### 10. Referências
- Elastic Security Labs: [Copy Fail e DirtyFrag: Erros de Página do Linux na Natureza](https://www.elastic.co/security-labs/copy-fail-dirtyfrag-linux-page-bugs-in-the-wild)
- Prova de Conceito Pública: [V4bel/dirtyfrag no GitHub](https://github.com/V4bel/dirtyfrag)
- MITRE ATT&CK: [T1068 - Exploração para Escalação de Privilégio](https://attack.mitre.org/techniques/T1068/)
- MITRE ATT&CK: [TA0004 - Escalação de Privilégio](https://attack.mitre.org/tactics/TA0004/)
- MITRE ATT&CK: [T1003.008 - /etc/passwd e /etc/shadow](https://attack.mitre.org/techniques/T1003/008/)
| Item | Detalhe |
|---|
| Vulnerabilidade | DirtyFrag - CVE-2026-43284 (caminho xfrm-ESP), CVE-2026-43500 (caminho RxRPC) |
| Impacto CVSS | Escalada total de privilégios local para root |
| Kernels afetados | Linux kernel >= janeiro de 2017 (vida útil de 9 anos) |
| Distros afetadas | Ubuntu 24.04.4, RHEL 10.1, AlmaLinux 10, openSUSE, CentOS Stream 10, Fedora 44 |
| Bypass de integridade de arquivos | Arquivos no disco inalterados - AIDE, Tripwire, monitoramento de hash reportam todos como limpos |
| PoC público | Disponível (V4bel/dirtyfrag no GitHub) |
| Tempo para root | < 10 minutos a partir do ponto de apoio com privilégios baixos |
| Prioridade | Ação |
|---|
| Imediata | Corrigir o kernel Linux para uma versão corrigida em todos os hosts. Aplicar avisos de segurança dos fornecedores para Ubuntu, RHEL, AlmaLinux, openSUSE, CentOS, Fedora. |
| Curto prazo | Implantar regras explícitas de syscall do auditd para socket, splice e unshare em todos os hosts Linux monitorados pelo Elastic Agent. |
| Curto prazo | Atualizar regras de detecção EQL para correlacionar por auditd.session em vez de process.parent.pid para sequências de manipulação de namespace. |
| Contínuo | Tratar alertas de escalada de privilégios com pontuação de risco >= 73 como triagem de alta prioridade. A regra atual dispara em segundos após a escalada. |
| CVE | Apelido | Introduzido | Caminho |
|---|
| CVE-2022-0847 | Dirty Pipe | - | pipe |
| CVE-2026-31431 | Copy Fail | - | splice |
| CVE-2026-43284 | DirtyFrag | Jan 2017 (commit cac2661c53f3) | xfrm-ESP |
| CVE-2026-43500 | DirtyFrag | Jun 2023 (commit 2dc334f1a63a) | RxRPC |
| Componente | Detalhes |
|---|
| Servidor Fleet / host ELK | ubuntu-tm / elk-docker - 172.66.66.30 (interno do laboratório) |
| Elastic Stack | v9.4.1 (Elasticsearch, Kibana, Logstash - Docker) |
| Host alvo (vítima) | ubuntu-vuln - 172.66.66.27 |
| Kernel da vítima | 6.0.0-22-generic (vulnerável) |
| Usuário da vítima | saskia - uid=1001, grupos=1001(saskia),27(sudo),100(users) |
| Elastic Agent | v9.4.1 com auditbeat |
| IDS de rede | Suricata 8.0.5 em sensor dedicado |
| Kibana | http://172.66.66.30:5601 (interno do laboratório) |
| Conjunto de Dados | Participação |
|---|
suricata.eve | 75.2% |
elastic_agent.fleet_server | 10.8% |
elastic_agent | 9.1% |
elastic_agent.filebeat | 1.9% |
elastic_agent.auditbeat | 1.4% |
auditd_manager.auditd | 0.5% |
system.auth | 0.2% |
system.syslog | 0.1% |
| Timestamp (UTC) | Syscall | Argumento | Processo (pid) | Usuário |
|---|
| 10:21:11.054 | unshare | a0=50000000 | clean_frag (4327) | saskia (1001) |
| 10:21:11.055 | socket | a0=21 (AF_RXRPC) | clean_frag (4326) | saskia (1001) |
| 10:21:17.403 | socket | a0=26 (AF_ALG) | clean_frag (4326) | saskia (1001) |
| 10:21:17.419 | splice | a0=4 | clean_frag (4326) | saskia (1001) |
| 10:21:17.419 | splice | a0=7 | clean_frag (4326) | saskia (1001) |
| Processo | PID | PPID | UID | auditd.session |
|---|
| shell (saskia) | 4182 | - | 1001 | 2 |
clean_frag (principal) | 4326 | 4182 | 1001 | 2 |
clean_frag (filho unshare) | 4327 | 4326 | 1001 | 2 |
bash (root) | - | 4451 | 0 | 2 |
| Alerta de sequência composta | 10:25:57.893 | host=ubuntu-vuln |
| Tática | Técnica | ID |
|---|
| Escalação de Privilégios | Exploração para Escalação de Privilégios | T1068 |
| Escalação de Privilégios | Escape para o Host | T1611 |
| Acesso a Credenciais | Dump de Credenciais do SO: /etc/passwd e /etc/shadow | T1003.008 |
| Descoberta | Descoberta de Serviços de Rede | T1046 |
| Syscall | Argumento | Significado |
|---|
unshare | a0=50000000 | CLONE_NEWUSER | CLONE_NEWNET |
socket | a0=26 | AF_ALG (subsistema de criptografia do kernel) |
socket | a0=21 | AF_RXRPC (caminho RxRPC) |
bind | socket.family=38 | ligação AF_ALG |
splice | - | Injeção de página em buffers de rede |