Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
LID — LID — Linux Integrity Drift: Bypassing AppArmor via eBPF pathname rewriting. Pre-LSM syscall argument manipulation with zero audit footprint. "Linux is Dying" | Kitploit
Outils/GitHubGitHub/azqzazq1/lid
Privilege EscalationVulnerability AnalysisExploitationIDS/IPS EvasionPenetration TestingBinary AnalysisPapers & ResearchLearning & EducationRed Teaming
GitHubazqzazq1/lid

LID

LID — Linux Integrity Drift: Bypassing AppArmor via eBPF pathname rewriting. Pre-LSM syscall argument manipulation with zero audit footprint. "Linux is Dying"

201il y a 2 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager
Voir le dépôt


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

Dérive d'intégrité Linux

— « Linux est en train de mourir » —


Découverte systématique de chemins de code du noyau qui contournent les garanties de sécurité des LSM
La porte n'a jamais été forcée. On l'a contournée.



Qu'est-ce que LID ?

Le framework des modules de sécurité Linux (LSM) repose sur une garantie centrale qui tient depuis plus de 20 ans :

Les modules de sécurité ne peuvent qu'ajouter des restrictions. Ils ne peuvent jamais les supprimer.

Cette garantie est correcte. LID ne la brise pas.

LID trouve des chemins de code du noyau qui contournent complètement les hooks LSM — des sous-systèmes effectuant des opérations sensibles pour la sécurité sans consulter le framework LSM. La vérification de sécurité est correcte. Le problème est que le noyau ne demande jamais.


Comprendre ce que LID est (et n'est pas)

Chaque découverte a deux dimensions distinctes qu'il ne faut pas confondre :

A) Écart de visibilité de la politique

Le point aveugle architectural. La question n'est pas « un attaquant peut-il exploiter cela ? » mais :

  • Que voit réellement AppArmor/SELinux ?
  • Que consigne le journal d'audit ?
  • Qu'observe votre SIEM/EDR ?
  • Que pense le moteur de politique qu'il s'est passé ?

Si une opération sensible pour la sécurité se produit et que la couche d'application ne l'évalue même pas, vous avez un écart de visibilité — indépendamment de la possibilité pratique pour un attaquant d'en abuser aujourd'hui. Cela compte pour la conformité, la criminalistique et les hypothèses de défense en profondeur.

B) Chemin d'escalade pratique

La question pratique de l'exploitabilité :

  • Cela franchit-il une limite de privilèges ?
  • Un attaquant a-t-il besoin d'un accès root / CAP_BPF existant pour le déclencher ?
  • Une chaîne d'exploitation est-elle nécessaire, ou est-ce autonome ?
  • Quel est l'impact réel — accès aux données, escalade de privilèges, contournement de politique ?

