L'eBPF (extended Berkeley Packet Filter) s'est imposé comme l'une des technologies les plus puissantes du noyau Linux — et, entre les mains d'acteurs offensifs, comme l'un des vecteurs d'attaque les plus redoutables. Conçu pour exécuter des programmes sandboxés dans le kernel avec des performances proches du natif, eBPF offre une visibilité et une capacité de manipulation inédites sur le trafic réseau, les appels système et les événements du noyau. Ces mêmes primitives — kprobes, tracepoints, filtres XDP — permettent de masquer des processus, d'intercepter des identifiants ou de détourner des connexions sans charger le moindre module noyau classique. La thématique ebpf offensif rootkit kernel concentre aujourd'hui l'attention des équipes de sécurité : les implants basés sur eBPF échappent aux contrôles traditionnels tout en restant partiellement détectables. Cet article détaille leurs techniques, leurs limites et les stratégies de détection kernel-level applicables en production.

En bref

  • eBPF permet des rootkits kernel-level sans module kernel — plus portables et plus furtifs que les LKM
  • Les rootkits eBPF dissimulent processus, fichiers, connexions réseau et interceptent les credentials
  • Les EDR basés sur eBPF peuvent être contournés par des programmes eBPF à priorité plus élevée
  • Le vérificateur eBPF a un historique de vulnérabilités permettant l'accès kernel arbitraire
  • La détection passe par l'audit de bpf() syscall, l'inspection des programmes et maps, et le monitoring continu

En bref

  • Architecture eBPF : programmes, maps, vérificateur, helpers et hooks
  • Rootkits eBPF : dissimulation de processus, fichiers, connexions réseau et users
  • Évasion EDR : manipulation des événements de télémétrie via eBPF
  • Vulnérabilités du vérificateur : bypass des bornes, type confusion, speculative attacks
  • Détection : audit des programmes eBPF chargés, signatures et monitoring
eBPF (extended Berkeley Packet Filter) — Technologie du noyau Linux permettant d'exécuter des programmes sandboxés dans le kernel sans modifier le code source ni charger de modules. Les programmes eBPF sont vérifiés statiquement avant exécution pour garantir la terminaison et la sûreté mémoire, mais des vulnérabilités dans le vérificateur permettent parfois le bypass de ces garanties.

Architecture eBPF : Vue d'Ensemble

eBPF est une machine virtuelle dans le kernel Linux qui exécute un bytecode vérifié. Les programmes eBPF sont attachés à des hooks (points d'attachement) dans le kernel — syscalls, tracepoints, kprobes, uprobes, XDP (réseau), LSM (sécurité). Ils utilisent des maps (structures de données partagées) pour communiquer entre eux et avec l'espace utilisateur.

ComposantRôleUsage offensif
ProgrammesBytecode eBPF exécuté dans le kernelInterception et modification de données
MapsStockage clé-valeur partagéConfiguration du rootkit, exfiltration
VérificateurAnalyse statique pré-exécutionCible de bypass pour accès kernel arbitraire
HelpersFonctions kernel accessibles depuis eBPFbpf_probe_read_kernel, bpf_override_return
Hooks (kprobes)Points d'attachement dynamiquesInterception de n'importe quelle fonction kernel

Rootkits eBPF : Principes et Architecture

Un rootkit eBPF exploite les capacités légitimes d'eBPF pour dissimuler la présence d'un attaquant. Contrairement aux rootkits kernel classiques (LKM — Loadable Kernel Module), les rootkits eBPF :

Retour terrain

Dans mes missions de red team, la phase de post-exploitation révèle systématiquement des données que le client pensait protégées. Le cas le plus fréquent : des fichiers Excel de comptabilité ou RH stockés sur des partages réseau accessibles à tous les utilisateurs du domaine, sans restriction. Sur les 30 dernières missions, 27 avaient des partages réseau avec des données sensibles accessibles à n'importe quel utilisateur authentifié. La sensibilité des données n'est pas corrélée à leur niveau de protection réel.

  • Ne nécessitent pas de compiler un module kernel — pas de dépendance aux headers kernel
  • Sont portables entre les versions de kernel (grâce au BTF — BPF Type Format)
  • Ne déclenchent pas les alertes de module loading (pas de insmod)
  • Sont plus difficiles à détecter car eBPF est un composant légitime et largement utilisé
  • Peuvent être déployés par un processus avec CAP_BPF + CAP_PERFMON (pas nécessairement root sur les kernels récents)

Dissimulation de Processus via eBPF

La technique consiste à intercepter les appels système getdents64() (utilisé par ls, ps, find) via un programme eBPF de type tracepoint ou fentry. Le programme modifie le buffer de retour pour supprimer les entrées correspondant aux processus à dissimuler :

// Programme eBPF de dissimulation de processus (simplifié)
SEC("tp/syscalls/sys_exit_getdents64")
int handle_getdents_exit(struct trace_event_raw_sys_exit *ctx) {
 // Lire le buffer de retour du syscall getdents64
 struct linux_dirent64 *dirp;
 long ret = ctx->ret;
 
 // Parcourir les entrées du répertoire (/proc/PID)
 // Si le nom correspond au PID à cacher :
 // → Décaler les entrées suivantes pour "supprimer" l'entrée
 // → Décrémenter ret (nombre d'octets retournés)
 
 // Le processus n'apparaît plus dans ps, top, /proc
 return 0;
}

// Programme de dissimulation de fichiers
SEC("tp/syscalls/sys_exit_getdents64")
int hide_files(struct trace_event_raw_sys_exit *ctx) {
 // Même technique pour cacher des fichiers dans un répertoire
 // Filtrer par nom de fichier (e.g., ".backdoor", "rootkit.so")
 return 0;
}

Dissimulation de Connexions Réseau

Les connexions réseau du rootkit (C2, reverse shell) sont dissimulées en interceptant la lecture de /proc/net/tcp et /proc/net/tcp6. Un programme eBPF de type fentry attaché à tcp4_seq_show supprime les lignes correspondant aux connexions à cacher. Le résultat : netstat, ss, et lsof ne montrent pas les connexions du rootkit.

Interception de Credentials via eBPF

// Keylogger eBPF via interception de read() sur /dev/tty
SEC("tp/syscalls/sys_exit_read")
int sniff_tty_read(struct trace_event_raw_sys_exit *ctx) {
 // Si le FD correspond à un terminal (stdin, /dev/tty)
 // Lire le buffer de retour (les caractères saisis)
 // Envoyer vers une map perf_event pour exfiltration
 
 char buf[256];
 bpf_probe_read_user(buf, sizeof(buf), (void *)ctx->ret);
 bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, buf, sizeof(buf));
 return 0;
}

