Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
Herramientas/GitHubGitHub/azqzazq1/lid
Escalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónEvasión de IDS/IPSPruebas de PenetraciónAnálisis de BinariosPapers e InvestigaciónAprendizaje y EducaciónRed Teaming
GitHubazqzazq1/lid

LID

LID — Linux Integrity Drift: Evadiendo AppArmor mediante la reescritura de rutas con eBPF. Manipulación de argumentos de syscalls previa a LSM con cero huella de auditoría. "Linux está muriendo"

201hace 2 mesesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
Ver Repositorio


``` ██╗ ██╗██████╗ ██║ ██║██╔══██╗ ██║ ██║██║ ██║ ██║ ██║██║ ██║ ███████╗██║██████╔╝ ╚══════╝╚═╝╚═════╝ ```

Linux Integrity Drift

— "Linux está muriendo" —


Descubrimiento sistemático de rutas de código del kernel que omiten las garantías de seguridad de LSM
La puerta nunca fue derribada. Simplemente la rodearon.



¿Qué es LID?

El framework de módulos de seguridad de Linux tiene una garantía central que se ha mantenido durante más de 20 años:

Los módulos de seguridad solo pueden añadir restricciones. Nunca pueden eliminarlas.

Esta garantía es correcta. LID no la rompe.

LID encuentra rutas de código del kernel que omiten por completo los hooks de LSM — subsistemas que realizan operaciones sensibles para la seguridad sin consultar el framework LSM. La comprobación de seguridad es correcta. El problema es que el kernel nunca pregunta.


Entendiendo qué es LID (y qué no es)

Cada hallazgo tiene dos dimensiones distintas que no deben confundirse:

A) Brecha de visibilidad de la política

El punto ciego arquitectónico. La pregunta no es "¿puede un atacante explotar esto?", sino:

  • ¿Qué ve realmente AppArmor/SELinux?
  • ¿Qué registra el log de auditoría?
  • ¿Qué observa tu SIEM/EDR?
  • ¿Qué cree el motor de políticas que sucedió?

Si se produce una operación sensible para la seguridad y la capa de aplicación de políticas ni siquiera la evalúa, tienes una brecha de visibilidad — independientemente de si un atacante puede abusar de ella en la práctica hoy. Esto importa para cumplimiento, forense digital y supuestos de defensa en profundidad.

B) Ruta práctica de escalada

La pregunta de explotabilidad en el mundo real:

  • ¿Cruza un límite de privilegios?
  • ¿El atacante necesita tener root/CAP_BPF para activarlo?
  • ¿Se requiere una cadena de explotación o es independiente?
  • ¿Cuál es el impacto real — acceso a datos, escalada de privilegios, evasión de políticas?

Estas dos cosas son diferentes. Un hallazgo puede ser una brecha de visibilidad crítica (tu monitoreo está ciego) sin ser una escalada de privilegios práctica (el atacante ya necesita root). A la inversa, un hallazgo puede ser una ruta de escalada directa con requisitos previos mínimos.


Matriz de reproducibilidad

Cada hallazgo tiene requisitos específicos de kernel/config/privilegios. Si tu entorno no coincide, el hallazgo no se reproducirá.

LID-001: Reescritura de pathname en eBPF

LID-002: io_uring MSG_RING

LID-004: Ceguera de AppArmor ante BPF Token

LID-003: Nueva API de montaje

LID-005: Bypass de egress tc de AF_XDP

Referencia rápida: qué bloquea cada hallazgo


Hallazgos


El patrón

