En quelques années, eBPF (Extended Berkeley Packet Filter) est devenu un des sous-systèmes les plus actifs du noyau Linux. Grâce à ses nombreuses promesses de sûreté de fonctionnement et d’observabilité, eBPF a beaucoup gagné en popularité auprès des outils de surveillance réseau et système. Malheureusement, cette nouvelle technologie a involontairement introduit un risque majeur pour Linux : une considérable simplification du développement des rootkits.
Depuis son introduction dans le noyau Linux (Linux 3.18), eBPF a beaucoup évolué, passant d’une technologie de surveillance réseau à un outil de traçage complet pour n’importe quel événement du noyau. Encore en actif développement aujourd’hui, eBPF commence également à faire son apparition dans des outils de sécurité à l’exécution, tirant parti de son impressionnante capacité d’observabilité pour remonter des alertes de sécurité de plus en plus complexes, et facilitant la réponse à incident grâce à son contexte applicatif. Malheureusement, cette étonnante capacité d’introspection du noyau Linux a également considérablement facilité l’implémentation des principales fonctionnalités d’un rootkit : de l’obfuscation de processus à l’injection et l’exfiltration réseau, de l’évasion d’outils de type RASP (Runtime application self-protection) à l’évasion de conteneurs. Dans cet article, nous évoquerons comment eBPF simplifie le développement de telles fonctionnalités, nous étudierons les deux premiers rootkits découverts (à date) utilisant ces techniques, et enfin, nous discuterons des différentes options pour nous en protéger.
1. eBPF : l’envers du décor
1.1 Introduction à eBPF
Extended Berkeley Packet Filter (eBPF) est un sous-système du noyau Linux permettant d’exécuter du code, dans une machine virtuelle, en espace noyau. L’une des principales motivations à l’introduction d’une telle fonctionnalité était de réduire considérablement l’impact à l’exécution d’une solution de surveillance réseau qui voudrait analyser le trafic entrant ou sortant d’une machine. En effet, filtrer des paquets réseaux en espace noyau permet d’éviter la multiplication des appels systèmes et des changements de contextes entre l'espace noyau et l'espace utilisateur. En réalité, cette affirmation s’applique également à n’importe quel événement système que l’on souhaiterait observer : un appel système, une allocation mémoire, une latence disque, etc. C’est ainsi qu’au fur et à mesure des années, eBPF a gagné en fonctionnalités et s’est progressivement imposé comme la solution la plus flexible en termes de capacité d’introspection du noyau.
D’un point de vue technique, l’utilisation d’eBPF se déroule en deux étapes :
- Le chargement d’un programme eBPF : cette étape est cruciale pour expliquer pourquoi eBPF est considéré comme sûr pour le noyau. En effet, quand un programme eBPF est chargé avec l’appel système « bpf », le noyau va exécuter une série de tests ayant pour objectif de s’assurer que le programme termine, qu’il ne peut pas provoquer une erreur de segmentation, qu’il alloue une quantité bornée de mémoire, etc. Toutes ces vérifications garantissent la stabilité de cette technologie, expliquant ainsi sa popularité par rapport à une interface telle qu’un module noyau.
- L’attachement d’un programme eBPF à son point d’ancrage : cette étape indique au noyau où et quand le programme eBPF devra être exécuté. Il existe de nombreux types de programmes eBPF, et chaque programme a sa propre spécificité. Nous allons parler de plusieurs types de programmes eBPF dans cet article, mais nous recommandons le livre « Linux Observability with BPF » [1] de David Calavera et Lorenzo Fontana pour une introduction plus approfondie à eBPF.
Le chargement et l’attachement d’un programme eBPF demande historiquement un accès privilégié, mais de nouvelles capacités noyaux (CAP_BPF et CAP_PERFMON [18]) ont récemment été ajoutées pour réduire l’accès donné aux services reposant sur eBPF.
Pour faciliter le développement d’un programme eBPF (et parfois pour simplifier l’accès au contexte d’exécution d’un programme), le noyau autorise l’appel à certaines fonctions « en dehors » des instructions chargées par le programme. Ces fonctions seront appelées « eBPF helpers » dans la suite de l’article pour simplifier leur appellation. Il existe de nombreux « helpers » et ils ne sont pas accessibles à tous les types de programmes eBPF. Dans la majorité des cas, ces fonctions ne donnent accès à des données qu’en lecture seule. Mais comme nous le verrons par la suite, il n’a suffit que de trois « helpers » avec accès en écriture pour implémenter tous les rootkits évoqués dans cet article.
Enfin, le noyau met à la disposition des programmes eBPF plusieurs types de stockage dans le but de simplifier la collecte de données et leur agrégation avant le retour en espace utilisateur. Nous verrons pourquoi cette fonctionnalité est elle aussi clé pour l’implémentation d’un rootkit eBPF.
1.2 Un secteur de recherche actif
La toute première mention publique de l’utilisation d’eBPF à des fins offensives remonte à la présentation « Evil eBPF Practical Abuses of In-Kernel Bytecode Runtime » [2] de Jeff Dileo pendant la conférence Defcon 27 à Las Vegas en 2019. Dans cette présentation, Jeff Dileo évoque la possibilité d’utiliser certaines fonctionnalités d’eBPF pour persister des informations et ainsi potentiellement implémenter une communication cachée entre plusieurs processus. De même, il propose d’utiliser le « helper » bpf_probe_write_user [3] pour modifier le contenu de la mémoire en espace utilisateur d’un processus. Il montre qu’il est ainsi possible de modifier la réponse du noyau à un appel système, et ce, potentiellement à des fins malveillantes. Non seulement cet « helper » est capable d'écrire un espace utilisateur, mais il n’est pas seulement limité aux pointeurs donnés à l’appel système : il est donc possible d’écrire directement sur la stack du processus. Une démonstration particulièrement impressionnante [4] de cette exploitation consiste à réécrire la stack d’un processus en espace utilisateur dans le but d’effectuer une attaque de type ROP (Return Object Programming) et ainsi de forcer un processus en espace utilisateur à exécuter du code contrôlé par l’attaquant. En d’autres termes, Jeff Dileo a montré qu’il était possible d’abuser d’eBPF à des fins malveillantes, mais il reste prudent sur la complexité d’un rootkit complet basé sur eBPF : en effet, bpf_probe_write_user ne donne accès qu’à la mémoire d’un processus en espace utilisateur, et tenter, par exemple, d’altérer discrètement une communication réseau sans provoquer d’erreur dans le programme en espace utilisateur se révèle très périlleux.
Cette première utilisation malveillante de bpf_probe_write_user pose également la question de son introduction dans le noyau : pourquoi cette fonction avait-elle été introduite, et quel était son principal objectif ? La réponse se trouve probablement dans le commentaire ajouté par son auteur lors de son ajout dans le noyau [5] : « this feature is meant for experiments », « [it should be used] to debug, divert, and manipulate execution of semi-cooperative processes ». Cette fonctionnalité avait donc principalement pour objectif d’être expérimentale. On peut néanmoins remarquer que cette fonction a été ajoutée en 2016, soit plus de 3 ans avant la première mention publique du risque de sécurité qu’elle introduit.
eBPF étant en constante évolution, une équipe de chercheurs en sécurité de Datadog a décidé de regarder ce qu’il était possible de faire, deux ans plus tard, en combinant de nouvelles fonctionnalités d’eBPF. C’est ainsi qu’à Blackhat 2021 [6] et Defcon 29 [7], nous avons présenté ebpfkit [8], un rootkit intégralement implémenté avec eBPF.
Dans un premier temps, nous voulions prouver que la modification de la mémoire utilisateur au retour d’un appel système est une option viable pour obfusquer des objets sur un système et provoquer l’exécution de code arbitraire. Que ce soit un processus ou simplement un fichier, notre rootkit est capable de cacher toute sorte de ressources, si bien qu’un implant persistant pourrait passer inaperçu pour un utilisateur non averti. D’un point de vue technique, nous avons exploité un deuxième « helper » eBPF : bpf_override_return [3]. Ce « helper » a la particularité de changer la valeur de retour d’un appel système (ou même d’empêcher son exécution). Cela nous a permis par exemple d’injecter une taille variable d’octets dans un pipe entre deux processus. Cette fonctionnalité était particulièrement utile pour altérer une commande du type « curl [mon_script_distant.sh] | bash » et ainsi provoquer l’exécution de code arbitraire, contrôlé par l’attaquant.
Notre deuxième objectif était d’explorer les nombreuses capacités réseaux d’eBPF pour implémenter une série de fonctionnalités innovantes. Par exemple, notre rootkit est capable d’usurper la communication réseau d’un serveur pour recevoir des ordres ou exfiltrer des données ; et le tout, de façon tout à fait transparente pour l’application en espace utilisateur. En effet, les programmes eBPF de type BPF_PROG_TYPE_SCHED_CLS (aussi appelés Traffic Control Classifier) ont la capacité de capturer et modifier tous les paquets réseaux entrants et sortants d’une interface ; et ce, avant (respectivement après) l’évaluation des règles de pare-feu iptables [9] pour le trafic entrant (respectivement sortant). Cela signifie qu’il est possible de modifier un paquet selon le bon vouloir de l’attaquant, sans que cela ne soit visible par l’application en espace utilisateur, et en échappant par exemple aux règles de pare-feu iptables [9] ou nftables [10]. Nous avons même montré qu’il était possible d’aller encore plus loin : un autre type de programme eBPF appelé BPF_PROG_TYPE_XDP peut être poussé directement sur l’interface réseau, ce qui fait qu’il sera exécuté avant même que le paquet n’atteigne le noyau Linux. Toute modification du paquet à ce niveau sera complètement invisible pour le noyau, et donc également invisible à tout outil de surveillance réseau en espace noyau. Les programmes de type BPF_PROG_TYPE_XDP sont également capables de retransmettre un paquet, après modification et sans même passer par le noyau. C’est en utilisant cette fonctionnalité que nous avons ainsi implémenté un scanner réseau, capable de détecter des ports ouverts sur une machine voisine, tout en garantissant qu’aucun paquet n’atteigne le noyau Linux.
Enfin, nous voulions étudier ce qu’il était possible de faire avec des programmes eBPF attachés directement sur des fonctions dans un processus en espace utilisateur. Ce type de programmes eBPF s’appelle une « uprobe », et il permet d’attacher un programme sur un symbole exporté. En nous appuyant de nouveau sur bpf_probe_write_user, nous avons ainsi montré qu’il était possible de contourner des mécanismes de défense de type RASP (Runtime application self-protection). En effet, en s’attachant aux fonctions avant et après les fonctions du RASP, il est possible d'altérer sa vision de l’application, et ainsi de cacher des entrées utilisateurs potentiellement malveillantes. Utilisant une technique similaire, il est également possible de s’attacher sur le démon Docker pour modifier à l’exécution les images exécutées dans un cluster Kubernetes. Nous avons par exemple montré qu’il était possible de prendre le contrôle du conteneur « Pause », un container utilisé par Kubernetes pour préparer les interfaces réseaux d’un « pod » sur un « nœud ».
En d’autres termes, nous avons montré que la menace n’était plus seulement théorique, et bien au contraire très concrète : écrire un rootkit avec les fonctionnalités d’ebpfkit aurait été extrêmement complexe et instable sans les outils apportés par eBPF.
1.3 Des rootkits déjà dans la nature
Deux rootkits ont récemment fait beaucoup parler d’eux parce qu’ils reposaient en partie sur eBPF pour parvenir à leurs fins : « Bvp47 » [11] et « Bpfdoor » [12].
« Bvp47 » a été publiquement divulgué par Pangu Lab, un laboratoire de chercheurs en sécurité informatique chinois. Selon leurs informations, ce rootkit serait utilisé depuis 2013 et aurait été développé par « The equation group », un groupe de pirates informatiques affiliés à la National Security Agency (NSA) américaine. Dans le rapport publié par Pangu Lab, eBPF est mentionné plusieurs fois pour indiquer qu’un programme eBPF de type BPF_PROG_TYPE_SOCKET_FILTER serait utilisé dans le but d’usurper les connexions réseaux existantes et de filtrer parmi le flux réseau les paquets destinés au rootkit. C’est en quelque sorte le même principe que celui utilisé par ebpfkit, mais avec un type de programme eBPF différent. La principale raison de l’utilisation d’eBPF dans ce rootkit était d’éviter de s’attacher directement sur des fonctions liées au réseau dans le noyau, dans le but de compliquer la tâche d’une équipe d’investigation qui chercherait à détecter la présence d’un tel programme sur une machine.
« Bpfdoor », quant à lui, a été découvert par Kevin Beaumont, un chercheur en sécurité de l’entreprise PricewaterhouseCoopers. Ce rookit aurait été observé tout au long de l’année 2021 et serait attribué à « Red Menshen », un groupe de pirates informatiques basé en Chine. Une nouvelle fois, c’est un programme eBPF de type BPF_PROG_TYPE_SOCKET_FILTER qui est utilisé par ce rookit. De même que pour « Bvp47 », le programme eBPF a pour objectif de filtrer le trafic réseau en entrée de la machine pour détecter les paquets qui sont à destination du rookit. À la différence de « Bvp47 » qui cherchait des paquets TCP ou UDP d’une taille prédéterminée, « Bpfdoor » s’intéresse à 3 protocoles : ICMP, TCP et UDP. De plus, les paquets TCP et UDP doivent présenter des valeurs spécifiques et une sorte de mot de passe pour que le filtre eBPF accepte le paquet. Quoi qu’il en soit, l’idée est une nouvelle fois d’écouter discrètement le trafic réseau sur la machine en faisant le moins de bruit possible. Même si « Bpfdoor » a été découvert en 2021, la date de création et de première utilisation de ce rootkit demeure inconnue.
La découverte et publication de ces deux rootkits pousse à se rendre compte que l’utilisation d’eBPF pour implémenter un rootkit n’est pas un sujet de recherche récent, mais une réalité vieille de bientôt 10 ans. Il y a 10 ans, eBPF n’était qu’à ses tout premiers débuts, les programmes de type BPF_PROG_TYPE_SOCKET_FILTER étaient de très loin l’objectif principal de ce sous-système du noyau, et il n’était même pas encore question d’étendre eBPF à ce qu’il est possible de faire aujourd’hui. Cela soulève donc la question de savoir si d’autres rootkits basés sur plus de fonctionnalités eBPF ne pourraient pas déjà être exploités dans la nature, sans qu’aucune équipe de chercheurs ne les ait encore découverts.
2. Comment s’en protéger ?
2.1 Configuration de Linux
Avec la forte croissance du nombre des vulnérabilités introduites dans le noyau à cause d’eBPF, les mainteneurs du noyau ont pris une série de mesures pour restreindre l’accès à certaines fonctionnalités d’eBPF et ainsi diminuer le risque posé par ce nouveau sous-système. En fonction de votre utilisation d’eBPF sur votre infrastructure, il est recommandé, dans la mesure du possible, de restreindre au maximum les fonctionnalités eBPF.
2.1.1 Désactiver l’accès non privilégié aux programmes BPF_PROG_TYPE_SOCKET_FILTER
Les programmes BPF_PROG_TYPE_SOCKET_FILTER peuvent être attachés à des sockets classiques, ce qui explique pourquoi, dans certains cas, ils peuvent être chargés dans le noyau par un utilisateur non privilégié. Le problème c’est que ce vecteur a été utilisé à de nombreuses reprises pour des attaques d’élévations de privilèges, après avoir trouvé des failles dans le « verifier » du sous-système d’eBPF (une partie du code du noyau chargée de vérifier, entre autres, que le programme eBPF n’accède pas en écriture à des zones mémoires sensibles). Sauf si votre infrastructure fait explicitement usage de cette fonctionnalité, il est recommandé de désactiver cet accès avec la commande sysctl suivante :
2.1.2 Désactiver l’appel système « bpf »
Le noyau Linux présente une série de paramètres de configuration pour sa compilation. Certains d’entre eux concernent directement le sous-système eBPF et il est ainsi possible, si vous le souhaitez, de désactiver complètement l’accès à l’appel système « bpf ». Cela empêchera ainsi toute utilisation de ce sous-système, vous protégeant de potentiels implants comme ceux décrits dans cet article. Pour cela, ajoutez la configuration CONFIG_BPF_SYSCALL=n au moment de la compilation du noyau.
Le seul problème de cette solution est qu’il vous faudra recompiler votre noyau vous-même, sachant que la majorité des distributions Linux activent ce paramètre par défaut.
Ironiquement, il existe deux autres façons de désactiver l’appel système « bpf »… en l’utilisant ! En effet, en attachant un programme de type BPF_PROG_TYPE_KPROBE sur cet appel système, il est possible d’utiliser bpf_override_return pour interrompre son exécution. Il est également possible d’utiliser un programme de type BPF_PROG_TYPE_LSM pour refuser l’accès à toute opération relative à eBPF en s’attachant aux fonctions commençant par security_bpf dans la liste des fonctions exportées par le noyau via l’interface « Linux Security Module » [19]. Néanmoins, ces deux options demandent qu’un programme en espace utilisateur charge ces programmes eBPF au démarrage de la machine, et qu’il ne soit jamais tué pendant toute la durée de fonctionnement du serveur (sans quoi le noyau supprimerait les programmes eBPF automatiquement).
2.1.3 Diminuer la surface d’attaque avec Lockdown
Depuis le noyau 5.13, il est désormais possible d’affiner ce que eBPF a le droit de faire grâce au sous-système de sécurité Lockdown [13]. Lockdown a été introduit dans le but de rendre configurable le paramétrage des outils de vérification d’intégrité du noyau. Ce nouveau module possède ainsi 3 modes : « none », « integrity » et « confidentiality ». Dans le mode « none », Lockdown n’a aucun effet et est essentiellement désactivé. Dans le mode « integrity », bpf_probe_write_user est désactivé et ne peut plus être usurpé comme montré en première partie. Dans le mode « confidentiality », Lockdown désactive les « kprobes » (un outil du noyau permettant, entre autres à eBPF, d’attacher des programmes eBPF sur les symboles du noyau), l’accès à l'appel système perf_event_open (un appel système impliqué dans la mise en place de la quasi-totalité des points d’ancrage eBPF), ainsi que tous les « helpers » eBPF permettant de lire de la mémoire noyau. En d’autres termes il devient quasiment impossible d’utiliser des programmes eBPF en mode « confidentiality ».
Contrairement à la solution précédente, celle-ci présente l’avantage de ne pas demander une recompilation du noyau : si Lockdown est présent sur votre machine, il vous sera possible de le configurer avec un utilisateur privilégié via le fichier /sys/kernel/security/lockdown. Lire ce fichier indiquera le mode de Lockdown, et il vous sera possible de le changer avec la commande suivante :
Notez que le changement de mode ne peut s’effectuer que d’un mode moins privilégié vers plus privilégié. Il est impossible de revenir à un mode moins privilégié sans un redémarrage complet de la machine.
2.2 Se protéger à l’exécution
En fonction de votre utilisation d’eBPF, il est possible qu’aucune des solutions de la première partie ne soit une option pour vous. Dans ce cas, il est recommandé de déployer un outil de surveillance de l’accès à eBPF. Ironiquement, cet outil sera très probablement basé sur eBPF.
Lors de la publication d’ebpfkit, nous avons également publié ebpfkit-monitor [14], un petit outil capable de remonter toutes les opérations « bpf » qui ont lieu sur une machine en temps réel. Il est également capable d’analyser statiquement des programmes eBPF dans le but de détecter une utilisation potentiellement malveillante d’eBPF. ebpfkit-monitor utilise donc eBPF pour surveiller l’appel système « bpf », et il est ensuite possible d’envoyer le résultat de ces opérations à outil de type SIEM (Security information and event management) pour en analyser la dangerosité.
En résumé, il y a 3 choses à surveiller :
- L’accès à des programmes eBPF inhabituels : si vous utilisez eBPF seulement pour faire du réseau, alors il n’y a aucune raison qu’un programme de surveillance système « kprobe » (par exemple) soit chargé. Inversement, si vous n’utilisez eBPF que pour récupérer des métriques d’utilisation des ressources d’une machine (I/O ou CPU par exemple), vous ne devriez jamais voir de programme eBPF de type réseau.
- Certains « helpers » eBPF sont à bannir, ils ne devraient jamais être utilisés en production : ce sont principalement bpf_probe_write_user, bpf_override_return et tous les « helpers » permettant de modifier un paquet réseau tel que bpf_skb_store_bytes (sauf si un cas d’usage précis justifie leur utilisation).
- Enfin, il est très rare de voir des programmes eBPF de type complètement différents partager des hashmaps eBPF (les unités de stockage eBPF présentées en première partie). En regardant le graphe des hashmaps et programmes eBPF d’ebpfkit [15], on voit très clairement que des hashmaps sont partagées entre des programmes de type BPF_PROG_TYPE_KPROBE et des programmes de type BPF_PROG_TYPE_SCHED_CLS. Dans notre cas, ce partage de hashmaps nous a permis d’implémenter toute la communication à distance avec le rootkit : alors que nos programmes BPF_PROG_TYPE_SCHED_CLS récupèrent et interprètent des ordres distants, ce sont nos programmes de type BPF_PROG_TYPE_KPROBE qui exécutent les ordres (comme par exemple changer le contenu d’un pipe entre « curl » et « bash »).
2.3 Détection après exploitation
Les deux premières sections couvrent les cas où vous savez que vous n’êtes pas encore infectés, et vous souhaitez vous protéger contre une potentielle tentative d’exploitation. Que faire si l’on souhaite vérifier qu’une machine est saine et qu’elle n’a pas été infectée ?
En théorie, un attaquant suffisamment motivé pourrait entièrement masquer la présence d’un rootkit eBPF, tout comme s’il avait chargé un module noyau et profondément altéré son fonctionnement. Néanmoins, c’est un exercice fastidieux et compliqué, et il est parfois possible de détecter des indices d’une potentielle exploitation (par exemple : est-il possible de charger un module noyau ? Le rootkit a peut-être décidé de l’empêcher). Malheureusement, il n’y a pas vraiment de méthode, il s’agit donc de trouver un moyen de détecter la présence d’un processus ou d’un fichier caché d’une façon à laquelle le développeur du rootkit n’aurait pas pensé.
Cela étant dit, s’il est possible de charger des modules noyaux sur votre machine, la méthode la plus simple consiste à extraire toute la mémoire du noyau pour ensuite l’analyser. Il est en effet possible d’utiliser un outil comme Volatility [16] pour détecter des programmes eBPF : deux chercheurs ont d’ailleurs présenté à Blackhat 2021 une extension de Volatility dédiée à cela [17].
Conclusion
eBPF est en quelque sorte une boîte de pandore. Ses très nombreuses fonctionnalités permettent d’implémenter des solutions de surveillance extrêmement puissantes qui vont très probablement révolutionner le développement logiciel dans les prochaines années, mais elles ont également ouvert la porte à des abus qui seront très compliqués à parer sans une drastique amélioration du contrôle d’accès à eBPF. La bonne nouvelle est qu’il y a clairement eu une prise de conscience des risques introduits par eBPF, et de nombreuses initiatives dans le noyau vont permettre de réduire la surface d’attaque. Par exemple, une nouvelle capacité noyau dédiée à eBPF (CAP_BPF) [18] a été introduite afin d’éviter de donner un accès privilégié aux services utilisant eBPF en production.
Références
[1] Lorenzo Fontana, David Calavera. « Linux Observability with BPF », O'Reilly Media, novembre 2019
[2] Jeff Dileo, « Evil eBPF Practical Abuses of In-Kernel Bytecode Runtime », Defcon 27,
https://media.defcon.org/DEF%20CON%2027/DEF%20CON%2027%20presentations/DEFCON-27-Jeff-Dileo-Evil-eBPF-In-Depth.pdf
[3] eBPF helpers, Manuel Linux, https://man7.org/linux/man-pages/man7/bpf-helpers.7.html
[4] Glipc pwn, Jeff Dileo, https://github.com/nccgroup/ebpf/tree/master/glibcpwn
[5] Ajout de bpf_probe_write_user dans le noyau Linux, https://github.com/torvalds/linux/commit/96ae5227
[6] Guillaume Fournier, Sylvain Afchain, Sylvain Baubeau, « With friends like eBPF, who needs ennemies ? », Blackhat 2021, https://www.blackhat.com/us-21/briefings/schedule/#with-friends-like-ebpf-who-needs-enemies-23619
[7] Guillaume Fournier, Sylvain Afchain, Sylvain Baubeau, « eBPF, I thought we were friends ! », Defcon 29,
https://defcon.org/html/defcon-29/dc-29-speakers.html#fournier
[8] Code source de ebpfkit, Guillaume Fournier, https://github.com/Gui774ume/ebpfkit
[9] Introduction to netfilter / iptables, lwn.net, https://lwn.net/Articles/11547/
[10] The return of nftables, Jonathan Corbet, lwn.net, https://lwn.net/Articles/564095/
[11] « Bvp47, Top-tier backdoor of US NSA Equation Group », Pangu Lab,
https://github.com/blackorbird/APT_REPORT/blob/master/EquationGroup/The_Bvp47_a_top-tier_backdoor_of_us_nsa_equation_group.en.pdf
[12] PWC Cyber Threats 2021, PricewaterhouseCoopers,
https://www.pwc.com/gx/en/issues/cybersecurity/cyber-threat-intelligence/cyber-year-in-retrospect/yir-cyber-threats-report-download.pdf
[13] Lockdown, Jonathan Corbet, lwn.net, https://lwn.net/Articles/791863/
[14] Code source de ebpfkit-monitor, Guillaume Fournier, https://github.com/Gui774ume/ebpfkit-monitor
[15] Schéma des programmes et hashmaps eBPF d’ebpfkit, Guillaume Fournier,
https://github.com/Gui774ume/ebpfkit-monitor/blob/9f7dfa7db96642a50855044a752edc504d5dc7c9/graphs/output.svg
[16] Code source de Volatility, https://github.com/volatilityfoundation/volatility
[17] Andrew Case, Golden Richard, « Fixing a Memory Forensics Blind Spot: Linux Kernel Tracing », Blackhat 2021, https://www.blackhat.com/us-21/briefings/schedule/#fixing-a-memory-forensics-blind-spot-linux-kernel-tracing-23603
[18] Introduction de CAP_BPF, Alexei Starovoitov, https://lwn.net/Articles/820560/
[19] LSM stacking and the future, Jake Edge, https://lwn.net/Articles/804906/