// Interception de sudo/su pour capturer les mots de passe
SEC("uprobe//usr/bin/sudo")
int sniff_sudo(struct pt_regs *ctx) {
 // Lire les arguments de la ligne de commande
 // Capturer la saisie du mot de passe via PAM hooks
 return 0;
}

Évasion EDR via eBPF

Les EDR modernes (CrowdStrike Falcon, SentinelOne, Elastic) utilisent eux-mêmes eBPF pour la télémétrie de sécurité. Un rootkit eBPF peut contourner ces EDR en :

  • Patching des programmes eBPF de l'EDR : détacher ou remplacer les programmes eBPF de l'EDR par des versions modifiées qui filtrent les événements malveillants
  • Manipulation des événements en amont : les programmes eBPF s'exécutent en chaîne — un programme attaché avec une priorité plus élevée peut modifier les données avant que l'EDR ne les voie
  • Blocking des perf events : empêcher la transmission des événements de télémétrie à l'agent EDR en espace utilisateur
  • bpf_override_return() : sur les kernels avec CONFIG_BPF_KPROBE_OVERRIDE, cette helper permet de modifier la valeur de retour d'une fonction kernel — un attaquant peut faire échouer silencieusement les checks de sécurité

Vulnérabilités du Vérificateur eBPF

Le vérificateur eBPF est la première ligne de défense : il analyse statiquement chaque programme avant exécution pour garantir la terminaison, la sûreté mémoire et le respect des contraintes. Mais le vérificateur est un logiciel complexe (~20 000 lignes de C) avec un historique de vulnérabilités :

CVETypeImpactKernel
CVE-2021-3490Bounds tracking (ALU32)OOB R/W kernel5.7-5.12
CVE-2023-2163Verifier bypass (branch pruning)Arbitrary R/W5.4-6.3
CVE-2022-23222Type confusion (PTR_TO_MEM)LPE5.8-5.16
CVE-2021-34866Ringbuf boundsOOB access5.8-5.14

Détection des Rootkits eBPF

La détection des programmes eBPF malveillants est un défi car eBPF est une technologie légitime. Les approches de détection :

  • Audit des programmes chargés : bpftool prog list affiche tous les programmes eBPF actifs. Un rootkit qui n'apparaît pas dans cette liste est suspect (dissimulation de la commande bpf()).
  • Monitoring de bpf() syscall : surveiller les appels à bpf(BPF_PROG_LOAD) avec les arguments (type de programme, hooks ciblés) via auditd ou un programme eBPF de surveillance.
  • Analyse des maps eBPF : les maps contiennent les données du rootkit (PIDs à cacher, ports à filtrer). L'inspection des maps peut révéler une activité malveillante.
  • Intégrité du kernel : comparer les hooks eBPF actifs avec une baseline connue. Un programme attaché à tcp4_seq_show ou getdents64 est suspect.
⚠️ Attention — Les rootkits eBPF sont particulièrement dangereux car ils opèrent au niveau kernel avec les privilèges les plus élevés, tout en utilisant une technologie légitime qui est de plus en plus déployée pour la sécurité elle-même. La frontière entre usage légitime et malveillant d'eBPF est extrêmement fine.
💡 Conseil pratique — Pour vous protéger contre les rootkits eBPF, restreignez l'accès au syscall bpf() via seccomp, désactivez unprivileged_bpf_disabled (sysctl kernel.unprivileged_bpf_disabled=1), et surveillez les programmes eBPF chargés via bpftool et les audit logs.

À retenir

  • eBPF permet des rootkits kernel-level sans module kernel — plus portables et plus furtifs que les LKM
  • Les rootkits eBPF dissimulent processus, fichiers, connexions réseau et interceptent les credentials
  • Les EDR basés sur eBPF peuvent être contournés par des programmes eBPF à priorité plus élevée
  • Le vérificateur eBPF a un historique de vulnérabilités permettant l'accès kernel arbitraire
  • La détection passe par l'audit de bpf() syscall, l'inspection des programmes et maps, et le monitoring continu

🔗 Références externes