
LID — Linux Integrity Drift: Contornando AppArmor via reescrita de pathname eBPF. Manipulação de argumentos de chamada de sistema pré-LSM com pegada de auditoria zero. "Linux is Dying"
```
██╗ ██╗██████╗
██║ ██║██╔══██╗
██║ ██║██║ ██║
██║ ██║██║ ██║
███████╗██║██████╔╝
╚══════╝╚═╝╚═════╝
```
— "O Linux está Morrendo" —
Descoberta sistemática de caminhos no kernel que ignoram as garantias de segurança do LSM
O portão nunca foi arrombado. Foi contornado.
O framework Linux Security Module tem uma garantia central que se mantém há mais de 20 anos:
Módulos de segurança só podem adicionar restrições. Eles nunca podem removê-las.
Esta garantia está correta. LID não a quebra.
LID encontra caminhos de código do kernel que ignoram completamente os hooks do LSM — subsistemas que realizam operações sensíveis à segurança sem consultar o framework LSM. A verificação de segurança está correta. O problema é que o kernel nunca pergunta.
Cada descoberta tem duas dimensões distintas que não devem ser confundidas:
O ponto cego arquitetônico. A pergunta não é "um atacante pode explorar isso?", mas sim:
Se uma operação sensível à segurança ocorre e a camada de aplicação nunca a avalia, você tem uma lacuna de visibilidade — independentemente de um atacante poder abusar dela na prática hoje. Isso importa para conformidade, perícia forense e pressupostos de defesa em profundidade.
A questão real de explorabilidade:
Essas duas coisas são diferentes. Uma descoberta pode ser uma lacuna de visibilidade crítica (seu monitoramento está cego) sem ser um escalonamento de privilégio prático (atacante já precisa de root). Por outro lado, uma descoberta pode ser um caminho direto de escalonamento com pré-requisitos mínimos.
| Descoberta | Lacuna de Visibilidade | Escalonamento Prático |
|---|---|---|
| LID-001 | Crítica — AppArmor não vê nada, log de auditoria vazio, zero vestígio forense | Limitado — requer root ou CAP_BPF+CAP_PERFMON (já privilegiado). Não é um escalonamento de privilégio. Impacto: evasão de política + cegueira de auditoria. |
| LID-002 | Alta — security_file_receive() nunca dispara, transferência de fd invisível para todos os LSMs | Alta — funciona a partir de userspace não privilegiado via io_uring. Cruza o limite de aplicação do LSM sem qualquer privilégio. |
| LID-003 | Alta — security_sb_mount() ignorado, política de montagem do AppArmor é código morto | Média — requer acesso ao namespace de montagem (CAP_SYS_ADMIN em user ns). Disponível em muitas configurações de contêiner. |
| LID-004 | Crítica — AppArmor não vê nada, zero hooks BPF (0/9), nenhum rastro de auditoria para qualquer operação de token BPF | Média — requer delegação de bpffs pelo host + CAP_BPF em user namespace. Disponível em runtimes de contêiner com delegação BPF (LXD/Incus). |
| LID-005 | Média — classificadores tc de egress em interface de contêiner nunca avaliam tráfego AF_XDP | Limitado — ignora tc egress na eth0 do contêiner (verificado). Cilium NÃO é ignorado — aplica no ingresso veth do lado do nó + verificação de IP de origem (testado). Impacto limitado a configurações Docker simples com filtragem egress apenas tc. |
Cada descoberta tem requisitos específicos de kernel/config/ privilégio. Se seu ambiente não corresponder, a descoberta não será reproduzida.
| Condição | Obrigatório | Observações |
|---|---|---|
| Versão do kernel | 5.x+ | Testado em 5.15, 6.1, 6.6, 6.8 |
CONFIG_BPF_SYSCALL | =y | Padrão em todas as principais distros |
CONFIG_BPF_KPROBE_OVERRIDE | =y | Ubuntu/Debian habilitam, RHEL não |
CONFIG_SECURITY_APPARMOR | =y | LSM alvo deve ser AppArmor |
| Perfil AppArmor | Em enforcing, regra de negação no caminho alvo | Funciona com qualquer regra de negação baseada em caminho |
| Privilégios | root ou CAP_BPF + CAP_PERFMON | Não pode ser executado sem privilégio |
kernel.lockdown | none ou integrity | Modo confidentiality bloqueia anexação de kprobe |
kernel.unprivileged_bpf_disabled | Irrelevante | Requer CAP_BPF independentemente |
fs.protected_hardlinks | 0 para links entre usuários | 1 (padrão) ainda permite hard links do mesmo usuário |
| SELinux em vez de AppArmor | Não funciona | SELinux é baseado em inode, não em caminho |
| Condição | Obrigatório | Observações |
|---|---|---|
| Versão do kernel | 6.0+ | IORING_MSG_SEND_FD adicionado em 6.0 |
CONFIG_IO_URING | =y | Padrão em todas as principais distros |
| Privilégios | Nenhum | Funciona a partir de userspace não privilegiado |
sysctl io_uring_disabled | 0 (padrão) | 2 bloqueia não privilegiado, 1 bloqueia todos |
| LSM alvo | Qualquer (SELinux, AppArmor, Smack) | security_file_receive() é um hook LSM genérico |
kernel.lockdown | Irrelevante | Nenhum BPF envolvido |
| Condição | Obrigatório | Observações |
|---|---|---|
| Versão do kernel | 6.9+ | Token BPF introduzido em 6.9 |
CONFIG_BPF_SYSCALL | =y | Padrão em todas as principais distros |
CONFIG_SECURITY_APPARMOR | =y | Padrão Ubuntu/Debian |
| bpffs com delegação | Sim | Host deve montar com opções delegate_* |
| Privilégios | CAP_BPF em user namespace | Trivialmente disponível para root de userns |
| SELinux em vez de AppArmor | Não afetado | SELinux implementa todos os 9 hooks BPF |
| Condição | Obrigatório | Observações |
|---|---|---|
| Versão do kernel | 5.2+ | fsopen/fsmount introduzidos em 5.2 |
CONFIG_SECURITY_APPARMOR | =y | Apenas AppArmor é afetado |
| Privilégios | CAP_SYS_ADMIN em user namespace | Disponível com unshare -m |
| SELinux em vez de AppArmor | Não funciona | SELinux implementa security_sb_kern_mount() |
| Runtime de contêiner | Depende do filtro seccomp | Seccomp padrão do Docker bloqueia fsopen — Podman/LXC podem não bloquear |
| Condição | Obrigatório | Observações |
|---|---|---|
| Versão do kernel | 4.18+ | AF_XDP introduzido em 4.18 |
CONFIG_XDP_SOCKETS | =y | Padrão em todas as principais distros |
| Privilégios | Apenas CAP_NET_RAW | Padrão em Docker, pods Kubernetes |
| Runtime de contêiner | Docker, K8s, LXC | Conjunto de capacidades padrão |
| Política de rede baseada em tc | Sim | Cilium eBPF, Calico, tc u32/flower |