Cada hallazgo sigue el mismo patrón:``` ┌─────────────────────────────────────────────────────────────┐ │ THE LID PATTERN │ │ │ │ Kernel Subsystem A LSM Framework │ │ (eBPF / io_uring / mount API) (AppArmor / SELinux) │ │ │ │ ┌───────────────────┐ │ │ │ Performs operation │──── should call ──── security_*() │ │ │ or manipulates │ but │ │ │ security input │ DOESN'T ██ │ │ └───────────────────┘ │ │ │ │ The LSM framework is correct. │ │ The kernel just doesn't always use it. │ └─────────────────────────────────────────────────────────────┘

root@kitploit:~
Dos subsistemas del kernel. Supuestos de confianza incompatibles. Una brecha.

<br>

---

## LID-001: Reescritura de Nombres de Ruta eBPF

**El hallazgo principal.** Un kprobe de BPF en `do_sys_openat2` reescribe el nombre de archivo en la memoria de usuario antes de que el kernel lo copie. AppArmor comprueba la ruta reescrita, concede el acceso. Cero rastro de auditoría.```
  process: open("/tmp/secret.txt")
       │
       ▼
  do_sys_openat2()
       │
    ★ LID kprobe fires here
    │  bpf_probe_write_user()
    │  rewrites "/tmp/secret.txt" → "/tmp/.bypass_link"
       │
       ▼
  getname_flags()          ← kernel copies the (rewritten) path
       │
       ▼
  security_file_open()     ← LSM hooks check "/tmp/.bypass_link"
       │                      AppArmor: ALLOW ✓
       ▼
  VFS opens inode          ← same file content (hard link)
       │
       ▼
  return fd to process     ← success, zero audit trace

Inicio rápido```bash

sudo ./scripts/check_prerequisites.sh sudo ./scripts/setup_env.sh make sudo ./scripts/setup_demo.sh sudo ./scripts/run_demo.sh

root@kitploit:~
### Salida de demostración```
╔══════════════════════════════════════════════════════════╗
║  Phase 1: AppArmor ENFORCING — access should be DENIED   ║
╚══════════════════════════════════════════════════════════╝

  $ /tmp/test_reader
  [-] DENIED: open() failed: Permission denied (errno=13)

╔══════════════════════════════════════════════════════════╗
║  Phase 2: Loading LID — BPF kprobe pathname rewrite       ║
╚══════════════════════════════════════════════════════════╝

  [*] BPF kprobe attached to do_sys_openat2

╔══════════════════════════════════════════════════════════╗
║  Phase 3: With LID active — access should be GRANTED      ║
╚══════════════════════════════════════════════════════════╝

  $ /tmp/test_reader
  [+] SUCCESS: Read 44 bytes: SECRET_DATA=this_is_protected_content_12345

╔══════════════════════════════════════════════════════════╗
║  Phase 4: Stealth check — audit log inspection             ║
╚══════════════════════════════════════════════════════════╝

  $ dmesg | grep apparmor | grep DENIED
  (empty — no denial was ever generated)


LID-002: io_uring MSG_RING: falta el hook de LSM

IORING_OP_MSG_RING con IORING_MSG_SEND_FD transfiere descriptores de archivo entre anillos io_uring sin llamar a security_file_receive(). Todos los demás mecanismos de transferencia de fd lo llaman:``` MSG_RING SEND_FD: __io_fixed_fd_install() ← NO security_file_receive() FIXED_FD_INSTALL: receive_fd() ← security_file_receive() ✓ SCM_RIGHTS: receive_fd() ← security_file_receive() ✓ binder: security_binder_transfer_file() ✓

root@kitploit:~
**Ubicación del bug:** `io_uring/msg_ring.c`, `io_msg_install_complete()` — llama directamente a `__io_fixed_fd_install()`, omitiendo el hook de LSM.

**Verificado con ftrace:** `security_file_receive` se dispara para SCM_RIGHTS pero no para MSG_RING.

**Afectado:** Linux 5.18+ hasta v7.1-rc3 (sin corregir a fecha de 2026-05-17).

**PoC:** [`findings/lid-002-iouring-msgring/msg_ring_bypass.c`](https://github.com/azqzazq1/lid/blob/HEAD/findings/lid-002-iouring-msgring/)

<br>

---

## LID-003: La nueva API de montaje omite AppArmor

La nueva API de montaje (`fsopen` + `fsconfig` + `fsmount` + `move_mount`) **nunca llama a `security_sb_mount()`** — el único hook de montaje que AppArmor implementa.```
  OLD API:  mount("proc", "/mnt", "proc", 0, NULL)
            → security_sb_mount()  → AppArmor: DENY ✗

  NEW API:  fsopen("proc") → fsconfig(CMD_CREATE) → fsmount() → move_mount()
            → security_sb_kern_mount()  → AppArmor: (not implemented) → ALLOW ✓

