Détection d'actions frauduleuses avec Falco
Falco est un outil de sécurité cloud-native qui offre une protection en temps réel pour les hôtes, les conteneurs, les environnements Kubernetes et les services cloud. Il surveille les événements du noyau Linux et d'autres sources de données via des plugins, enrichissant ces événements avec des métadonnées contextuelles pour fournir des alertes en temps réel. Cela permet de détecter les comportements anormaux, les menaces potentielles et les violations de conformité.
Fonctionnalités principales de Falco¶
-
Détection des menaces en temps réel : Falco utilise eBPF pour surveiller l'activité du système et détecter les comportements malveillants sur les hôtes et les conteneurs, quelle que soit leur échelle.
-
Conformité réglementaire : Grâce à sa surveillance intelligente et à sa détection basée sur des règles, Falco aide à maintenir la conformité dans les systèmes cloud-native.
-
Intégration étendue : Les alertes de Falco peuvent être facilement transmises à plus de 50 systèmes tiers, facilitant l'analyse, le stockage ou les réactions appropriées.
-
Open Source : Développé au sein de la communauté cloud-native, Falco est une solution multi-fournisseurs largement adoptée, fonctionnant sur des architectures x64 et ARM, et déployable dans Kubernetes via un chart Helm officiel.
Drivers¶
Pour fonctionner on va devoir fournir à Falco un driver spécifique. Quand je parle de driver il faut voir derrière cela comment Falco va pouvoir collecter les informations et l'ensemble des appels système qui seront effectués. À toi de choisir ce qui correspond le mieux selon l'environnement et les restrictions que tu auras afin d'avoir l'approche la plus adaptée.
Voici un tableau récapitulatif des avantages et inconvénients des différentes méthodes de collecte des appels système pour Falco :
| Méthode | Avantages | Inconvénients |
|---|---|---|
Sonde eBPF moderne (modern_ebpf, CO-RE) | - Driver par défaut des versions récentes de Falco, embarqué dans le binaire : aucune compilation ni téléchargement de driver. - Pas de module noyau à charger, utilisable dans les environnements qui l'interdisent (GKE par exemple). - Peut tourner en mode moindre privilège (capabilities BPF, PERFMON, SYS_RESOURCE, SYS_PTRACE) au lieu d'un conteneur privileged. | - Nécessite un noyau récent (en pratique >= 5.8) exposant BTF. - Les fonctionnalités eBPF doivent être activées dans le noyau, ce qui n'est pas le cas sur tous les systèmes. |
Module du noyau (kmod) | - Solution la plus légère, avec une surcharge minimale sur le système. - Fonctionne sur des noyaux anciens qui ne supportent pas la sonde eBPF moderne. - Peut être construit, hébergé et installé directement sur le système hôte. | - Étroitement lié au noyau hôte, ce qui peut introduire de la complexité lors de changements de version du noyau, d'architecture ou de système d'exploitation. - Un module défectueux peut provoquer un plantage du noyau Linux. - Le chargement de modules noyau peut être restreint ou interdit dans certains environnements. |
Drivers retirés
La sonde eBPF « legacy » (ebpf), dépréciée depuis Falco 0.43, a été retirée : le chart Helm 9.x ne propose plus que modern_ebpf et kmod (et auto pour laisser Falco choisir). L'instrumentation en espace utilisateur via ptrace(2) n'est plus maintenue non plus.
Dans l'ordre à tester je te conseille :
- eBPF moderne (
modern_ebpf) - Module du noyau (
kmod), si ton noyau est trop ancien pour la sonde moderne
Mise en place¶
Installation du chart¶
On va passer par le Helm chart officiel. Je vais l'installer avec mon provider terraform argoproj-labs qui me permet d'utiliser ArgoCD.
Mais libre à toi, pour un use case plus simple, de le déployer via la CLI Helm : helm repo add falcosecurity https://falcosecurity.github.io/charts puis helm upgrade --install falco falcosecurity/falco -n falco --create-namespace.
resource "argocd_application" "falco" {
metadata {
name = "falco"
namespace = "argocd"
}
spec {
destination {
server = "https://kubernetes.default.svc"
namespace = kubernetes_namespace.security.metadata[0].name
}
sync_policy {
automated {
prune = false
self_heal = true
allow_empty = true
}
sync_options = ["Validate=true"]
retry {
limit = "5"
backoff {
duration = "30s"
max_duration = "2m"
factor = "2"
}
}
}
source {
repo_url = "https://falcosecurity.github.io/charts"
chart = "falco"
target_revision = "9.2.0"
helm {
release_name = "falco"
}
}
}
}
Mise en place des métriques¶
On va compléter le bloc helm {} de notre application avec ces values-ci. Les métriques seront accessibles via le webserver de Falco sur le port 8765 (http://localhost:8765/metrics après un kubectl port-forward).
values = yamlencode({
metrics = {
enabled = true
}
driver = {
kind = "modern_ebpf"
modernEbpf = {
leastPrivileged = true
}
}
falco = {
webserver = {
prometheus_metrics_enabled = true
}
}
})
À toi de gérer selon ta stack de monitoring pour récupérer les logs et/ou métriques afin de te créer ton propre système d'alertes qui t'avertissent lors de potentielles attaques.
Exemple pour trigger Falco¶
Mise en place¶
J'ai créé un simple pod que voici :
apiVersion: v1
kind: Pod
metadata:
name: alpine-pod
spec:
containers:
- name: alpine-container
image: alpine:latest
command: ["/bin/sh", "-c", "sleep 3600"]
securityContext:
runAsUser: 0
allowPrivilegeEscalation: true
restartPolicy: Never
Ici le but est d'avoir un pod qui se lance sous l'user root avec la possibilité d'acquérir des privilèges supplémentaires (su, sudo...), tels que l'ajout de capacités ou l'exécution de commandes nécessitant des privilèges élevés.
Exemple 1 : Alerte d'utilisation d'un terminal¶
On va avoir une première alerte remontée de la part de Falco, qui va me prévenir qu'un terminal a été ouvert sur un pod.
2025-01-06T14:52:30.037679658+01:00 13:29:16.039605364: Notice
A shell was spawned in a container with an attached terminal
evt_type=execve
user=root
user_uid=0
user_loginuid=-1
process=sh
proc_exepath=/bin/busybox
parent=containerd-shim
command=sh -c command -v bash >/dev/null && exec bash || exec sh
terminal=34816
exe_flags=EXE_WRITABLE|EXE_LOWER_LAYER
container_id=d857035a621a
container_image=<NA>
container_image_tag=<NA>
container_name=<NA>
k8s_ns=<NA>
k8s_pod_name=<NA>
Exemple 2 : Alerte d'exécution d'un binaire¶
Dans le terminal je vais exécuter la commande sudo touch momo.sh. Ici je veux imiter le fait de réaliser une commande sous les pleins pouvoirs avec le sudo
2025-01-06T14:02:03.338144717: Critical
Executing binary not part of base image
proc_exe=sudo
proc_sname=sh
gparent=sh
proc_exe_ino_ctime=1736173475640000634
proc_exe_ino_mtime=1733128624000000000
proc_exe_ino_ctime_duration_proc_start=18446742721407406491
proc_cwd=/
container_start_ts=1736171734240852034
evt_type=execve
user=root
user_uid=0
user_loginuid=-1
process=sudo
proc_exepath=/usr/bin/sudo
parent=sh
command=sudo touch momo.sh
terminal=34816
exe_flags=EXE_WRITABLE|EXE_UPPER_LAYER
container_id=d60da3400589
container_image=<NA>
container_image_tag=<NA>
container_name=<NA>
k8s_ns=<NA>
k8s_pod_name=<NA>
Pour situer Falco face à Tetragon, KubeArmor ou KubeHound, vois le comparatif des solutions pour sécuriser ton cluster.