Ces deux choses sont différentes. Une découverte peut être un écart de visibilité critique (votre surveillance est aveugle) sans être une escalade de privilèges pratique (l'attaquant a déjà besoin de root). Inversement, une découverte peut être un chemin d'escalade direct avec des prérequis minimaux.


Matrice de reproductibilité

Chaque découverte a des exigences spécifiques de noyau/config/privlèges. Si votre environnement ne correspond pas, la découverte ne se reproduira pas.

LID-001 : Réécriture de chemin eBPF

LID-002 : io_uring MSG_RING

LID-004 : Cécité AppArmor pour les jetons BPF

LID-003 : Nouvelle API de montage

LID-005 : Contournement tc egress AF_XDP

Référence rapide : ce qui bloque chaque découverte


Découvertes


Le schéma

Chaque découverte suit le même schéma :``` ┌─────────────────────────────────────────────────────────────┐ │ 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:~
Deux sous-systèmes du noyau. Hypothèses de confiance incompatibles. Une faille.

<br>

---

## LID-001: Réécriture des chemins par eBPF

**La découverte phare.** Une kprobe BPF sur `do_sys_openat2` réécrit le nom de fichier dans la mémoire utilisateur avant que le noyau ne le copie. AppArmor vérifie le chemin réécrit et accorde l'accès. Aucune trace d'audit.```
  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

Démarrage rapide```bash

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

root@kitploit:~
### Sortie de démonstration```
╔══════════════════════════════════════════════════════════╗
║  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 – Crochet LSM manquant

IORING_OP_MSG_RING avec IORING_MSG_SEND_FD transfère des descripteurs de fichier entre des rings io_uring sans appeler security_file_receive(). Tous les autres mécanismes de transfert de fd l'appellent :``` 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:~
**Emplacement du bogue :** `io_uring/msg_ring.c`, `io_msg_install_complete()` — appelle directement `__io_fixed_fd_install()`, en contournant le hook LSM.

**Vérifié avec ftrace :** `security_file_receive` se déclenche pour SCM_RIGHTS mais pas pour MSG_RING.

**Affecté :** Linux 5.18+ jusqu'à v7.1-rc3 (non corrigé au 17/05/2026).

**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 nouvelle API de montage contourne AppArmor

La nouvelle API de montage (`fsopen` + `fsconfig` + `fsmount` + `move_mount`) **n'appelle jamais `security_sb_mount()`** — le seul hook de montage qu'AppArmor implémente.```
  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 enregistre 4 hooks de montage. SELinux enregistre 14. La nouvelle API de montage utilise des hooks que seul SELinux implémente.

Autres lacunes identifiées :

  • open_tree(OPEN_TREE_CLONE) : Zéro hook de sécurité — contourne la politique de bind-mount
  • mount_setattr() : Aucun hook LSM n'existe dans le noyau
  • move_mount() avec des montages détachés : AppArmor voit un chemin source NULL

Détails : findings/lid-003-mount-api/



LID-004: BPF Token — Couverture zéro d'AppArmor

Le sous-système de token BPF (Linux 6.9+) délègue les capacités BPF à des processus non privilégiés dans des espaces de noms utilisateur. Le noyau définit 9 hooks LSM BPF. SELinux implémente les 9 avec une véritable application de avc_has_perm(). AppArmor n'en implémente aucun.``` 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:~
Sur Ubuntu/Debian, un conteneur avec délégation bpffs peut :
- Créer des jetons BPF → AppArmor ne voit rien
- Utiliser des jetons pour charger des programmes de tracing → AppArmor ne voit rien
- Déléguer CAP_PERFMON → désactiver les atténuations Spectre → AppArmor ne voit rien

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

<br>

---

## LID-005 : Contournement de la sortie tc egress depuis un conteneur Docker par défaut via AF_XDP

Le chemin de transmission en mode copie d'AF_XDP (`xsk_generic_xmit` → `__dev_direct_xmit`) **contourne les classifieurs tc egress** sur l'interface du conteneur. Vérifié avec tc u32 DROP-ALL — AF_PACKET bloqué, AF_XDP passe.

**Cependant :** Testé avec Cilium v1.19 (cluster kind, NetworkPolicy egress deny-all) — **Cilium n'a PAS été contourné.** Cilium applique les règles sur le veth pair côté nœud en ingress (`cil_from_container` via tcx/ingress) + possède une vérification de l'adresse IP source. Les paquets AF_XDP ont été rejetés comme « Adresse source invalide » à `bpf_lxc.c:1603`. L'impact est limité aux environnements qui reposent uniquement sur des classifieurs tc egress pour la politique réseau (Docker simple + règles tc, pas de 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)

Vérifié dynamiquement sur le noyau 6.8.0 avec les conteneurs par défaut 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:~
Les paquets transportent des en-têtes Ethernet contrôlées par l'attaquant — MAC usurpée, IP usurpée — et atteignent le pont Docker malgré une politique DROP active.

**Preuve de concept + détails :** [`findings/lid-005-afxdp-tc-bypass/`](https://github.com/azqzazq1/lid/blob/HEAD/findings/lid-005-afxdp-tc-bypass/)

<br>

---

## Architecture: Pourquoi BPF LSM ne peut pas corriger cela```
  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.

Compagnon : 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>

## Structure du projet```
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

Profil Furtif (LID-001)


Atténuations

Pour des conseils d'atténuation détaillés, voir docs/RESEARCH.md.


Prérequis

Voir la Matrice de reproductibilité pour tous les détails par constatation. Résumé :


Auteur

Azizcan Daştan
Milenium Security

  • GitHub: @azqzazq1

Avertissement

Cet outil est publié uniquement à des fins autorisées de test de sécurité, de recherche et d'éducation. Ne l'utilisez pas contre des systèmes que vous ne possédez pas ou pour lesquels vous n'avez pas d'autorisation écrite explicite de test.


LID — parce que l'intégrité n'a jamais été verrouillée.

Télécharger l’outil
DécouverteÉcart de visibilitéEscalade pratique
LID-001Critique — AppArmor ne voit rien, journal d'audit vide, aucune trace forensiqueLimitée — nécessite root ou CAP_BPF+CAP_PERFMON (déjà privilégié). Pas d'escalade de privilèges. Impact : contournement de politique + cécité d'audit.
LID-002Élevé — security_file_receive() jamais déclenché, transfert de fd invisible pour tous les LSMÉlevé — fonctionne depuis un espace utilisateur non privilégié via io_uring. Franchit la limite d'application LSM sans aucun privilège.
LID-003Élevé — security_sb_mount() contourné, la politique de montage AppArmor est du code mortMoyen — nécessite un accès à l'espace de noms de montage (CAP_SYS_ADMIN dans user ns). Disponible dans de nombreuses configurations de conteneurs.
LID-004Critique — AppArmor ne voit rien, zéro hooks BPF (0/9), aucune trace d'audit pour toute opération de jeton BPFMoyen — nécessite une délégation bpffs par l'hôte + CAP_BPF dans l'espace de noms utilisateur. Disponible dans les environnements d'exécution de conteneurs avec délégation BPF (LXD/Incus).
LID-005Moyen — les classificateurs tc egress sur l'interface du conteneur n'évaluent jamais le trafic AF_XDPLimitée — contourne tc egress sur eth0 du conteneur (vérifié). Cilium PAS contourné — applique sur l'ingress veth côté nœud + vérification IP source (testé). Impact limité aux configurations Docker simples avec filtrage tc egress uniquement.
ConditionRequisNotes
Version du noyau5.x+Testé sur 5.15, 6.1, 6.6, 6.8
CONFIG_BPF_SYSCALL=yPar défaut sur toutes les distributions majeures
CONFIG_BPF_KPROBE_OVERRIDE=yUbuntu/Debian l'activent, RHEL non
CONFIG_SECURITY_APPARMOR=yLe LSM cible doit être AppArmor
Profil AppArmorEnforcing, règle de refus sur le chemin cibleFonctionne avec toute règle de refus basée sur le chemin
Privilègesroot ou CAP_BPF + CAP_PERFMONNe peut pas s'exécuter non privilégié
kernel.lockdownnone ou integrityLe mode confidentiality bloque l'attachement kprobe
kernel.unprivileged_bpf_disabledSans importanceNécessite CAP_BPF quoi qu'il arrive
fs.protected_hardlinks0 pour les liens inter-utilisateurs1 (par défaut) autorise encore les liens physiques du même utilisateur
SELinux au lieu d'AppArmorNe fonctionne pasSELinux est basé sur les inodes, pas sur les noms de chemin
ConditionRequisNotes
Version du noyau6.0+IORING_MSG_SEND_FD ajouté dans 6.0
CONFIG_IO_URING=yPar défaut sur toutes les distributions majeures
PrivilègesAucunFonctionne depuis un espace utilisateur non privilégié
sysctl io_uring_disabled0 (par défaut)2 bloque les non privilégiés, 1 bloque tout
LSM cibleTout (SELinux, AppArmor, Smack)security_file_receive() est un hook LSM générique
kernel.lockdownSans importanceAucun BPF impliqué
ConditionRequisNotes
Version du noyau6.9+Jeton BPF introduit dans 6.9
CONFIG_BPF_SYSCALL=yPar défaut sur toutes les distributions majeures
CONFIG_SECURITY_APPARMOR=yValeur par défaut Ubuntu/Debian
bpffs avec délégationOuiL'hôte doit monter avec les options delegate_*
PrivilègesCAP_BPF dans l'espace de noms utilisateurTrivialement accessible au root d'userns
SELinux au lieu d'AppArmorNon affectéSELinux implémente les 9 hooks BPF
ConditionRequisNotes
Version du noyau5.2+fsopen/fsmount introduits dans 5.2
CONFIG_SECURITY_APPARMOR=ySeul AppArmor est affecté
PrivilègesCAP_SYS_ADMIN dans l'espace de noms utilisateurDisponible avec unshare -m
SELinux au lieu d'AppArmorNe fonctionne pasSELinux implémente security_sb_kern_mount()
Environnement d'exécution de conteneurDépend du filtre seccompLe seccomp par défaut de Docker bloque fsopen — Podman/LXC peuvent ne pas le faire
ConditionRequisNotes
Version du noyau4.18+AF_XDP introduit dans 4.18
CONFIG_XDP_SOCKETS=yPar défaut sur toutes les distributions majeures
PrivilègesCAP_NET_RAW uniquementPar défaut dans Docker, pods Kubernetes
Environnement d'exécution de conteneurDocker, K8s, LXCEnsemble de capacités par défaut
Politique réseau basée sur tcOuiCilium eBPF, Calico, tc u32/flower
EnvironnementLID-001LID-002LID-003LID-004LID-005
Ubuntu 22.04+ (AppArmor, par défaut)FonctionneFonctionneFonctionneFonctionne (6.9+)Fonctionne
Debian 12+ (AppArmor)FonctionneFonctionneFonctionneFonctionne (6.9+)Fonctionne
RHEL/Fedora (SELinux)NonFonctionneNonNonFonctionne
lockdown=confidentialityNonFonctionneFonctionnePartiellementFonctionne
Utilisateur non privilégiéNonFonctionneDépend de user nsDépend de la délégation bpffsNon
Conteneur (sans CAP_BPF)NonDépend de io_uringDépend de seccompNonFonctionne
Conteneur (CAP_NET_RAW retiré)NonDépendDépendNonNon
IDVecteurCibleCe qui se passe
LID-001Réécriture de chemin par kprobe eBPFAppArmorLe kprobe réécrit le nom de fichier avant copy_from_user → AppArmor vérifie le mauvais chemin
LID-002io_uring MSG_RING SEND_FDSELinux, AppArmor, SmackLe transfert de fd ignore security_file_receive() — tous les autres transferts de fd l'appellent
LID-003Nouvelle API de montage (fsopen/fsmount)AppArmorsecurity_sb_mount() jamais appelé — le seul hook de montage d'AppArmor contourné
LID-004Délégation de jeton BPFAppArmor, SmackZéro hooks BPF — création de jeton, utilisation, délégation de capacité complètement invisibles
LID-005AF_XDP __dev_direct_xmittc egress, Cilium, CalicoLa TX en mode copie depuis Docker par défaut contourne les classificateurs tc — les paquets falsifiés atteignent le pont
IndicateurVisibilitéNotes
Journal d'audit AppArmorRienAucun refus ne se produit
auditd / journaldRienAucun événement de sécurité généré
dmesgAvertissement uniqueMessage générique bpf_probe_write_user
bpftool prog listVisibleAffiche le kprobe attaché (si vérifié)
Lien physique sur le disqueDétectablefind -samefile (lent, bruyant)
AtténuationEfficacitéCompromis
kernel.lockdown=confidentialityBloque complètement BPFTue la surveillance légitime
Désactiver bpf_probe_write_userEmpêche la réécriture de chemin LID-001Nécessite une reconstruction du noyau
fs.protected_hardlinks=1Limite la création de liens physiquesPar défaut sur les noyaux modernes
Surveiller bpftool prog listDétecte les sondes attachéesNécessite une interrogation active
Migrer vers SELinuxBasé sur les inodes, contrecarre la réécriture de cheminMigration complexe
Restreindre io_uringBloque LID-002Peut casser des applications
ConstatationNoyau minPrivilègesCible
LID-0015.x+root / CAP_BPF+CAP_PERFMONAppArmor uniquement
LID-0026.0+AucunTous (SELinux, AppArmor, Smack)
LID-0035.2+CAP_SYS_ADMIN (user ns ok)AppArmor uniquement
LID-0046.9+CAP_BPF (user ns ok)AppArmor, Smack
LID-0054.18+CAP_NET_RAW (par défaut Docker)tc egress (Cilium, Calico, etc.)