AppArmor registra 4 ganchos de mount. SELinux registra 14. La nueva API de mount utiliza ganchos que solo SELinux implementa.

Brechas adicionales encontradas:

  • open_tree(OPEN_TREE_CLONE): Cero ganchos de seguridad — evade la política de bind-mount
  • mount_setattr(): No existe ningún gancho LSM en el kernel en absoluto
  • move_mount() con montajes desconectados: AppArmor ve una ruta de origen NULL

Detalles: findings/lid-003-mount-api/



LID-004: Token BPF — Cero Cobertura de AppArmor

El subsistema de token BPF (Linux 6.9+) delega capacidades BPF a procesos sin privilegios en namespaces de usuario. El kernel define 9 ganchos LSM de BPF. SELinux implementa los 9 con una aplicación real de avc_has_perm(). AppArmor implementa cero.``` Kernel defines 9 BPF LSM hooks: ┌─────────────────────────────────────────────────────────────────┐ │ bpf, bpf_map, bpf_prog, bpf_map_create, bpf_prog_load, │ │ bpf_token_create, bpf_token_free, bpf_token_cmd, │ │ bpf_token_capable │ └─────────────────────────────────────────────────────────────────┘

SELinux: ████████████████████████████ 9/9 implemented AppArmor: 0/9 implemented Smack: 0/9 implemented

root@kitploit:~
On Ubuntu/Debian, un contenedor con delegación de bpffs puede:
- Crear tokens BPF → AppArmor no ve nada
- Usar tokens para cargar programas de tracing → AppArmor no ve nada
- Delegar CAP_PERFMON → deshabilitar mitigaciones de Spectre → AppArmor no ve nada

**Detalles:** [`findings/lid-004-bpf-token/`](https://github.com/azqzazq1/lid/blob/HEAD/findings/lid-004-bpf-token/)

<br>

---

## LID-005: Bypass de egress tc de AF_XDP desde el contenedor Docker predeterminado

La ruta de transmisión en modo copia de AF_XDP (`xsk_generic_xmit` → `__dev_direct_xmit`) **omite los clasificadores de egress tc** en la interfaz del contenedor. Verificado con tc u32 DROP-ALL — AF_PACKET bloqueado, AF_XDP pasa.

**Sin embargo:** Probado con Cilium v1.19 (kind cluster, NetworkPolicy de egress deny-all) — **Cilium NO fue omitido.** Cilium aplica enforcement en el ingress del peer veth del lado del nodo (`cil_from_container` vía tcx/ingress) + tiene verificación de IP de origen. Los paquetes AF_XDP se descartaron como "Invalid source ip" en `bpf_lxc.c:1603`. El impacto se limita a entornos que dependen únicamente de clasificadores de egress tc para la política de red (Docker simple + reglas tc, sin CNI).```
  Normal TX path:
  socket → dev_queue_xmit() → sch_handle_egress() → tc classifiers → driver
                                     ↑
                                  ENFORCED (Cilium eBPF, Calico, tc u32)

  AF_XDP copy-mode TX:
  xsk_sendmsg() → xsk_generic_xmit() → __dev_direct_xmit() → driver
                                              ↑
                                           SKIPPED (tc never runs)

Verificado dinámicamente en el kernel 6.8.0 con los contenedores predeterminados de Docker:``` tc egress DROP-ALL on container eth0:

AF_PACKET sendto → ENOBUFS (BLOCKED by tc) AF_XDP sendto → 0 (BYPASS — 3 spoofed packets reached docker0 bridge)

root@kitploit:~
Packets carry attacker-controlled Ethernet headers — spoofed MAC, spoofed IP — and reach the Docker bridge despite active DROP policy.

**PoC + detalles:** [`findings/lid-005-afxdp-tc-bypass/`](https://github.com/azqzazq1/lid/blob/HEAD/findings/lid-005-afxdp-tc-bypass/)

<br>

---

## Arquitectura: Por qué BPF LSM no puede arreglar esto```
  LSM Hook Chain: call_int_hook(file_open, ...)

  ┌─────────────┐   ┌─────────────┐   ┌─────────────┐   ┌─────────────┐
  │  Lockdown    │──>│  Capability  │──>│   AppArmor   │──>│  BPF LSM    │
  │  return 0    │   │  return 0    │   │  return -13  │   │  (never     │
  │  (allow)     │   │  (allow)     │   │  (DENY) ██   │   │   reached)  │
  └─────────────┘   └─────────────┘   └──────┬───────┘   └─────────────┘
                                              │
                                         loop breaks
                                         RC = -EACCES

  ★ The LSM framework is correct. No module can undo another's denial.
  ★ LID operates OUTSIDE the framework — before hooks run, or where hooks don't exist.

Compañero: SunnyDayBPF```

root@kitploit:~
               ┌───────────────────────────────────────┐
               │          THE ATTACK TIMELINE           │
               │                                       │

Syscall Entry │ ★ LID ─── manipulates input │ │ │ (security check sees wrong data) │ ▼ │ │ LSM Check │ LSM allows (or never runs) ✓ │ │ │ │ ▼ │ │ Syscall Exit │ ★ SunnyDayBPF ─── rewrites telemetry │ │ │ (monitoring sees wrong data) │ ▼ │ │ Audit/Log │ SIEM sees nothing ✓ │ │ │ │ Combined: ghost access │ └───────────────────────────────────────┘

root@kitploit:~
<br>

## Estructura del Proyecto```
LID/
├── src/
│   ├── bpf/
│   │   └── lid.bpf.c              # BPF kprobe — pathname rewriter (LID-001)
│   └── loader/
│       └── lid_loader.c           # Userspace loader + event monitor
├── findings/
│   ├── lid-001-ebpf-pathname/     # eBPF pathname rewriting bypass
│   ├── lid-002-iouring-msgring/   # io_uring MSG_RING missing LSM hook
│   │   ├── msg_ring_bypass.c      # PoC with ftrace verification
│   │   └── ADVISORY.md            # Technical advisory
│   ├── lid-003-mount-api/         # New mount API AppArmor bypass
│   ├── lid-004-bpf-token/        # BPF token AppArmor/Smack zero coverage
│   └── lid-005-afxdp-tc-bypass/  # AF_XDP tc egress bypass from container
├── tests/
│   └── test_reader.c              # Victim binary for LID-001 demo
├── scripts/
│   ├── check_prerequisites.sh     # Verify system requirements
│   ├── setup_env.sh               # Install build dependencies
│   ├── setup_demo.sh              # Create demo environment
│   ├── run_demo.sh                # Run full LID-001 demonstration
│   └── teardown.sh                # Clean up everything
├── docs/
│   └── RESEARCH.md                # Full technical research paper
├── publish/                       # Articles for Medium, dev.to, etc.
├── Makefile
├── LICENSE
├── SECURITY.md
└── README.md

Perfil de Stealth (LID-001)


Mitigaciones

Para obtener una guía de mitigación detallada, consulte docs/RESEARCH.md.


Requisitos

Consulte la Matriz de Reproducibilidad para obtener todos los detalles por hallazgo. Resumen:


Autor

Azizcan Daştan
Milenium Security

  • GitHub: @azqzazq1

Aviso legal

Esta herramienta se publica únicamente para pruebas de seguridad autorizadas, investigación y fines educativos. No la utilice contra sistemas que no posea o para los cuales no tenga permiso explícito por escrito para probar.


LID — porque la integridad nunca estuvo bloqueada.

Descargar herramienta
HallazgoBrecha de visibilidadEscalada práctica
LID-001Crítica — AppArmor no ve nada, log de auditoría vacío, cero rastro forenseLimitada — requiere root o CAP_BPF+CAP_PERFMON (ya privilegiado). No es una escalada de privilegios. Impacto: evasión de políticas + ceguera de auditoría.
LID-002Alta — security_file_receive() nunca se dispara, la transferencia de fd invisible para todos los LSMAlta — funciona desde el espacio de usuario sin privilegios mediante io_uring. Cruza el límite de aplicación de LSM sin ningún privilegio.
LID-003Alta — security_sb_mount() evadido, la política de montaje de AppArmor es código muertoMedia — requiere acceso al espacio de nombres de montaje (CAP_SYS_ADMIN en user ns). Disponible en muchas configuraciones de contenedores.
LID-004Crítica — AppArmor no ve nada, cero hooks BPF (0/9), sin rastro de auditoría para ninguna operación de token BPFMedia — requiere delegación de bpffs por parte del host + CAP_BPF en el espacio de nombres de usuario. Disponible en runtimes de contenedores con delegación BPF (LXD/Incus).
LID-005Media — los clasificadores de egress tc en la interfaz del contenedor nunca evalúan el tráfico AF_XDPLimitada — evita el egress tc en eth0 del contenedor (verificado). Cilium NO es evadido — aplica control en el ingress veth del lado del nodo + verificación de IP de origen (probado). Impacto limitado a configuraciones de Docker simple con filtrado de egress solo con tc.
CondiciónRequeridoNotas
Versión del kernel5.x+Probado en 5.15, 6.1, 6.6, 6.8
CONFIG_BPF_SYSCALL=yPredeterminado en todas las distros principales
CONFIG_BPF_KPROBE_OVERRIDE=yUbuntu/Debian lo habilitan, RHEL no
CONFIG_SECURITY_APPARMOR=yEl LSM objetivo debe ser AppArmor
Perfil de AppArmorEnforcing, regla de denegación en la ruta objetivoFunciona con cualquier regla de denegación basada en rutas
Privilegiosroot o CAP_BPF + CAP_PERFMONNo puede ejecutarse sin privilegios
kernel.lockdownnone o integrityEl modo confidentiality impide adjuntar kprobes
kernel.unprivileged_bpf_disabledIrrelevanteRequiere CAP_BPF de todos modos
fs.protected_hardlinks0 para enlaces entre usuarios1 (predeterminado) todavía permite enlaces duros del mismo usuario
SELinux en lugar de AppArmorNo funcionaSELinux se basa en inodos, no en nombres de ruta
CondiciónRequeridoNotas
Versión del kernel6.0+IORING_MSG_SEND_FD añadido en 6.0
CONFIG_IO_URING=yPredeterminado en todas las distros principales
PrivilegiosNingunoFunciona desde el espacio de usuario sin privilegios
sysctl io_uring_disabled0 (predeterminado)2 bloquea a los no privilegiados, 1 bloquea a todos
LSM objetivoCualquiera (SELinux, AppArmor, Smack)security_file_receive() es un hook LSM genérico
kernel.lockdownIrrelevanteNo involucra BPF
CondiciónRequeridoNotas
Versión del kernel6.9+El token BPF se introdujo en 6.9
CONFIG_BPF_SYSCALL=yPredeterminado en todas las distros principales
CONFIG_SECURITY_APPARMOR=yPredeterminado en Ubuntu/Debian
bpffs con delegaciónSíEl host debe montar con opciones delegate_*
PrivilegiosCAP_BPF en el espacio de nombres de usuarioDisponible trivialmente para root de userns
SELinux en lugar de AppArmorNo afectadoSELinux implementa los 9 hooks BPF
CondiciónRequeridoNotas
Versión del kernel5.2+fsopen/fsmount introducidos en 5.2
CONFIG_SECURITY_APPARMOR=ySolo AppArmor se ve afectado
PrivilegiosCAP_SYS_ADMIN en el espacio de nombres de usuarioDisponible con unshare -m
SELinux en lugar de AppArmorNo funcionaSELinux implementa security_sb_kern_mount()
Runtime de contenedoresDepende del filtro seccompEl seccomp predeterminado de Docker bloquea fsopen — Podman/LXC puede que no
CondiciónRequeridoNotas
Versión del kernel4.18+AF_XDP introducido en 4.18
CONFIG_XDP_SOCKETS=yPredeterminado en todas las distros principales
PrivilegiosSolo CAP_NET_RAWPredeterminado en Docker, pods de Kubernetes
Runtime de contenedoresDocker, K8s, LXCConjunto de capacidades predeterminado
Política de red basada en tcSíCilium eBPF, Calico, tc u32/flower
EntornoLID-001LID-002LID-003LID-004LID-005
Ubuntu 22.04+ (AppArmor, predeterminado)FuncionaFuncionaFuncionaFunciona (6.9+)Funciona
Debian 12+ (AppArmor)FuncionaFuncionaFuncionaFunciona (6.9+)Funciona
RHEL/Fedora (SELinux)NoFuncionaNoNoFunciona
lockdown=confidentialityNoFuncionaFuncionaParcialmenteFunciona
Usuario sin privilegiosNoFuncionaDepende del user nsDepende de la delegación de bpffsNo
Contenedor (sin CAP_BPF)NoDepende de io_uringDepende de seccompNoFunciona
Contenedor (CAP_NET_RAW eliminado)NoDependeDependeNoNo
IDVectorObjetivoQué ocurre
LID-001Reescritura de pathname mediante eBPF kprobeAppArmorel kprobe reescribe el nombre de archivo antes de copy_from_user → AppArmor comprueba la ruta incorrecta
LID-002io_uring MSG_RING SEND_FDSELinux, AppArmor, Smackla transferencia de fd omite security_file_receive() — cualquier otra transferencia de fd lo llama
LID-003Nueva API de montaje (fsopen/fsmount)AppArmorsecurity_sb_mount() nunca se llama — el único hook de montaje de AppArmor es evadido
LID-004Delegación de token BPFAppArmor, SmackCero hooks BPF — creación, uso y delegación de capacidades del token completamente invisibles
LID-005AF_XDP __dev_direct_xmittc egress, Cilium, CalicoTX en modo copia desde Docker predeterminado evita los clasificadores tc — los paquetes suplantados llegan al bridge
IndicadorVisibilidadNotas
Registro de auditoría de AppArmorNadaLa denegación nunca ocurre
auditd / journaldNadaNo se genera ningún evento de seguridad
dmesgAviso únicoMensaje genérico de bpf_probe_write_user
bpftool prog listVisibleMuestra el kprobe adjunto (si se comprueba)
Enlace físico en discoDetectablefind -samefile (lento, ruidoso)
MitigaciónEfectividadCompromiso
kernel.lockdown=confidentialityBloquea BPF por completoElimina la monitorización legítima
Deshabilitar bpf_probe_write_userEvita la reescritura de rutas de LID-001Requiere recompilar el kernel
fs.protected_hardlinks=1Limita la creación de enlaces físicosActivado por defecto en kernels modernos
Monitorizar bpftool prog listDetecta sondas adjuntasRequiere sondeo activo
Migrar a SELinuxBasado en inodos, frustra la reescritura de rutasMigración compleja
Restringir io_uringBloquea LID-002Puede romper aplicaciones
HallazgoKernel mínimoPrivilegiosObjetivo
LID-0015.x+root / CAP_BPF+CAP_PERFMONSolo AppArmor
LID-0026.0+NingunoCualquiera (SELinux, AppArmor, Smack)
LID-0035.2+CAP_SYS_ADMIN (user ns ok)Solo AppArmor
LID-0046.9+CAP_BPF (user ns ok)AppArmor, Smack
LID-0054.18+CAP_NET_RAW (Docker por defecto)tc egress (Cilium, Calico, etc.)